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

ExpandableListViewっぽいものを独自で実装してみる

Android

ExpandableListViewの使い方覚えるが面倒で、更にカスタマイズしてみたけど開閉ボタンの消し方が分からなかったので、結局それっぽものを自作してみた。


※drawableのxmlは省略


ヘッダーのレイアウト
list_header.xml

<?xml version="1.0" encoding="utf-8"?>
<com.sample.RowHeader
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@drawable/header">
  <TextView
  	android:id="@+id/header"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:layout_gravity="center_vertical"
	android:textColor="#FFFFFFFF"
	android:textSize="20sp"/>  
</com.sample.RowHeader>

列のレイアウト
list_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@drawable/row">
  <TextView
  	android:id="@+id/row"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:layout_gravity="center_vertical"
	android:textColor="#FF000000"
	android:textSize="15sp"/>
</LinearLayout>

メイン
main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/virtual_listview"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
</LinearLayout>


ヘッダークラス
RowHeader.java

package com.sample;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

public class RowHeader extends LinearLayout {
	public boolean mIsExpanded;
	public List<View> mRows;

	public RowHeader(Context context, AttributeSet attr) {
		super(context, attr);
		mIsExpanded = false;
		mRows = new ArrayList<View>();
	}

	public boolean isExpanded() {
		return mIsExpanded;
	}
	
	public void expand() {
		mIsExpanded = true;
		for (final View v : mRows) {
			v.setVisibility(View.VISIBLE);
		}
	}
	
	public void collapse() {
		mIsExpanded = false;
		for (final View v : mRows) {
			v.setVisibility(View.GONE);
		}
	}
	
	public List<View> getRows() {
		return mRows;
	}

	public int getRowCount() {
		return mRows.size();
	}

	public void addRow(View row) {
		mRows.add(row);
	}
}

メイン

package com.sample;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {
    private Map<String, List<String>> map;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        map = new HashMap<String, List<String>>() {
        	{ put("哺乳類", new ArrayList<String>() {{ add("イヌ"); add("ネコ"); add("イルカ"); }} ); }
        	{ put("鳥類", new ArrayList<String>() {{ add("スズメ"); add("ペンギン"); }} ); }
        	{ put("魚類", new ArrayList<String>() {{ add("ブリ"); }} ); }
        };
        
        // 擬似リストビュー
        final LinearLayout listView = (LinearLayout) findViewById(R.id.virtual_listview);        
        
        for (final Entry<String, List<String>> set : map.entrySet()) {
        	// ヘッダーのレイアウトを取得してテキストを設定
        	RowHeader headerLayout = (RowHeader) View.inflate(this, R.layout.list_header, null);
        	TextView headerText = (TextView) headerLayout.findViewById(R.id.header);
        	headerText.setText(set.getKey());
        	
        	// ヘッダークリックイベント
        	headerLayout.setOnClickListener(new OnClickListener() {				
				@Override
				public void onClick(View v) {
					RowHeader headerView = (RowHeader) v;
					
					// ヘッダーが親から見て何番目にあるかを取得
					int index = listView.indexOfChild(headerView);
					
					if (headerView.getRowCount() == 0) { // 0の場合は子どもがまだ生成されていない									
						List<String> rows = set.getValue();
						for (String row : rows) {
							LinearLayout rowLayout = (LinearLayout) View.inflate(MainActivity.this, R.layout.list_row, null);
							TextView rowText = (TextView) rowLayout.findViewById(R.id.row);
							rowText.setText(row);
							// ヘッダーの次のインデックスにどんどん追加
							listView.addView(rowLayout, ++index);
							headerView.addRow(rowLayout);
						}						
					}
					
					if (headerView.isExpanded()) {
						headerView.collapse(); // 閉じる
					} else {
						headerView.expand(); // 開く
					}
				}
			});
        	listView.addView(headerLayout);
        }
    }
}

こんな感じになるよ。ヘッダーをクリックして開閉。


アニメーションがうまくつかねー



>>2011/07/25 追記


expandableListView.setGroupIndicator(null)


でインジケーター消せた<<2011/07/25