티스토리 뷰

 Android Expandable 예제에 이어서 Expandable Custom 예제를 작성해보았습니다. 지난번과는 다른 데이터를 사용하였고, 결과화면의 차이는 없습니다. 첫 번째에 올렸던 기본예제는 아래 링크를 통해 확인 가능합니다.

   http://thdev.net/365


Custom 하기

이번 예제는 제목 그대로 Custom을 하였습니다. Expandable을 커스텀하기 위한 방법은 간단합니다.

 BaseExpandableListAdapter를 상속받아서 커스텀하면 됩니다.

BaseExpandableListAdapter API 페이지

  http://developer.android.com/reference/android/widget/BaseExpandableListAdapter.html

ExpandableListAdapter API 페이지

   http://developer.android.com/reference/android/widget/ExpandableListAdapter.html


BaseExpandableListAdapter Public Mehtod

 BaseExpandableListAdapter은 ListView와는 다르게 Child와 Group 2가지로 구분이 됩니다. 그렇기 때문에 2가지의 다른 메소드가 아래와 같이 정의 되어 있습니다. 그렇기에 아래 메소드 중 화면에 표시하는 관련 Method는 모두 작성해주셔야 합니다. 사용해야 할 Method는 별도로 체크하겠습니다.

 - 기본적으로 구현해야 하는 내용을 구현여부에 V 했습니다.

 구현여부

 Type

 Method Name

 

 abstract boolean

 areAllItemsEnabled()

V

 abstract Object

 getChild(int groupPosition, int childPosition)
   Group내의 Child의 값들을 가져옵니다.

V

 abstract long

 getChildId(int groupPosition, int childPosition)
   Child의 ID값을 가져옵니다.

V

 abstract View

 getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
   Child View에 데이터를 뿌려주는 메소드 입니다.

V

 abstract int

 getChildrenCount(int groupPosition)
   해당 Group의 Child의 수를 Count 합니다.


 abstract long

 getCombinedChildId(long groupId, long childId)
    특정 항목의 Child 아이디 값을 가져옵니다.

  abstract long getCombinedGroupId(long groupId)
    특정 Group의 아이디 값을 가져옵니다.

V

 abstract Object

 getGroup(int groupPosition)
    Group의 값들을 가져옵니다.

V

 abstract int getGroupCount()
    Group의 Count를 Return 합니다.

V

 abstract long

 getGroupId(int groupPosition)
    Group의 ID값을 가져옵니다.

V

 abstract View

 getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
    Group View에 데이터를 뿌려주는 메소드 입니다.

V

 abstract boolean

 hasStableIds()
    Indicates whether the child and group IDs are stable across changes to the underlying data.(해석이 안되네요.)
  기본 return 은 false 입니다.

V

 abstract boolean

 isChildSelectable(int groupPosition, int childPosition)
   특정 Group의 Child를 클릭할 것인지를 정합니다. 기본값은 false이며 선택되지 않습니다.

  abstract boolean isEmpty()
  abstract void

 onGroupCollapsed(int groupPosition)
   Group이 수정될 경우 호출합니다.

  abstract void onGroupExpanded(int groupPosition)
   Group이 확장될 경우 호출합니다.
  abstract void registerDataSetObserver(DataSetObserver observer)
  abstract void unregisterDataSetObserver(DataSetObserver observer)


V 표시가된 Method들이 기본적으로 구현되어야 하며, 나머지는 선택적으로 구현하시면 됩니다.


구현 내용

 구현내용은 BaseExpandableAdapter를 상속받아서 구현하였습니다. API를 보시면 아시겠지만 BaseExpandableAdapter를 상속을 받지만 실제로는 ExpandableAdapter에서 해당 Method의 내용을 볼 수 있습니다.

 저는 간단하게 휴대폰 OS 별로 휴대폰의 종류를 작성해보는 Custom ExpandableListView를 작성해보았습니다. 그리고 이미지 View를 사용했는데 기본 아이콘을 화면에 표시하였습니다.


주요 소스코드

MainActivity.java - 메인 엑티비티

ExpandableListView list = (ExpandableListView)findViewById(R.id.list);
		
		//create Data
		list.setAdapter(new ExpandableAdapter(this, createData()));

phoneData.java - 제가 사용하기 위해 구현한 Data 클래스

public class phoneData {
	String OS;
	ArrayList<String> PhoneType;
	
	public phoneData(String os, ArrayList<String> phoneType) {
		OS = os;
		PhoneType = phoneType;
	}
}

ExpandableAdapter.java - BaseExpandableAdatper를 상속받아 구현한 클래스

public class ExpandableAdapter extends BaseExpandableListAdapter {
	Context mContext;
	ArrayList<phoneData> mPhoneData;
	
	public ExpandableAdapter(Context context, ArrayList<phoneData> phone) {
		mContext = context;
		mPhoneData = phone; 
	}

	@Override
	public Object getChild(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return mPhoneData.get(groupPosition).PhoneType.get(childPosition);
	}

	@Override
	public long getChildId(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return childPosition;
	}

	//ChildView에 데이터 뿌리기 
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		View view;
		if(convertView == null) {
			view = getChildGenericView();
		} else {
			view = convertView;
		}
		
		TextView text = (TextView)view.findViewById(android.R.id.text1);
		text.setText(mPhoneData.get(groupPosition).PhoneType.get(childPosition));
		return view;
	}

	@Override
	public int getChildrenCount(int groupPosition) {
		return mPhoneData.get(groupPosition).PhoneType.size();
	}

	@Override
	public Object getGroup(int groupPosition) {
		return mPhoneData.get(groupPosition);
	}

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

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

	//GroupView에 데이터 뿌리
	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		
		View view;
		if(convertView == null) {
			view = getParentGenericView();
		} else {
			view = convertView;
		}
		
		ImageView img = (ImageView)view.findViewById(R.id.img);
		img.setImageResource(mContext.getResources().getIdentifier("ic_launcher", "drawable", mContext.getPackageName()));
		TextView text = (TextView)view.findViewById(R.id.text);
		text.setText(mPhoneData.get(groupPosition).OS);
		return view;
	}

	@Override
	public boolean hasStableIds() {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public boolean areAllItemsEnabled() {
		// TODO Auto-generated method stub
		return super.areAllItemsEnabled();
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return false;
	}
	
	//Child의 View의 XML을 생성 
	public View getChildGenericView() {
		LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, null);
		return view;
	}
	
	//Parent(Group)의 View의 XML을 생성 
	public View getParentGenericView() {
		LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View view = inflater.inflate(R.layout.simple_expandable_list_item_1, null);
		return view;
	}
}

Custom ListView xml - 리스트 뷰의 Custom

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
	    android:id="@+id/text"
	    android:layout_width="wrap_content"
	    android:layout_height="?android:attr/listPreferredItemHeight"
	    android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
	    android:gravity="center_vertical"
	    android:layout_weight="1" />
    <ImageView 
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:scaleType="centerInside"
        android:layout_weight="0" />
</LinearLayout>


결과 화면

 지난번에 작성한 것과는 내용만 다르고, Custom을 했다는것 말곤 전혀 차이가 없습니다. ExpandableListView 역시 UI커스텀도 가능합니다. 단 기본적으로 지원해주는 adapter를 사용하시면 커스텀 UI를 사용할 수 없고 위와 같이 구현하셔야 합니다. 이상으로 이번 글은 마치겠습니다. 역시 소스코드는 아래 주소로 다운로드 받으시면 됩니다.


소스코드 다운로드

   http://db.tt/UepRKIAx





댓글