2013年7月23日火曜日

SimpleExpandableListAdapter

SimpleExpandableListAdapter

Adapter系のクラスを使うメリットは、データ群を一括して取り扱えることだ。
例えば、SimpleAdapterの場合、文字列群と画像群と、そしてそれら以外のデータ(例えば、自分で作成した任意のクラス等)をも、一括して、対応するView(例えば、TextViewやImageView等)に代入することができた。

(参考)SimpleAdapterの簡単すぎる基本形
    String sFrom[] = {"Bitmap", "Title"};
    int iTo[] = new int[]{
        R.id.Image_List_Favorite,
   R.id.Text_List_Favorite_Title
    };
      sa = new SimpleAdapter(mainActivity, al, R.layout.list_keyword, sFrom, iTo);
上記は、"Bitmap"と命名した画像データを、R.id.Image_List_FavoriteというImageViewに代入&表示する。

しかし、SimpleExpandableListAdapterの場合、一括して代入できるのは文字列データだけである。画像データはできないし、それ以外のデータもできない。仕様です。

画像データを、対応するImageViewに代入する場合、それ用のプログラムをしなければならない。
また、ChildViewに、例えばButtonを配置した場合、そのButtonに対する利用者からのクリック状況の把握の仕方もプログラムしなければならない。

サンプルプログラムは下記のとおりです。

    String sFrom[] = {"Title"};
    int iTo[] = new int[]{
        R.id.Text_List_Favorite_Title//自動的に代入できるのは、文字列データだけである。画像データを取り扱うことはできない。
    };
    private ExpandableListView lv;
    private MySA sa;
    private ArrayList<ArrayList<Map<String, Object>>> ChildrenList;
 
    /* 画像データを表示させ、かつ、ChildViewにButtonを実装させるため、
    SimpleExpandableListAdapterを拡張して使う。
    */
    class MySA extends SimpleExpandableListAdapter{
        /*
         * constructorは、Eclipseが自動生成したものをそのまま使う。
         * constructorは、ごちゃごちゃしているが、何も問題は無い。見ないでおこう。
         */
        public MySA(Context context,
                List<? extends Map<String, ?>> groupData, int groupLayout,
                String[] groupFrom, int[] groupTo,
                List<? extends List<? extends Map<String, ?>>> childData,
                int childLayout, String[] childFrom, int[] childTo) {
            super(context, groupData, groupLayout, groupFrom, groupTo, childData,
            childLayout, childFrom, childTo);
        }

    /*以下はプログラミングする箇所である。*/
        @Override
        public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

            View v = super.getChildView(groupPosition, childPosition, isLastChild,
                convertView, parent);
            /*
             * superによる処理が終わった後のViewを使うこと。
    super内で文字列の代入が行われているのである。
             * 以下は、ImageViewへ画像を代入する処理である。
    つまり、文字列データの処理を先にしてから画像データの処理を行う。
             */
            RelativeLayout rl = (RelativeLayout)v;//私のPGではRelativeLayoutである
            ImageView iv = (ImageView)rl.findViewById(R.id.Image_List_Favorite);
            Map<String, Object> m = ChildrenList.get(groupPosition).get(childPosition);
            Bitmap bm = (Bitmap)m.get("Bitmap");
            iv.setImageBitmap(bm);
            
            /*
             * 下記newChildView()においてButtonにリスナーを付けクリックイベントを捕捉できるようにする。しかし、それだけでは個々のButtonを識別できない。
このため、識別できるようにするため、次のようにタグを付ける。
             */
            Button btn = (Button)rl.findViewById(R.id.Button_List_Favorite);
            long l = ExpandableListView.getPackedPositionForChild(
                    groupPosition, childPosition);
            btn.setTag(l);
            return v;
        }

        /*
         * 次のnewChildView()は、上記getChildView()のsuper.getChildView()内において、
         * アプリ開始時にChildViewが新規に生成する時に呼ばれる。
         * 一定数のChildViewを生成し終えたら、もはや生成されることはない。
         * 生成後の処理は、getChildView()で行うことになる。
         * layout用xmlにおいてViewを書いてあるので、基本的にはnewChildView()をイジル必要は無い。
         */
        @Override
        public View newChildView(boolean isLastChild, ViewGroup parent) {
            View v = super.newChildView(isLastChild, parent);
            RelativeLayout rl = (RelativeLayout)v;//私のPGではRelativeLayoutである
            Button btn = (Button)rl.findViewById(R.id.Button_List_Favorite);
            btn.setOnClickListener(FavoriteView.this);
            return v;
        }
    }
    //以上が、SimpleExpandableListAdapterの拡張クラスでした。

    public 自分のメソッド(){
        
        lv = (ExpandableListView)****.findViewById(R.id.ListFavorite);
       
        ArrayList<Map<String, String>> parentList = new ArrayList<Map<String, String>>();
        ArrayList<String> als = Group用文字列データ群を取得する。
        for(String s : als){
            Map<String, String> m = new HashMap<String, String>();
            m.put("Parent_Text", s);
            parentList.add(m);
        }
        
        ChildrenList = Child用文字列データ群を取得する。
        
        sa = new MySA(
            ****,

            //Group用文字列データ群の代入
            parentList,//データそのもの
            android.R.layout.simple_expandable_list_item_1,
            new String[]{"Parent_Text"},//入力
            new int[]{android.R.id.text1},//出力

            //Child用文字列データ群の代入
            ChildrenList,//データそのもの
            R.layout.list_favorite,//layout用xmlファイル
            sFrom,//入力
            iTo//出力
        );
        
        lv.setAdapter(sa);
        lv.setOnChildClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
        if(v.getId()==R.id.Button_List_Favorite){
        //サンプルなので、ログを表示するだけです。
        //任意のChild内に表示されたボタンが押されたことを取得します。
            Button btn = (Button)v;
            long l = (Long)btn.getTag();
            int iG = ExpandableListView.getPackedPositionGroup(l);
            int iC = ExpandableListView.getPackedPositionChild(l);
if(BuildConfig.DEBUG) Log.d(TAG, "onClick(). " + iG + ". " + iC);
            return;
        }
    }

    @Override
    public boolean onChildClick(ExpandableListView arg0, View v, int iG, int iC, long arg4) {
        //サンプルなので、ログを表示するだけです。
        //任意のChildが押されたことを取得します。
if(BuildConfig.DEBUG) Log.d(TAG, "onChildClick(). " + iG + ". " + iC);
        return false;
    }


以下は、ChildViewのlayout用xmlファイルであり、ファイル名はR.layout.list_favorite.xmlです。
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <Button
        android:id="@+id/Button_List_Favorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:drawableLeft="@android:drawable/ic_menu_edit"
        android:focusable="false"
        >
    </Button>
    <ImageView
        android:id="@+id/Image_List_Favorite"
        android:contentDescription="@string/app_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        >
    </ImageView>
    <TextView
        android:id="@+id/Text_List_Favorite_Title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:layout_toRightOf="@id/Image_List_Favorite"
        android:layout_toLeftOf="@id/Button_List_Favorite"
        android:layout_alignBottom="@id/Image_List_Favorite"
        android:focusable="false"
        >
    </TextView>
</RelativeLayout>

0 件のコメント:

コメントを投稿