안드로이드/Android ArrayAdapter, BaseAdapter를 이용한 ListView 구현
안드로이드 프로젝트를 진행하면서 ListView 를 이용한 화면 구성을 많이 하겠 됩니다. ListView란 Data를 List 형식으로 출력해주는 View 인데요. ArrayAdapter 와 BaseAdapter를 이용한 ListView 구현 방법에 대하여 알아 보겠습니다. Adapter란 ListView에 출력할 Data를 보관하는 장소라고 생각 하시면 되는데요. 실질적으로 List형식의 Data를 Adapter에 넘겨주면 Adapter가 ListView의 Row마다 List형식의 데이터를 출력 할 수 있게 도와 줍니다.
TesLlistViewActivity.java
public class TestListViewActivity extends Activity {
private ArrayList mCareList = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setLayout();
mCareList = new ArrayList();
for(int i = 0 ; i < 10 ; i++){
mCareList.add(new InfoClass
(
i + "번째" + " ListView 입니다.",
getResources().getDrawable(R.drawable.ic_launcher),
"" + i
));
}
// BaseAdapter 연결
mListView.setAdapter(new CustomBaseAdapter(this, mCareList));
// ArrayAdapter 연결
// mListView.setAdapter(new CustomArrayAdapter(this, R.layout.list_row, mCareList));
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView arg0, View view, int position,
long arg3) {
Toast.makeText(
getApplicationContext(),
"ITEM CLICK = " + position,
Toast.LENGTH_SHORT
).show();
}
});
}
private ListView mListView = null;
private void setLayout(){
mListView = (ListView) findViewById(R.id.lv_list);
}
}
//
CustomBaseAdapter.java ( 베이스어답터 )
public class CustomBaseAdapter extends BaseAdapter{
private LayoutInflater inflater = null;
private ArrayList infoList = null;
private ViewHolder viewHolder = null;
private Context mContext = null;
public CustomBaseAdapter(Context c , ArrayList arrays){
this.mContext = c;
this.inflater = LayoutInflater.from(c);
this.infoList = arrays;
}
// Adapter가 관리할 Data의 개수를 설정 합니다.
@Override
public int getCount() {
return infoList.size();
}
// Adapter가 관리하는 Data의 Item 의 Position을 <객체> 형태로 얻어 옵니다.
@Override
public InfoClass getItem(int position) {
return infoList.get(position);
}
// Adapter가 관리하는 Data의 Item 의 position 값의 ID 를 얻어 옵니다.
@Override
public long getItemId(int position) {
return position;
}
// ListView의 뿌려질 한줄의 Row를 설정 합니다.
@Override
public View getView(int position, View convertview, ViewGroup parent) {
View v = convertview;
if(v == null){
viewHolder = new ViewHolder();
v = inflater.inflate(R.layout.list_row, null);
viewHolder.tv_title = (TextView)v.findViewById(R.id.tv_title);
viewHolder.iv_image = (ImageView)v.findViewById(R.id.iv_image);
viewHolder.btn_button = (Button)v.findViewById(R.id.btn_button);
viewHolder.cb_box = (CheckBox)v.findViewById(R.id.cb_box);
v.setTag(viewHolder);
}else {
viewHolder = (ViewHolder)v.getTag();
}
viewHolder.tv_title.setText(getItem(position).title);
// image 나 button 등에 Tag를 사용해서 position 을 부여해 준다.
// Tag란 View를 식별할 수 있게 바코드 처럼 Tag를 달아 주는 View의 기능
// 이라고 생각 하시면 됩니다.
viewHolder.iv_image.setTag(position);
viewHolder.iv_image.setOnClickListener(buttonClickListener);
viewHolder.btn_button.setTag(position);
viewHolder.btn_button.setText(getItem(position).button);
viewHolder.btn_button.setOnClickListener(buttonClickListener);
viewHolder.cb_box.setTag(position);
viewHolder.cb_box.setOnClickListener(buttonClickListener);
return v;
}
// Adapter가 관리하는 Data List를 교체 한다.
// 교체 후 Adapter.notifyDataSetChanged() 메서드로 변경 사실을
// Adapter에 알려 주어 ListView에 적용 되도록 한다.
public void setArrayList(ArrayList arrays){
this.infoList = arrays;
}
public ArrayList getArrayList(){
return infoList;
}
private View.OnClickListener buttonClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
// 이미지 클릭
case R.id.iv_image:
Toast.makeText(
mContext,
"이미지 Tag = " + v.getTag(),
Toast.LENGTH_SHORT
).show();
break;
// 버튼 클릭
case R.id.btn_button:
Toast.makeText(
mContext,
"버튼 Tag = " + v.getTag(),
Toast.LENGTH_SHORT
).show();
break;
// CheckBox
case R.id.cb_box:
Toast.makeText(
mContext,
"체크박스 Tag = " + v.getTag(),
Toast.LENGTH_SHORT
).show();
break;
default:
break;
}
}
};
/*
* ViewHolder
* getView의 속도 향상을 위해 쓴다.
* 한번의 findViewByID 로 재사용 하기 위해 viewHolder를 사용 한다.
*/
class ViewHolder{
public TextView tv_title = null;
public ImageView iv_image = null;
public Button btn_button = null;
public CheckBox cb_box = null;
}
@Override
protected void finalize() throws Throwable {
free();
super.finalize();
}
private void free(){
inflater = null;
infoList = null;
viewHolder = null;
mContext = null;
}
}
//
CustomArrayAdapter
( 어레이어답터 )
ArrayAdapter는 생성시 Array를 넘겨주면 Super에서 자동으로 Data를 관리해 주므로 사용자 입장에서는 Adapter를 관리하기 편합니다.
public class CustomArrayAdapter extends ArrayAdapter{ private ViewHolder viewHolder = null; private LayoutInflater inflater = null; private ArrayList infoList = null; private Context mContext = null; public CustomArrayAdapter(Context c, int textViewResourceId, ArrayList arrays) { super(c, textViewResourceId, arrays); this.inflater = LayoutInflater.from(c); this.mContext = c; } @Override public int getCount() { return super.getCount(); } @Override public InfoClass getItem(int position) { return super.getItem(position); } @Override public long getItemId(int position) { return super.getItemId(position); } @Override public View getView(int position, View convertview, ViewGroup parent) { View v = convertview; if(v == null){ viewHolder = new ViewHolder(); v = inflater.inflate(R.layout.list_row, null); viewHolder.tv_title = (TextView)v.findViewById(R.id.tv_title); viewHolder.iv_image = (ImageView)v.findViewById(R.id.iv_image); viewHolder.btn_button = (Button)v.findViewById(R.id.btn_button); viewHolder.cb_box = (CheckBox)v.findViewById(R.id.cb_box); v.setTag(viewHolder); }else { viewHolder = (ViewHolder)v.getTag(); } viewHolder.tv_title.setText(getItem(position).title); viewHolder.iv_image.setOnClickListener(buttonClickListener); viewHolder.iv_image.setTag(position); viewHolder.btn_button.setText(getItem(position).button); viewHolder.btn_button.setOnClickListener(buttonClickListener); viewHolder.btn_button.setTag(position); viewHolder.cb_box.setTag(position); viewHolder.cb_box.setOnClickListener(buttonClickListener); return v; } //
이렇게 해서 ArrayAdapter 까지 알아 봤구요. 한가지 주의 하셔야 할 점이 있습니다. 바로 ListView의 한 Row 안에 Button 이나 CheckBox가 들어가게 되는 경우 인데요. 이럴 경우에는 Button이나 CheckBox가 ListView의 Item(Row의 한행) 에 onItemClickListener 들어가는 이벤트를 먼저 가져 가버린 다는 점임니다. 그렇게 되면 아무리 ListView의 Item을 클릭해도 전혀 반응이 없게 되는 것이지요.
그래서 에 Button 과 Check 의 XML 속성에 "focusable = false" 를 해주시면, ListView의 Item이 이벤트를 받을 수 있기 때문에 정상 적으로 호출 하는 것을 보실 수 있습니다. 그리고 다른 방법은 Button 대신 ImageView 를 사용해 ClickEvent 를 달아서 사용 하는 경우입니다. ImageView는 원래 이벤트 속성이 없기 때문에 ListView의 Item에 이벤트를 가져갈 수 가 없습니다.
그외에 여러 방법들이 있을 수 있으며, 각각에 상황에 맞게 사용 하시면 될 거 같습니다.
'Android > Listview' 카테고리의 다른 글
| 안드로이드/Android ExpandableListView 만들기 - 2 - (속성 추가) (8) | 2013.02.25 |
|---|---|
| 안드로이드/Android ListView Header, Footer 설정 하기 ~! (3) | 2013.01.10 |
| 안드로이드/Android AdapterView.onItemClickListener 사용법 (2) | 2012.04.03 |
| 안드로이드/Android ExpandableListView 만들기 (31) | 2012.03.29 |
| 안드로이드/Android Custom ListView CheckBox 모두 선택 하기 (6) | 2011.11.30 |
TestListView.zip