Androidでタグクラウドを実装する(ソースコード付き)

このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをFC2ブックマークに追加このエントリをNifty Clipに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをChoixに追加このエントリをnewsingに追加

Android開発を行っていて、意外にもライブラリなどが存在しなかったのがタグクラウドです。まぁ、見つからないなら自分で作ってしまえ、という考えで下の画像のようなタグクラウドをちょっと実装してみました。なので、そのTagCroudクラスとそれを利用するために必要なTagクラスの2つをここに公開します。自分自身Javaにはあまり強くないことと、Androidアプリ開発を始めてまだ間もないということからおかしな実装をしている部分もあるかと思いますが、その場合にはコメントにてお知らせいただくか、twitter(@1987yama3)までご連絡ください。

tagCroud

Tagクラス

タグクラスはタグ(語句とその出現数)を格納することが主な役割です。また、これに加えてタグクラウド上でタグをクリック(タップ)した際の挙動をここに記述できるようにしています。具体的には、クリック時には、タグクラス内のIntent型のメンバ変数intentを引数としてインテントを発行します。タグクラスのメンバ変数(語句、出現数、インテント)はSetメソッドによりセットすることができます。

ソースコード

ソースコードを以下に記します。また、ソースコードは記事末尾のリンクからダウンロードすることが可能ですので、ソースコードの利用にはそちらをご利用ください。

import android.content.Intent;
public class Tag {
    /** タグに表示される文字列 */
    private String word;

    /** タグの重要度 */
    private int    count;

    /** タグがクリックされた際に発行するインテント */
    private Intent intent = new Intent();

    /**
     * コンストラクタ
     */
    public Tag( String _word, int _count, Intent _intent ) {
        Set( _word, _count, _intent );
    }

    public Tag( String _word, int _count ) {
        Set( _word, _count );
    }

    public Tag( String _word ) {
        Set( _word );
    }

    public Tag( String _word, Intent _intent ) {
        Set( _word, _intent );
    }

    /**
     * 重要度を増やすためのメソッド
     */
    public void CountUp() {
        this.CountUp(1);
    }

    public void CountUp( int c ) {
        this.Set( this.getCount() + c );
    }

    /**
     * セッター
     */
    public void Set(String _word) {
        this.word = _word;
    }

    public void Set(int _count) {
        this.count = _count;
    }

    public void Set( Intent _intent ) {
        intent = _intent;
    }

    public void Set( String _word, int _count ) {
        Set( _word );
        Set( _count );
    }

    public void Set( String _word, Intent _intent ) {
        Set( _word );
        Set( _intent );
    }

    public void Set( String _word, int _count, Intent _intent ) {
        Set( _word );
        Set( _count );
        Set( _intent );
    }

    /**
     * ゲッター
     */
    public Intent getIntent() {
        return intent;
    }

    public String getWord() {
        return word;
    }

    public int getCount() {
        return count;
    }

}

TagCroudクラス

TagCroudクラスはLinearLayoutクラスを継承したクラスです。継承元がLinearLayoutクラスということが正しい判断であるかどうかは分からないのですが、とりあえず上手く動いているので良しとします。(ってこんなんでいいのかな?)

TagCroudクラスで設定可能な項目は、タグの文字の色とタグがクリック可能であるかどうか、それに加え、表示するタグの追加です。タグの削除はできません。実装ミスではなく仕様ですw。addメソッドにより、tagを追加することができます。そして、tagを追加し終わって、タグクラウドを描くタイミングになれば、Drawメソッドを実行です。Drawメソッド内では、タグクラウドの持つtagの出現数を元にタグの重み付けを1から10の10段階で行います。このタグの重みを元に、タグクラウドで表示される文字の大きさが決定されます。最後に描画処理ですが、これは自分自身が以前に大学のゼミでも発表した箱詰め問題の近似アルゴリズム(NF, Next Fit)を用いて実装しています。こんなところで、ゼミでの学習内容が生かされるとは、という感じですね。

ソースコード

ソースコードを以下に記します。また、ソースコードは記事末尾のリンクからダウンロードすることが可能ですので、ソースコードの利用にはそちらをご利用ください。

package yama3.biz.BookList;

import java.util.ArrayList;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

public class TagCroud extends LinearLayout {
    /** Viewのサイズ */
    private int                 width;
    private int                 height;

    /** 表示するtagのリスト */
    protected ArrayList<Tag>    element = new ArrayList<Tag>();

    /** 呼び出されたアクティビティ */
    private static Context      context;

    /** タグの文字の色 */
    private int                 TextColor;

    /** タグはクリック可能かどうか */
    private boolean             tagClickable;

    /**
     * コンストラクタ
     * @param _context
     */
    public TagCroud(Context _context) {
        super(_context);
        context = _context;
        this.setOrientation( LinearLayout.VERTICAL );
        this.TextColor = Color.argb( 255, 255, 255, 255 );    // テキストの色の初期値は白
        tagClickable = false;
        width = 320;
    }

    public void Draw() {
        Button btn;
        int i;
        int twidth = 0;
        ArrayList<Integer> weight = setWeight();
        for( i=-1; i+1<size(); i++ ) {
            LinearLayout layout2 = new LinearLayout( context );
            layout2.setOrientation( LinearLayout.HORIZONTAL );
            addView( layout2, new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT,
                                                             LayoutParams.WRAP_CONTENT ) );
            twidth = 0;
            while( twidth <= 320 && i+1<size() ) {
                btn = new Button( context );
                btn.setText( element.get(i+1).getWord() );
                btn.setTextSize( 5.0f*weight.get(i+1)+5.0f );
                btn.setBackgroundColor( Color.argb( 0, 0, 0, 0 ) );
                btn.setTextColor( TextColor );
                twidth += btn.getTextSize() * btn.length() + 10;
                if( twidth >= 320 ) {
                    break;
                } else {
                    i++;
                    btn.setPadding( 5, 0, 5, 0 );
                    btn.setClickable( isClickable() );
                    btn.setId( i );
                    if( isClickable() ) {
                        btn.setOnClickListener( new OnClickListener() {
                            public void onClick(View v) {
                                int id = v.getId();
                                TagCroud.context.startActivity(element.get(id).getIntent() );
                            }
                        });
                    }
                    layout2.addView( btn, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT,
                                                                         LayoutParams.WRAP_CONTENT ) );
                }
            }
        }
    }

    /**
     * 各タグの重みを計算する。重みは、1~10の10段階とする。
     * @return
     */
    private ArrayList<Integer> setWeight() {
        ArrayList<Integer> weight = new ArrayList();
        int max = 0;
        for( int i=0; i<size(); i++ ) {
            if( max <= element.get(i).getCount() ) {
                max = element.get(i).getCount();
            }
        }

        for( int i=0; i<size(); i++ ) {
            int w = (int)( (10*element.get(i).getCount()/max) );
            weight.add( w );
        }
        return weight;
    }

    /**
     * ビューのサイズが変更された際に呼び出される
     */
    protected void onSizeChanged(int w, int h, int oldw, int oldh){
        width = w;
        height = h;
    }

    public int width() {
        return width;
    }

    public int height() {
        return height;
    }

    /**
     * タグを追加する
     * @param t
     */
    public void add( Tag t ) {
        int idx = exist(t.getWord());
        if( idx != -1 ) {
            element.get(idx).CountUp(t.getCount());
        } else {
            element.add( new Tag( t.getWord(), t.getCount(), t.getIntent() ) );
        }
    }

    public void add( Tag t, Intent intent ) {
        int idx = exist(t.getWord());
        if( idx != -1 ) {
            element.get(idx).CountUp(t.getCount());
        } else {
            element.add( new Tag( t.getWord(), t.getCount(), intent ) );
        }
    }

    /**
     * タグクラウド内に存在するタグの数を取得する
     * @return
     */
    public int size() {
        return element.size();
    }

    /**
     * 指定されたWordの挿入されている数を取得する
     * @param word
     * @return
     */
    public int GetCount( String word ) {
        int idx = exist( word );
        if( idx != 0 ) {
            return element.get(idx).getCount();
        } else {
            return 0;
        }
    }

    /**
     * 指定されたWordの重み(1~10)を取得する
     * @param word
     * @return
     */
    public int GetWeight( String word ) {
        ArrayList<Integer> weight = setWeight();
        int pos = exist( word );
        return weight.get(pos);
    }

    /**
     * 指定されたwordを持つTagをリストに含んでいればそのインデックスを、
     * 含んでいなければ、-1を返す。
     * @param word
     * @return
     */
    private int exist( String word ) {
        int k = element.size();
        for( int i=0; i<k; i++ ) {
            if( element.get(i).getWord().equals(word) ) {
                return i;
            }
        }
        return -1;
    }

    /**
     * セッター、ゲッターの定義
     *     public void    setTextColor( int )
     *     public int     getTextColor()
     *     public void    setClickable( boolean )
     *     public boolean isClickable()
     */
    public void setTextColor( int c ) {
        this.TextColor = c;
    }

    public int getTextColor() {
        return this.TextColor;
    }

    public void setClickable( boolean bool ) {
        this.tagClickable = bool;
    }

    public boolean isClickable() {
        return this.tagClickable;
    }

}

ダウンロード

関連記事

人気ブログランキングへ

[PR]

トラックバック

http://yamablo.com/2009/12/13-112411.php/trackback

コメント


Get Adobe Flash playerPlugin by wpburn.com wordpress themes