カテゴリーアーカイブ Java

asaba 著者:asaba

【androidjava】javaでhtmlタグを操作する

javaでは、Html.fromHtml(何かの変数)メソッドを使うことでhtmlタグでTextView

を操作することが出来ます。

部分的に強調したいところがあったりTextViewをリンクとして

使いたくなった時に色を変えたい時が主な用途です。

まず、sring.xmlで文字を追加します。

 

<pre><string name="sample" translatable="false">※[&lt;font color=\"navy\"&gt;%s&lt;/font&gt;]</string></pre>

 

stringタグを作った後に色を変えたい箇所を&ltと&gtで囲みます。囲まれている

$sが今回表示したい文字になります。

 

color=\”何かの色\の形式で好きな色に変えることができます。

 

続いてxml↓

 

<pre><TextView
    android:id="@+id/text_sample"
    android:layout_width="150sp"
    android:layout_height="wrap_content"
    android:layout_marginStart="10dp"
    android:layout_marginEnd="20dp"
    android:layout_marginTop="110dp"
    android:textColor="#444444"
    android:background="@drawable/selector"
    android:textSize="16sp"
    android:textStyle="bold" /></pre>

 

後にコード上で文字列を入れるのでテキストには何も設定しません。

ですがこれだけではこのまま表示されてしまうので、次にMainActivityに

実際に文字を入れていきます。

 

まず、String.formatでstring.xmlから文字を抽出しています。第一引数

が形式、第二引数が入れたい文字となっております。

次に、入れたい文字列ですが、ここではhogehogeが先ほどのstring.xmlの%sに入っていきます。

 

最後にsetTextの中でHtml.fromHtml(text)でhtmlタグを使って

 


@InjectView(R.id.text_sample)
TextView sampleText;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
ButterKnife.inject(this);

String text = String.format(getText(R.string.sample).toString(), "hogehoge");
sampleText.setText(Html.fromHtml(text));
}

 

string.xml内の文字列を翻訳して色が変われば無事終了となります。簡単

なコード数行で済むのでhtml経験者ならもっと自在に扱えそう・・・・。

でもcssなしでここまでカスタマイズできるなら上等かなぁと思います。

  • この記事いいね! (0)
asaba 著者:asaba

【javaライブラリ】picassoがどこから画像を取得したか調べる方法

画像読み込みライブラリのpicassoが便利なのは前のブログで

散々説明してきたので割愛します。

 

今回は、キャッシュした画像はどこから取ってきたかを

調べるためにPicasso.with(getApplicationContext()).setIndicatorsEnabled(true);

を使います。

 

この一行を加えるだけでpicassoがどこを通じてキャッシュしたか

分かるようになります。

例えば、ピカソの画像の左上を見ると

 

 

角の部分が色になっているの

が分かります。

 

これはメモリ経由、つまりメモリ上でキャッシュした画像を

引き出して表示しているという意味合いになります。

 

もともとはこの画像はネットワーク上から取得したのですが、picassoは取得した画像を

指定の場所にキャッシュをするので、必然的にこの画像の発生場所は

メモリ上になるということです。

 

この他にもネットワークから直接持ってきた場合は、ディスクから

持ってきた場合は色の角として表示されます。

 

出自元が分かればそこまで調べる必要はなさそうですが、ダウンロードした

画像がちゃんとキャッシュされているか確認したい場合は使う価値大ですね。

 

 

  • この記事いいね! (0)
asaba 著者:asaba

【java】Fisher-Yatesアルゴリズムで配列を闇鍋状態にする

数あるshuffle法の中で最も分かりやすいかつ速度が安定している

Fisher-Yatesアルゴリズムで値をごちゃまぜにしてみました。

どこまで値を増やしてもO(n)のままなので、速度にこだわらない

のであれば大体これ一択という流れになります。

こちらは、15個の値を順に並べ、シャッフルボタンを

押すと1から順に並んだ値とランダムで出した値を100通り

shuffleしています。

このやり方、先週ブログでも書いた文字列を判定する方法と

似ていますね。これを更に応用してランダムに1番から15番の値を

iが100に達するまで回しています。

100のところは500でも1000でもその限度まで回してくれるので

もっと回したい!というかたはお好みで。

 

<pre>public class MainActivity extends AppCompatActivity {
    int[] data = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    int[] first = new int[5];
    int[] sec = new int[5];
    int[] drawableIds;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);

        //drawableIds = new int[typedArray.length()];
    }
    @OnClick(R.id.shuffle)
    public void shuffle() {
        Random rand = new Random();
        for(int i = 0; i < 100; i++){
            for(int j =0; j < data.length; j++) {
                int temp;
                int num = rand.nextInt(data.length);
                temp = data[j];
                data[j] = data[num];
                data[num] = temp;
            }
        }
    }
}</pre>

 

更に、このままだとシャッフルしただけで何も面白くないという

ことなので、せっかくなのでカードゲームのように最初の列から

値を5個ずつ取ってみましょう。

まず、一番最初にfirstという配列にドローした値を格納しています。

このfirstはもういじることはないので、次に連続して引きたい時に

先ほど引いた5個の値を後ろに押し戻して次の5個の値を

取り出します。

同時に10列目の値群も動かさないといけないので5の倍数で

動かしていきます。

一通り入れ替えたらSystem.out.printlnをして確認してみましょう。

こちらが確認できれば組立終了です。

 


@OnClick(R.id.take)
public void draw() {
for(int d = 0; d < data.length / 3; d++){
first[d] = data[d];
}
System.out.println(Arrays.toString(first));
for(int s = 0; s < data.length / 3; s++){
int temp;
temp = data[s];
data[s] = data[s+5];
data[s+5] = data[s+10];
data[s+10] = temp;
}
System.out.println(Arrays.toString(data));
}

シャッフルクラスの説明は以上でおしまいです。

これを一つのクラスにまとめればトランプとかボウズめくりの

ための汎用クラスとして使えそうですね。

  • この記事いいね! (0)
asaba 著者:asaba

【java】StringBuilderでデータをまとめてpostで送る

StringBuilderを使ってhttpURLConnectionで好きなだけデータを

postする汎用メソッドを作りました。

 

使い方はシンプルで、ただ拡張for文を使って回すだけなので

特別な制約は無いです。

 

</pre>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

StringBuilder contentsBuilder = new StringBuilder();
Map<String, String> map = new HashMap<>();
String str = "hello!!";
double lat = 34.222222;
double longi = 137.111111;
String line = ",";
String strlati = String.valueOf(lat);
String strlong = String.valueOf(longi);
map.put("string", str);
map.put("latitude", strlati);
map.put("longitude", strlong);
for (String val : map.values()) {
if (contentsBuilder.length() > 0) {
contentsBuilder.append(line);
}
contentsBuilder.append(val);
}
}
<pre>

変数latとlongiはdoubleですが、途中でString.valueOf()で変換することで

送ることができるようになります。

 

もしサーバー側で変換したい場合は、\nとか、ごとに切り分けた後に

各値に合った型に戻してあげればいけそうですね。

 

本当はもっと簡単に書きたかったですがこの辺で妥協します。

  • この記事いいね! (0)
asaba 著者:asaba

【java】ライブラリを使わずに文字列を反転させる

入力した文字列を反転させるミニアプリを作りました。

ライブラリを使えばこんな手間なんてかからないのですが、

なんとなく生のjavaを触って反転させたいと思ったのがきっかけです。

 


public class MainActivity extends AppCompatActivity {
EditText ed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.altBtn);
ed = findViewById(R.id.mountingText);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String beforeAlterText;
beforeAlterText = ed.getText().toString();
char[] chars = beforeAlterText.toCharArray();
int i = beforeAlterText.length();
if(i % 2 == 0) {
int dev = i / 2;
for(int j = 0; j < dev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);

}else if(i % 2 == 1){
int notdev = i / 2 + 1;
for(int j = 0; j < notdev; j++){
char temp = chars[j];
chars[j] = chars[i – j – 1];
chars[i – j – 1] = temp;
}
System.out.println(chars);
}
}
});
}
}


 

最初の分岐で奇数か偶数か判別した後に入力した文字を2で割って中間地点を決めます。

この中間地点まで文字を反転させるといった感じになっています。

 

バブルソートは値の大小を判断しますがここではただの文字列

なのでそのまま文字を置き換えています。

 

文字は出てこないですがSystem.outで反転後の文字列が

確認することができます。

以上ですが見ての通り中身が何もないです。

ttsとか使って応用できればもっと面白そうなアプリが作れるかもしれません。

とりあえずソートの練習をしたいとか見てみたいとか思ったら試してみてください。

 

P.S.余談ですが、自分はこのコードの中で文字列を

退避するところをゴミ箱って呼んでます。

 

  • この記事いいね! (0)
asaba 著者:asaba

【androidjava】Bitmap初期化失敗した時に確認すること

googlemapを使う時にマーカーをカスタマイズしたい時に

bitmapを使うのですが、googlemapと併用する際は

始動時のonMapReadyの中で処理をする必要があります。

 

これは、Google Map の用意が出来た時に初めて初期化できる状態に

なるからです。

 

なのでonCreate内でbitmapを初期化

しようとするとエラー「IBitmapDescriptorFactory is not initialized」

で初期化が失敗してしまいます。

 

</pre>
@Override
public void onMapReady(GoogleMap googleMap) {

//この中でforを使いたい場合

BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(myImageList[i]);

ClusterModel offsetItem = new ClusterModel(title[i],url[i], icon);

}
<pre>

 

なんでもフィールドやonCreate内で初期化するのも

よくないということですね。

  • この記事いいね! (0)
asaba 著者:asaba

【android・googlemap】DefaultClusterRendererをオーバーライドしたカスタマイズ法

DefaultClusterRendererを継承したクラスを作ってオーバーライドして

値を変えることで自分好みのマップを作ることができます。

例えば、addmarkerを使わずにsetInfoWindowAdapterと併用して

マーカーをカスタマイズしたい時は、DefaultClusterRendererを継承した

クラスの中にonBeforeClusterItemRenderedをオーバーライドした

メソッドを書くことでマーカーのアイコンを変更することができます。

 

マーカーを変更したい時はこちらも

お忘れなく。↓

</pre>
public class ClusterModel implements ClusterItem {
private LatLng mPosition;
private String mTitle;
private String mSnippet;
private BitmapDescriptor mIcon;

//一番最後にBitmapDescriptorを追加

public ClusterModel(double lat, double lng, String title, String snippet,BitmapDescriptor icon) {
mPosition = new LatLng(lat, lng);
mTitle = title;
mSnippet = snippet;
mIcon = icon;
}

@Override
public LatLng getPosition() {
return mPosition;
}

@Override
public String getTitle() {
return mTitle;
}

@Override
public String getSnippet() {
return mSnippet;
}
public BitmapDescriptor getIcon() {
return mIcon;
}
}
<pre>

 

こちらはメインアクティビティ↓

 

</pre>
@Override
public void onMapReady(GoogleMap googleMap) {
mMap= googleMap;
//クラスターインスタンス化
mClusterManager = new ClusterManager<ClusterModel>(this, mMap);
mClusterManager.setRenderer(new MarkerRenderer(this, mMap, mClusterManager));
mClusterManager.setOnClusterClickListener(this);
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
for(int i =0; i < points.size(); i++) {
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(myImageList[i]);
ClusterModel offsetItem = new ClusterModel(pointX[i], pointY[i],title[i],url[i], icon);
mClusterManager.addItem(offsetItem);
}
}
<pre>

 

アクティビティ内に以下のクラスを追加↓

 

</pre>
private class MarkerRenderer extends DefaultClusterRenderer<ClusterModel>{
public MarkerRenderer(Context context, GoogleMap map, ClusterManager<ClusterModel> clusterManager) {
super(context, map, clusterManager);
}
@Override
protected int getColor(int clusterSize) {
return Color.rgb(0, 255, 255);
}
@Override
public void onBeforeClusterItemRendered(ClusterModel markerItem, MarkerOptions markerOptions) {
if (markerItem.getIcon() != null) {
markerOptions.icon(markerItem.getIcon());
}
markerOptions.visible(true);
}
}
<pre>

 

onBeforeClusterItemRenderedは、アイコンが出る前にrenderする(アイコンの更新

や動きを決める)役割を持ったメソッドです。

つまり、アイコンの見た目を変えたい場合はこちらをオーバーライドして

設置しておけば画像を受け取って変更してくれるという訳です。

 

addmarkerは同期してマーカーがrenderされるので遅い&容量食らうのでメモリ不足

になりがちですが、ClusterManagerと組み合わせて非同期で

renderすることで、マーカー・クラスターが増えても高速でrender

をしてくれるので多少複雑に作ってもこっちを作った方が

よさそうです。

  • この記事いいね! (0)
asaba 著者:asaba

【androidjava】Linkifyで簡単にテキストリンクを作る

androidでテキストとリンクの混合テキストを作る方法の一つに

Linkifyライブラリを使う方法があります。

 

こちらがサンプル

 

</pre>
<pre>TextView text = findById(this, R.id.sample);
text.setText(R.string.sampleText);
Linkify.addLinks(text, Linkify.ALL);

第一引数にリンクを付けたいテキスト、第二引数に

リンクとして出したい形式を渡します。

 

第二引数の形式に合ったテキストを第一引数の中から

あぶりだして該当したテキストをリンクに変換する

と覚えましょう。簡素ですが覚えましょう。

 

ここではhttps://の形式でリンクを作りたいのでallとしています。

他にも電話番号をあぶりだすPHONE_NUMBERSや住所をリンク

にできるmapaddress(こちらはすでに非推奨)がありますが、

allは全て対象に含んでくれるのでリンクを作りたいと

思ったら迷わずこれでいいと思います。

 

  • この記事いいね! (0)
asaba 著者:asaba

【androidjava】ClusterManagerでクラスターを作る

Android Utility Libraryの一つであるClusterManagerを使ってみました。

 

これを使って位置登録で地図にあふれ出たマーカーを

ズームアウトすると、周辺のマーカーを吸収してひとまとめに

して表示してくれます。

 

撮った写真を地図に逐次追加したいアプリに向いていますね。

 

追加方法は、まずClusterModelを作ります。

 

</pre>
public class ClusterModel implements ClusterItem {
private LatLng mPosition;
private String mTitle;
private String mSnippet;

public ClusterModel(double lat, double lng, String title, String snippet) {
mPosition = new LatLng(lat, lng);
mTitle = title;
mSnippet = snippet;
}

@Override
public LatLng getPosition() {
return mPosition;
}

@Override
public String getTitle() {
return mTitle;
}

@Override
public String getSnippet() {
return mSnippet;
}
}
<pre>

 

続いて表示したいアクティビティに次のように書きます。

 

</pre>
private ClusterManager<ClusterModel> mClusterManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report);
}

@Override
public void onMapReady(GoogleMap googleMap) {

mClusterManager = new ClusterManager<ClusterModel>(this, mMap);
mMap.setOnCameraIdleListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);

for(int i =0; i < points.size(); i++) {
ClusterModel offsetItem = new ClusterModel(pointX[i], pointY[i],title[i],url[i]);
mClusterManager.addItem(offsetItem);
}
}

mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
return null;
}
@Override
public View getInfoContents(Marker marker) {
View view = getLayoutInflater().inflate(R.layout.info_window, null);
TextView title = (TextView)view.findViewById(R.id.info_title);
title.setText(marker.getTitle());
ImageView imageView = (ImageView) view.findViewById(R.id.info_image);
Picasso.with(ReportActivity.this)
.load(marker.getSnippet())
.placeholder(R.drawable.sample)
.resize(200,200)
.into(imageView,new MarkerCallback(marker,marker.getSnippet(),imageView));

return view;
}
<pre>

 

ClusterModelインスタンスで定義した緯度経度・タイトル・urlを

順に出していきたいためforで回しています。

 

画像を出したい時はまたpicassoで読み込んでいきます。

 

複雑になってしまいましたがこれで晴れてクラスターを使えるように

なりました。

 

  • この記事いいね! (0)
asaba 著者:asaba

【androidjava】FusedLocationProviderについて

撮影した写真の位置情報が付いてこなかった時に現在位置を取ってきて

それを代わりに使う機能を作りました。

 

FusedLocationProviderがでるまでは、gps、wifi、電話といった受信機器

から開発者で切り分けていましたが

これを実装すると、どの機器からも処理を分岐させる

必要がなくなり楽に受信処理を書くことができます。

 

locationmanagerよりもかなり短くお手軽に書けました。

 

まず最初にパーミッションを付けましょう。他の

uses-permissionがついているところに適当にぶちこみます。

 

&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
・・・
・・・
・・・
</manifest>

リクエストを受け取る為にインスタンスを作ります。

 

 


private FusedLocationProviderClient fusedLocationClient;

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//コンストラクタはthisでok
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
getLastLocation();
}

//現在地を緯度経度の形で受け取る

private void getLastLocation() {
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(
                        this,
                        new OnSuccessListener<Location>() {
                            @Override
                            public void onSuccess(Location location) {
                                System.out.println("asaba");
                                latitude = location.getLatitude();
                                longitute = location.getLongitude();
                                latLng = new LatLng(latitude, longitute);
                                MapFragment mapFragment = (MapFragment) getFragmentManager()
                                        .findFragmentById(R.id.mapFragment);
                                mapFragment.getMapAsync(MainActivity.this);
                            }
                        });
    }

getLastLocation()で通信に成功した場合にlatitudeとlongituteを

取ってきます。

注意するべきは、MapFragmentの定義位置です。

onCreate内でこれを呼ぶと、mapFragmentがgetLastLocation()より

早く呼ばれてしまい、latLngがnullとなりアプリがクラッシュして

しまう点です。

必ず同じスコープ内で処理をしておきましょう。

latitudeとlongituteをSystem.out.println();で表示して

現在地が読み取れれば成功です。

 

リファレンスはこちら→https://developer.android.com/training/location/retrieve-current.html

  • この記事いいね! (0)