getView()
getView()는 Adapter 가 가지고 있는 data 를 어떻게 보여줄 것인가를 정의하는데 쓰인다. ListView 를 예를 들면 하나의 list item 의 모양을 결정하는 역할을 하는 것이다.getView() 의 설명과 사용법은 [ref. 2] 에 정리가 잘 되어 있고, source code 도 제공한다. 그러므로 영어에 부담이 없다면 ref.2 를 참조하면 좋을 듯 하다. 여기서는 대략적으로 정리만 하려한다.
ref.2 에서 얘기하듯이 ListView 가 각각의 list item 을 그릴때 Adapter에게 어떻게 그려야 할 지 묻는다. 그때 사용하는 함수가 getView() 가 되겠다.
ref. 2 에서는 이 getView() 를 이용해서 view 의 재사용 하는 법에 대한 자세한 이야기를 해준다.
ref.2 의 코드를 조금 간단하게 만들고 아래에 옮겨놨다. 아래의 코드는 ListView 에 getView() 로 listItem 을 만들어서 보여주는 것이다.
package com.muchart;
import java.util.ArrayList;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
//--------------------------------------------------------
public class MainActivity extends ListActivity {
private CustomAdapter mAdapter;
//--------------------------------------------------------
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new CustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
//mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
//--------------------------------------------------------
private class CustomAdapter extends BaseAdapter{
/**
* layout inflator
*
* Instantiates a layout XML file into its corresponding View objects.
* @ref : http://developer.android.com/reference/android/view/LayoutInflater.html
*/
private LayoutInflater mInflater;
private ArrayList<String> mData = new ArrayList<String>();
//--------------------------------------------------------
public CustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//--------------------------------------------------------
public void addSeparatorItem(String string) {
// TODO Auto-generated method stub
}
//--------------------------------------------------------
public void addItem(String string) {
mData.add(string);
notifyDataSetChanged();
}
//--------------------------------------------------------
@Override
public int getCount() {
return mData.size();
}
//--------------------------------------------------------
@Override
public Object getItem(int position) {
return mData.get(position);
}
//--------------------------------------------------------
@Override
public long getItemId(int position) {
return position;
}
//--------------------------------------------------------
@Override
public View getView(int pos, View convertView, ViewGroup parent)
{
TextView textView = null;
if(convertView == null){
convertView = mInflater.inflate(R.layout.item1, null);
textView = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(textView);
}
else
{
textView = (TextView)convertView.getTag();
}
textView.setText(mData.get(pos));
return convertView;
}
}
}
참고로, ListActivity 는 기본적으로 화면 가운데에 한개의 full-screen list 로 구성된 layout 을 갖는다. [ref. 1] constructor 에서
super.onCreate(savedInstanceState);
를 호출할 때 설정되는 듯 하다.
그래서 기본적으로 setListAdapter() 만 설정해 주는 것으로 ListView 를 완성할 수 있다.
여기서 핵심은 getView() 이기 때문에 getView()에 대한 이야기만 조금 하자면,
//-------------------------------------------------------- @Override public View getView(int pos, View convertView, ViewGroup parent) { TextView textView = null; if(convertView == null){ // item1.xml 을 view object 에 넣어준다. convertView = mInflater.inflate(R.layout.item1, null); // text 라는 id 를 가져다가 convertView 에 달아준다. // setTag() 가 tag 의 용도도 있지만, 그냥 특정 data 를 붙여놓는 용도로도 쓰인다. textView = (TextView)convertView.findViewById(R.id.text); convertView.setTag(textView); } else { // convetView 가 null 이 아닌 경우에는 // convertView 에 붙여놓았던 textView 를 // 그냥 가져다 쓰면 된다. textView = (TextView)convertView.getTag(); } textView.setText(mData.get(pos)); return convertView; }
convertView 는 처음에 null 이다. 그런데 처음 만들어진 convertView(편의상 cv1 이라 하자.) 가 화면 밖으로 사라지면, 이 cv1 을 Recycler 라는 곳에 넣어뒀다가, 새롭게 보여지는 item 이 getView() 를 호출할 때 convertView 가 cv1 을 가지고 있게 된다.[ref.2]
여러 type 의 item 이 있을 때
이 때 View 의 종류가 여러 개일 수도 있다. 이때를 위해- getItemViewType()
- getItemViewTypeCount()
를 override 하고, getView() code 에서 getItemViewType() 에 따라 convertView 를 할당해준다면, 나머지는 알아서 해결 해 준다.
AbsListView()에서 getView() 와 관련된 내용
// view 가 추가될때 void addScrapView(View scrap, int position) mScrapViews[viewType].add(scrap); // view count 를 mViewTypeCount 에 할당 RecycleBin mRecycler mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); mViewTypeCount = mAdapter.getViewTypeCount() // view 를 얻어 올 때 View obtainView(int position, boolean[] isScrap) scrapView = mRecycler.getScrapView(position); // --> getScrapView() if (mViewTypeCount == 1) { return retrieveFromScrap(mCurrentScrap, position); } else { int whichScrap = mAdapter.getItemViewType(position); if (whichScrap >= 0 && whichScrap < mScrapViews.length) { return retrieveFromScrap(mScrapViews[whichScrap], position); } } //<-- if (scrapView != null) child = mAdapter.getView(position, scrapView, this);
ref. 2 에서 example code에서 확인할 수 있다.
getView() 를 사용할 때 주의할 점
결론부터 이야기 하면, 화면에 보이지 않는 item 을 사용하면 null 이 return 되니 주의하라는 이야기이다.코딩을 하다 보니, 아래 그림과 같은 구조의 ListView 를 사용하게 되었다. 그런데 아래와 같은 코드에서 종종 어플리케이션이 죽었다.
LinearLayout ll = (LinearLayout)getChildAt(mCurPage);
TextView titleTextView = (TextView)ll.findViewById(R.id.title);
mToast.setText(titleTextView.getText());
원인은 titleTextView 가 null 이어서 인데, 아래 그림과 같은 경우에 발생했다.
그림에서 처럼 맨 위에 TextView 가 있고, 이녀석의 id 가 title 이다. 그런데 scroll 을 하게 되면, 이녀석이 사라지고, 결국 id 가 title 인 녀석도 ListView 내에서 존재하지 않게 되었다. 그렇기 때문에 그상태에서
LinearLayout ll = (LinearLayout)getChildAt(mCurPage);
TextView titleTextView = (TextView)ll.findViewById(R.id.title);
를 하면 결국 R.id.title 을 찾지 못하고 null 을 return 하는 것이었다. 그러므로 ListView 의 item 을 호출해서 사용할 때는 화면에 보이지 않는 경우에 대한 고려를 하고 사용해야 할 듯 하다.
Reference
- http://developer.android.com/reference/android/app/ListActivity.html
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- http://www.youtube.com/watch?v=wDBM6wVEO70, 5분부터 보면 된다.
- http://stackoverflow.com/questions/10160475/when-getview-in-arrayadapter-is-called
- http://android-codes-examples.blogspot.kr/2011/03/customized-listview-items-selection.html
- State List of Drawables
- Color State List
댓글 없음:
댓글 쓰기