読者です 読者をやめる 読者になる 読者になる

tumblr

tumblr(タンブラー)は、メディアミックスブログサービス。ブログとミニブログ、そしてソーシャルブックマークを統合したマイクロブログサービスである。アメリカのDavidville.inc(現: Tumblr, Inc.)により2007年3月1日にサービスが開始された。

TokenAutoCompleteを使ってandroidでタグ入力

f:id:shim0mura:20160501220828p:plain

画像のようにJqueryTagItみたいなのがandroidでも使いたい。

jQuery Tag-it!

で、そういう時はTokenAutoCompleteというライブラリを使うといい。 github.com

使い方

一行xmlに追加して終わり、という感じじゃなくてちょっと使い方が面倒。色々と作成しないといけない。

セットアップ

dependencies {
    compile "com.splitwise:tokenautocomplete:2.0.7@aar"
}

android studioならばこんな感じでセットアップする。

Viewクラスを用意する

まずはタグの入力支援してくれるViewクラスは自作しないといけない。といってもTokenAutoCompleteに元となるクラスがすでに用意されているので、それを継承したクラスを作る。

public class AutoTagCompletionView extends TokenCompleteTextView<TagEntity> {
    public AutoTagCompletionView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected View getViewForObject(TagEntity tag) {

        LayoutInflater l = (LayoutInflater)getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        LinearLayout view = (LinearLayout)l.inflate(R.layout.tag_comp, (ViewGroup) AutoTagCompletionView.this.getParent(), false);
        ((TextView)view.findViewById(R.id.name)).setText(tag.getName());

        return view;
    }

    @Override
    protected TagEntity defaultObject(String completionText) {
        TagEntity tag = new TagEntity();
        tag.setName(completionText);
        return tag;
    }
}

getViewForObjectはオートコンプリートでタグ候補表示をするときのViewを展開するもの。なのでタグ候補表示するためのレイアウトファイルもいる。 defaultObjectはタグ入力した時、AutoTagCompletionView(クラス名はなんでもいい)からタグオブジェクトを取得するためのメソッド

候補表示レイアウト

これは別にListViewなんかでデフォルトで使われてるsimple_list_item1とか使いまわしてもOK。とりあえず公式に合わせたものを適当に作っておく。

R.layout.tag_comp

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content">

    <TextView android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/token_background"
        android:padding="5dp"
        android:textColor="@android:color/white"
        android:textSize="18sp" />

</LinearLayout>

タグエンティティを作る

これも適当に自分で好きなように作る。公式ではPeopleクラスを作っていたけど、今回はTagEntityクラスを作ってみる。

public class TagEntity implements Serializable {

    public String name;

    public TagEntity(){}

    public TagEntity(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String toString(){
        return name;
    }

}

これで準備完了。

アクティビティに組み込む

さっき作った自作のViewクラス(今回はAutoTagCompletionView)をActivityのxmlに入れる。

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="タグ"/>
        <shim0mura.testtag.view.AutoTagCompletionView
            android:id="@+id/tag"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

あとはActivity側での処理。表示させたいタグを一気に作って、ArrayAdapterに渡せばOK。

public class TokenAutoCompActivity extends AppCompatActivity {

    private AutoTagCompletionView completionView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_token_auto_comp);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        TagEntity tags[] = new TagEntity[]{
                new TagEntity("android"),
                new TagEntity("rails"),
                new TagEntity("ruby")
        };

        ArrayAdapter<TagEntity> adapter = new ArrayAdapter<TagEntity>(this, android.R.layout.simple_list_item_1, tags);

        completionView = (AutoTagCompletionView)findViewById(R.id.tag);
        completionView.setAdapter(adapter);
    }


}

これで完成。エミュレータで表示させてみるとこんな感じ。

f:id:shim0mura:20160501222827p:plain

android」のanを入力すると候補のタグが表示される。この候補のレイアウトがこの記事で書いてるところのR.layout.tag_comp。で、その候補をタップすると、

f:id:shim0mura:20160501223033p:plain

いい感じにタグっぽく入力できた。

オプションで色々できる

タグのサジェスト自体はArrayAdapterに渡したタグしかしてくれないけど、そうではないタグも自分で入力できる。カンマ区切りやEnterなどの決定ボタンで独自のタグも入力可能。ただし、デフォルトはカンマ区切りなので、半角スペースとか全角スペース区切りにも対応したい。そういう場合はsetSplitChar(' ')としてやればOK。

completionView.setSplitChar(' ');

が、これだと半角スペースしか対応しなくなって今度は逆にカンマ区切りに対応しなくなるので、以下のように複数の区切り文字を定義してからセットするといいっぽい。

char[] splitChar = {',', ';', ' '};
completionView.setSplitChar(splitChar);

あとはタグ候補を表示する閾値も設定できる。デフォルトでは2文字以上入力された時、たとえば今回のようなタグであれば「ru」と入力したところで「ruby」というタグ候補が出てくる。「r」とだけ入力した時に、「ruby」と「rails」のタグ候補が出て欲しい場合、つまり閾値が1文字にしたい場合は以下のようにする。

completionView.setThreshold(1);

こうすると

f:id:shim0mura:20160501224016p:plain

こんな感じで両方とも出てきてくれる。 公式のサンプルはgmailのようにメールアドレスの補完とメールアドレスからのPeopleオブジェクトの取得とかやってるし、使い方次第で結構幅が出てきて面白い。