안드로이드/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 ArrayListmCareList = 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 ArrayListinfoList = 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 |