LoginSignup
14
12

More than 5 years have passed since last update.

マルチヒエラルキーなExpandableListView

Posted at

AndroidのExpandableListView(以下ExLV)はルート階層のアイテムはすべて親になりますが、展開できるアイテムと、通常のListView的なアイテムを共存させるようにしてみました。

準備

ExLVに渡す子のモデルクラスを作ります。下のコードでは名前しか無いですが、クリックされた時の処理のためにRunnableやら他のインスタンスやらを渡しておいて、機能を付け足してください。

Element.java
public class Element
{

    private String name;
    private ArrayList<Element> children = new ArrayList<Element>();

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

    public String getName()
    {
        return name;
    }

    public boolean isParent()
    {
        return children.size() > 0;
    }

    public List<Element> getChildren()
    {
        return children;
    }

    public void addChild(Element element)
    {
        children.add(element);
    }
}

Viewの生成

今回はインラインで生成します。XMLでも同じ事できると思います

ArrayList<Element> elements = new ArrayList<Element>();
// elementsを仕込む
ExpandableListView listview = new ExpandableListView(activity);
listview.setGroupIndicator(getResource().getDrawable(android.R.color.transparent));
MyExpandListAdapter adapter = new MyExpandListAdapter(activity, elements);

listview.setGroupIndicator(getResource().getDrawable(android.R.color.transparent));で、

とか V みたいなインジケータを消しています。これ重要。展開できるできないにかかわらずExLVはすべてのトップアイテムにインジケータを最後に上書きするので、Inflaterだけで普通のアイテムぽくしようとしてもダメです。

Adapterを作る

肝心要のAdapterです。BaseExpandableListAdapterを継承して作ります。

MyExpandListAdapter.java
public class MyExpandListAdapter extends BaseExpandableListAdapter
{

    private List<Element> elements;
    private Activity activity;
    private LayoutInflater inflater;

    public MyExpandListAdapter(Activity activity, List<Element> elements)
    {
        this.activity = activity;
        this.elements = new ArrayList<Element>(elements);
        this.inflater = activity.getLayoutInflater();
    }

    @Override
    public Object getChild(int arg0, int arg1)
    {
        return elements.get(arg0).getChildren().get(arg1);
    }

    @Override
    public long getChildId(int arg0, int arg1)
    {
        return arg1;
    }

    @Override
    public View getChildView(int arg0, int arg1, boolean arg2, View view, ViewGroup arg4)
    {
         /**
        * 子アイテムの描画
         */
        return view;
    }

    @Override
    public int getChildrenCount(int arg0)
    {
        return elements.get(arg0).getChildren().size();
    }

    @Override
    public Object getGroup(int arg0)
    {
        return elements.get(arg0);
    }

    @Override
    public int getGroupCount()
    {
        return elements.size();
    }

    @Override
    public long getGroupId(int arg0)
    {
        return arg0;
    }

    @Override
    public View getGroupView(int arg0, boolean isExpanded, View view, ViewGroup parent)
    {
        Element element = elements.get(arg0);
        if(element.isParent())
        {
            view = inflater.inflate(R.layout.parent, null);
            TextView textView = (TextView) view.findViewById(R.id.parent_name);
            textView.setText(element.getName());
            ImageView indicator = (ImageView) view.findViewById(R.id.parent_indicator);
            indicator.setImageResource(isExpanded ? R.drawable.expand_open : R.drawable.expand_close);
        }
        else
        {
             /**
             * 子アイテムの描画
            */
        }

        return view;
    }

    @Override
    public boolean hasStableIds()
    {
        return true;
    }

    @Override
    public boolean isChildSelectable(int arg0, int arg1)
    {
        return true;
    }
}

getGroupViewの中で、ElementがisParentかどうかで描画処理を変えています。
子の場合はgetChildViewと全く同じ処理で構いません。親の場合は、予め親用のレイアウト(今回はR.layout.parent)を作っておいて、その中にインジケータの代わりになるImageViewを置いておきます。そんで引数のisExpandedで用いる画像(Drawable)を切り替えれば完成です。
親にインジケータ表示が要らないという方はこの辺りはばっさりカットで、単に親用に描画すればいいだけです。

stackoverflowとかいろいろめぐった結果この実装が一番簡単かなという感じです。
最初からカスタムViewでゴリゴリっと作ってしまえる方はぜひそうして、そんでもってライブラリ配布してくださいお願いします(他力本願)

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12