ExpandableListView 예제

|

Android에서 다음 그림과 같이 Depth가 존재하는 ListView를 만들고 싶을 때는 어떻게 해야 할까요? 여러 가지 방법이 있긴 한데, 가장 간편하게 만들 수 있는 방법으로는 ExpandableListView를 사용하는 방법이 있습니다. 이 UI 컴포넌트는 Android SDK에 기본으로 포함되어 있습니다.

image

위와 같은 화면을 구현하려면 크게 다음과 같은 요소들을 구현해주면 됩니다.

  • 첫 번째 Depth의 ItemView
  • 두 번째 Depth의 ItemView
  • ExpandableListView의 Adapter


item_view_setting_parent.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/layout_background"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="15dp"
  android:orientation="horizontal">

  <ImageView
    android:id="@+id/icon"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_marginLeft="16dp"
    android:src="@mipmap/ic_launcher" />

  <TextView
    android:id="@+id/name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="16dp"
    android:layout_gravity="center"
    android:text="name"
    android:textColor="@color/black"
    android:textSize="22sp" />

</LinearLayout>


item_view_setting_child.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/layout_background"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="15dp"
  android:orientation="horizontal">

  <TextView
    android:id="@+id/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="80dp"
    android:layout_gravity="center"
    android:text="name"
    android:textColor="@color/black"
    android:textSize="18sp" />

  <Switch
    android:id="@+id/data_switch"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginRight="18dp"
    android:layout_gravity="right"
    android:checked="true" />

</LinearLayout>


fragment_device_setting.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="false">

  <android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/background"
    android:fitsSystemWindows="true">

    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content">

      <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:layout_centerInParent="true"
        android:text="Device Setting"
        android:textColor="@color/white"
        android:textSize="24sp" />

    </RelativeLayout>

  </android.support.design.widget.AppBarLayout>

  <ExpandableListView
    android:id="@+id/expandable_listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:groupIndicator="@null"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>


DeviceSettingExpandableAdapter.java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;

public class DeviceSettingExpandableAdapter extends BaseExpandableListAdapter {

  private Context mContext;
  private ArrayList mParentList;
  private HashMap<String, ArrayList> mChildHashMap;

  public DeviceSettingExpandableAdapter(Context context) {
    this.mContext = context;

    initList();
  }

  private void initList() {
    mParentList = new ArrayList<>();
    mParentList.add(
        new SettingParentItem(SettingParentItem.KEY_MYPHONE,
            R.drawable.icon_setting_myphone, "My Phone"));
    mParentList.add(
        new SettingParentItem(SettingParentItem.KEY_SHEALTH,
            R.drawable.icon_setting_shealth, "SHealth"));

    mChildHashMap = new HashMap<>();

    ArrayList childList = new ArrayList<>();
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_MYPHONE_APP_USAGE,
        "앱 사용 시간", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_MYPHONE_LOCATION,
        "위치 정보", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_MYPHONE_ACTIVITY,
        "액티비티 정보", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_MYPHONE_WEATHER,
        "날씨", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_MYPHONE_EVENT,
        "스마트폰 이벤트", ""));
    mChildHashMap.put(mParentList.get(0).key + "", childList);

    childList = new ArrayList<>();
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_SHEALTH_STEP_COUNT,
        "걸음 수", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_SHEALTH_SLEEP,
        "수면 정보", ""));
    childList.add(new SettingChildItem(DEVICE_DATA_TYPE.TYPE_SHEALTH_HEART_RATE,
        "심박수", ""));
    mChildHashMap.put(mParentList.get(1).key + "", childList);
  }

  @Override
  public String getGroup(int groupPosition) {
    return mParentList.get(groupPosition).key + "";
  }

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

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

  // ParentListView
  @Override
  public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
      ViewGroup parent) {
    ParentItemHolder holder = null;
    View row = convertView;

    if(row == null) {
      LayoutInflater inflator = (LayoutInflater) mContext
          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      row = inflator.inflate(R.layout.item_view_setting_parent, null);

      holder = new ParentItemHolder();

      holder.icon = (ImageView) row.findViewById(R.id.icon);
      holder.name = (TextView) row.findViewById(R.id.name);

      row.setTag(holder);
    } else {
      holder = (ParentItemHolder) row.getTag();
    }

    final SettingParentItem item = mParentList.get(groupPosition);
    if(item != null) {
      holder.icon.setImageResource(item.resId);
      holder.name.setText(item.name);
    }

    return row;
  }

  //ChildListView
  @Override
  public SettingChildItem getChild(int groupPosition, int childPosition) {
    return this.mChildHashMap.get(this.mParentList.get(groupPosition).key + "")
        .get(childPosition);

  }

  @Override
  public int getChildrenCount(int groupPosition) {
    return this.mChildHashMap.get(this.mParentList.get(groupPosition).key + "")
        .size();

  }

  @Override
  public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
  }

  @Override
  public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
      View convertView, ViewGroup parent) {
    ChildItemHolder holder = null;
    View row = convertView;

    if(row == null) {
      LayoutInflater inflator = (LayoutInflater) mContext
          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      row = inflator.inflate(R.layout.item_view_setting_child, null);

      holder = new ChildItemHolder();

      holder.name = (TextView) row.findViewById(R.id.name);

      row.setTag(holder);
    } else {
      holder = (ChildItemHolder) row.getTag();
    }

    SettingChildItem item = getChild(groupPosition, childPosition);

    if(item != null) {
      holder.name.setText(item.name);
    }

    return row;
  }

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

  @Override
  public boolean isChildSelectable(int groupPosition, int childPosition) { return true; }


  class ParentItemHolder {

    ImageView icon;
    TextView name;
  }

  ;

  class ChildItemHolder {

    TextView name;
    Switch _switch;
  }

  ;
}
</pre>