본문 바로가기

Android/Listview

안드로이드/Android ExpandableListView 만들기

안드로이드/Android ExpandableListView 만들기


안드로이드에서 ListView는 많이들 써보셨을 텐데요. ListView안에 또다른 List가 들어있는 ExpandableListView라는 녀석이 존재 합니다. 기본적으로 ListView를 상속받아 구현한 클래스기 때문에 ListView의 속성과 거의 유사하다고 생각 하시면 됩니다.


생각하실것은 기존의 ListView는 getView하나로 Row를 만들고 사용하였는데 ExpandableListView는 Group 과 Child 의 getView를 각각 구현해 준다는 점만 기억하시면 만드시는데는 큰 문제가 없을 거라고 생각합니다.


자 그럼, ExpandableListView 의 예제를 살펴 보겠습니다.


public class TestExpandableListViewActivity extends Activity {

	private ArrayList mGroupList = null;
	private ArrayList> mChildList = null;
	private ArrayList mChildListContent = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		setLayout();

		mGroupList = new ArrayList();
		mChildList = new ArrayList>();
		mChildListContent = new ArrayList();

		mGroupList.add("가위");
		mGroupList.add("바위");
		mGroupList.add("보");

		mChildListContent.add("1");
		mChildListContent.add("2");
		mChildListContent.add("3");

		mChildList.add(mChildListContent);
		mChildList.add(mChildListContent);
		mChildList.add(mChildListContent);

		mListView.setAdapter(new BaseExpandableAdapter(this, mGroupList, mChildList));
		
		// 그룹 클릭 했을 경우 이벤트
		mListView.setOnGroupClickListener(new OnGroupClickListener() {
			@Override
			public boolean onGroupClick(ExpandableListView parent, View v,
					int groupPosition, long id) {
				Toast.makeText(getApplicationContext(), "g click = " + groupPosition, 
						Toast.LENGTH_SHORT).show();
				return false;
			}
		});
		
		// 차일드 클릭 했을 경우 이벤트
		mListView.setOnChildClickListener(new OnChildClickListener() {
			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				Toast.makeText(getApplicationContext(), "c click = " + childPosition, 
						Toast.LENGTH_SHORT).show();
				return false;
			}
		});
		
		// 그룹이 닫힐 경우 이벤트
		mListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
			@Override
			public void onGroupCollapse(int groupPosition) {
				Toast.makeText(getApplicationContext(), "g Collapse = " + groupPosition, 
						Toast.LENGTH_SHORT).show();
			}
		});
		
		// 그룹이 열릴 경우 이벤트
		mListView.setOnGroupExpandListener(new OnGroupExpandListener() {
			@Override
			public void onGroupExpand(int groupPosition) {
				Toast.makeText(getApplicationContext(), "g Expand = " + groupPosition, 
						Toast.LENGTH_SHORT).show();
			}
		});
	}

	/*
	 * Layout
	 */
	private ExpandableListView mListView;

	private void setLayout(){
		mListView = (ExpandableListView) findViewById(R.id.elv_list);
	}
}
//


자 그럼 Adapter 코드도 한번 살펴 보겠습니다.
public class BaseExpandableAdapter extends BaseExpandableListAdapter{
	
	private ArrayList groupList = null;
	private ArrayList> childList = null;
	private LayoutInflater inflater = null;
	private ViewHolder viewHolder = null;
	
	public BaseExpandableAdapter(Context c, ArrayList groupList, 
			ArrayList> childList){
		super();
		this.inflater = LayoutInflater.from(c);
		this.groupList = groupList;
		this.childList = childList;
	}
	
	// 그룹 포지션을 반환한다.
	@Override
	public String getGroup(int groupPosition) {
		return groupList.get(groupPosition);
	}

	// 그룹 사이즈를 반환한다.
	@Override
	public int getGroupCount() {
		return groupList.size();
	}

	// 그룹 ID를 반환한다.
	@Override
	public long getGroupId(int groupPosition) {
		return groupPosition;
	}

	// 그룹뷰 각각의 ROW 
	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		
		View v = convertView;
		
		if(v == null){
			viewHolder = new ViewHolder();
			v = inflater.inflate(R.layout.list_row, parent, false);
			viewHolder.tv_groupName = (TextView) v.findViewById(R.id.tv_group);
			viewHolder.iv_image = (ImageView) v.findViewById(R.id.iv_image);
			v.setTag(viewHolder);
		}else{
			viewHolder = (ViewHolder)v.getTag();
		}
		
		// 그룹을 펼칠때와 닫을때 아이콘을 변경해 준다.
		if(isExpanded){
			viewHolder.iv_image.setBackgroundColor(Color.GREEN);
		}else{
			viewHolder.iv_image.setBackgroundColor(Color.WHITE);
		}
		
		viewHolder.tv_groupName.setText(getGroup(groupPosition));
		
		return v;
	}
	
	// 차일드뷰를 반환한다.
	@Override
	public String getChild(int groupPosition, int childPosition) {
		return childList.get(groupPosition).get(childPosition);
	}
	
	// 차일드뷰 사이즈를 반환한다.
	@Override
	public int getChildrenCount(int groupPosition) {
		return childList.get(groupPosition).size();
	}

	// 차일드뷰 ID를 반환한다.
	@Override
	public long getChildId(int groupPosition, int childPosition) {
		return childPosition;
	}

	// 차일드뷰 각각의 ROW
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		
		View v = convertView;
		
		if(v == null){
			viewHolder = new ViewHolder();
			v = inflater.inflate(R.layout.list_row, null);
			viewHolder.tv_childName = (TextView) v.findViewById(R.id.tv_child);
			v.setTag(viewHolder);
		}else{
			viewHolder = (ViewHolder)v.getTag();
		}
		
		viewHolder.tv_childName.setText(getChild(groupPosition, childPosition));
		
		return v;
	}

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

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) { return true; }
	
	class ViewHolder {
		public ImageView iv_image;
		public TextView tv_groupName;
		public TextView tv_childName;
	}

}
//



그리고 XML의 ExpandableListView 속성에 android:groupIndicator="@null" 속성을 추가해 줘서 기본적으로 안드로이드가 제공하는 그룹뷰 아이콘을 제거해 줍니다.

<ExpandableListView  
      android:id="@+id/elv_list"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:groupIndicator="@null"
      />


자 그럼 이렇게 해서 ExpandableListView 에 대해서 알아봤는데요. 디테일한 설명이 없더라도 중간중간에 주석을 달아서 보시는데 크게 어려움은 없을 거라고 생각 합니다. 그럼 ExpandableListView 를 활용한 멋진 UI 작업을 하시길 바라겠습니다.


Android Developers 사이트를 이용하시면 ExpandableListView 에 대한 속성 및 이벤트들을 더 많이 활용할 수 있습니다.


참고 : http://developer.android.com/reference/android/widget/ExpandableListView.html



파일첨부 : 


TestExpandableListView.zip



스크린샷 :