Skip to content

Android.widget.ListView

A view that shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view.

Custom ListView

ListView를 직접 수정하기 위하여 아래와 같은 과정을 거쳐야 한다.

  1. 1개 아이템(ROW)에 대한 Layout XML을 작성한다.
  2. 1개 아이템의 정보를 가지 고 있는 구조체(클래스)작성.
  3. ListView에 setAdapter()를 사용하여 장착시킬 ArrayAdapter 또는 BaseAdapter를 상속받는 어댑터클래스 작성. 중요한점은 BaseAdapter를 상속받을 경우 최소한 getItem(), getView(), getCount()를 override하여 구현해야 한다. (내부적으로 getCount()를 사용하여 아이템의 존재유무를 검사한다.)
  4. 아이템의 클릭 이벤트를 추가하고 싶을 경우 setOnItemClickListener()를 사용한다. 1
  5. 성능개선을 위해, #ViewHolder를 사용한다. 아래는 그 예제를 보여준다.
/** 하나의 어플리케이션 정보. */
public static class AppInfo {
    /** 패키지명(Package name). */
    public String pkgname;
    /** 어플리케이션 명칭. */
    public String name;
    /** 어플리케이션 아이콘. */
    public Bitmap icon;
}

/** 리스트뷰에 장착시키기 위한 어댑터(Adapter) 클래스. */
public class AppInfoAdapter extends ArrayAdapter<AppInfo> {

    /** 어댑터의 getView() 성능을 높이기 위한 ViewHolder. */
    private class ViewHolder {
        /** 아이콘 이미지뷰. */
        public ImageView iconview;
        /** 어플리케이션 명칭. */
        public TextView appname;
        /** 어플리케이션 추가 설명. */
        public TextView appinfo;
    }

    public AppInfoAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public AppInfoAdapter(Context context, int textViewResourceId, List<AppInfo> objects) {
        super(context, textViewResourceId, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final AppInfo kCurrentItem = getItem(position);

        if (convertView == null) {
            convertView = LayoutInflater.from(FavoriteAppPopup.this).inflate(R.layout.listitem_favoriteapp, null);

            // Register view objects.
            ViewHolder holder = new ViewHolder();
            holder.iconview = (ImageView) convertView.findViewById(R.id.favoriteapp_listitem__icon_img);
            holder.appname = (TextView) convertView.findViewById(R.id.favoriteapp_listitem__title_label);
            holder.appinfo = (TextView) convertView.findViewById(R.id.favoriteapp_listitem__comment_label);
            convertView.setTag(holder);
        }

        final ViewHolder kCurrentHolder = (ViewHolder) convertView.getTag();

        if (kCurrentHolder == null) {
            Log.d(FavoriteAppPopup.class.toString(), "kCurrentHolder is null.");
        } else {
            kCurrentHolder.iconview.setImageBitmap(kCurrentItem.icon);
            kCurrentHolder.appname.setText(kCurrentItem.name);
            kCurrentHolder.appinfo.setText(kCurrentItem.pkgname);
            kCurrentHolder.appinfo.setVisibility(View.INVISIBLE);
        }

        // return super.getView(position, convertView, parent);
        return convertView;
    }
}
// ....

/** 리스트뷰를 설치한다. */
private void setupListView() {
    _listview = (ListView) findViewById(R.id.favoriteapp_popup__apps_listview);
    _lsitadapter = new AppInfoAdapter(this, R.layout.listitem_favoriteapp);

    _lsitadapter.addAll(getLocalAppInfoList());
    _lsitadapter.addAll(requestAppInfoList());

    _listview.setAdapter(_lsitadapter);
    _listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final AppInfo kCurrentItem = _lsitadapter.getItem(position);

            // 어플이 존재한다면 실행하고, 그렇지 않다면 마켓으로 이동한다.
            if (kCurrentItem != null) {
                IntentHelper.runApplicationOrJumpMarket(FavoriteAppPopup.this, kCurrentItem.pkgname);
            }
        }
    });
    _lsitadapter.notifyDataSetChanged();
}

사용자 입력값을 ArrayAdapter에 추가(add)한 다음에 변경사항을 체크하라는 notifyDataSetChanged()메서드를 호출해야 한다.

한 개의 문자열을 출력할 수 있는 ListView

마치 콤보박스와 같은 역할을 하는 ListView이다.

ListView list_view = (ListView) findViewById(kOptionListViewId);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
adapter.add("Test1");
adapter.add("Test2");
adapter.add("Test3");
list_view.setAdapter(adapter);

위의 소스에서 어뎁터(ArrayAdapter)의 생성자로 넘기는 android.R.layout.simple_list_item_1는 미리 정의된 ListView를 위한 레이아웃이다. 이와 같이 미리정의된 레이아웃은 아래와 같이 존재한다.

  • android.R.layout.simple_list_item_1;
  • android.R.layout.simple_list_item_2;
  • android.R.layout.simple_list_item_activated_1;
  • android.R.layout.simple_list_item_activated_2;
  • android.R.layout.simple_list_item_checked;
  • android.R.layout.simple_list_item_multiple_choice;
  • android.R.layout.simple_list_item_single_choice;

두 개의 문자열을 출력할 수 있는 ListView

ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
HashMap<String,String> item;

// 이부분은 예를 들기위하여 풀어 썼으며 리소스를 이용하기 위해서는 for 문 등을 이용하면 된다.
item = new HashMap<String,String>();
item.put("item 1", "Title 1");
item.put("item 2", "description 1");
list.add(item);
item = new HashMap<String,String>();
item.put("item 1","Title 2");
item.put("item 2","another description here");
list.add(item);

simpleAdapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, new String[] {"item 1","item 2"}, new int[] {android.R.id.text1, android.R.id.text2});
setListAdapter(simpleAdapter);

리스트뷰나 스크롤뷰에 바운스(Bounce)되는 효과를 제거하는 방법

바운스효과(리스트가 살짝 튕겨서 돌아오는 효과)를 제거하는 방법. 안드로이드에서는 뷰의 마지막에 도착했을 때 마지막 위치의 끝 엣지(Edge)가 밝게 빛나는 효과를 지칭한다.

_pager.setOverScrollMode(View.OVER_SCROLL_NEVER);

ListView의 속도문제 (Making ListView Scrolling Smooth)

ViewHolder

ViewHolder란, 이름 그대로 뷰들을 홀더에 꼽아놓듯이 보관하는 객체를 말합니다. 각각의 Row를 그려낼 때 그 안의 위젯들의 속성을 변경하기 위해 findViewById를 호출하는데 이것의 비용이 큰것을 줄이기 위해 사용합니다.

See also

Favorite site

References


  1. http://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html 

  2. Android_listview_howtouse.pdf 

  3. Android_listview_list-activity_and_list-fragment_tutorial.pdf