Gooday Note Scrap Source Android login
 
작성일 : 11-04-11 00:52
ListView
 글쓴이 : 기리
조회 : 5,299   추천 : 0   비추천 : 0  
   http://androidhuman.tistory.com/194 [1495]
안드로이드에서 일련의 데이터를 표시할 때에는 대부분 리스트를 사용합니다. 사실, 안드로이드 뿐만 아니라 모든 곳에서 데이터를 표시할 때에는 리스트를 사용하죠.:)

안드로이드에서 리스트를 사용하는 예

데이터를 리스트 형태로 표시해 주기 위해서는 아래와 같은 세 가지 요소가 필요합니다.
 
  • ListView 
  • 어댑터 
  • 원본 데이터 


앞의 AutoCompleteTextView에서와 마찬가지로, ListView에서도 원본 데이터와 그 데이터를 표시해주는 ListView 사이에 어댑터가 필요합니다. 여기에서도 마찬가지로 어댑터는 원본 데이터를 ListView와 연결시켜줌과 동시에, 리스트에 원본 데이터를 어떻게 표시할 지 정의해줍니다.

탭을 사용할 때와 마찬가지로, ListView를 조금 더 편하게 사용하기 위해 액티비티를 구현할 때 List
 안드로이드에서 ListView를 표시할 때 그냥 Activity를 상속하는 클래스를 사용할 수도 있지만, List에 관련된 여러 메소드들이 추가되어있는 ListActivity를 주로 사용합니다.

ListActivity를 상속하는 액티비티를 작성할 경우 ListView의 어댑터를 설정할 때 ListView를 참조하는 객체를 만들지 않아도 어댑터를 지정할 수 있지만, ListView의 id를 필히 @android:id/list로 설정하셔야 합니다. 그렇지 않으면 아래와 같이 런타임 오류가 발생하게 됩니다.

ListView의 ID를 제데로 설정해주지 않으면 발생하는 런타임 오류



ListActivity를 상속하게 되면 리스트에 표시할 항목이 없을 때 사용자에게 보여줄 화면을 설정하는 것도 비교적 쉽게 할 수 있습니다. 일반적으로 아래와 같은 화면이 되겠죠.

리스트에 표시할 내용이 없을 때 사용자에게 보여주는 문구



이처럼 리스트에 표시할 내용이 없을 때, 빈 화면을 보여주는 대신 사용자에게 항목을 추가하는 방법에 대한 안내를 해주거나, 최소한 "항목이 없습니다" 정도는 표시해 주는 것이 예의(?) 입니다. :)

위와 같이 표시할 항목이 없을 때 대체로 표시할 화면을 설정하려면, 해당 화면 (레이아웃, 뷰)의 id를 @android:id/empty로 설정해주면 됩니다. 정말 매우 간단하죠? 예제에서는 표시할 항목이 없을 경우 아래와 같이 간단한 문구를 표시해주도록 구현하였습니다.


한번 예제의 레이아웃 코드 중 일부를 보도록 하겠습니다.


[main.xml]


01.<ListView android:layout_height="wrap_content"
02.                android:id="@android:id/list" 
03.        android:layout_width="fill_parent"/>
04.      
05.    <TextView android:layout_width="wrap_content" 
06.        android:id="@android:id/empty" 
07.        android:text="표시할 내용이 없습니다." 
08.        android:layout_height="wrap_content" 
09.        android:layout_gravity="center_horizontal"/>
10.    


ListActivity를 상속하므로 ListView의 id는 @android:id/list 로, 리스트에 표시할 항목이 없을 경우 표시할 TextView의 id는 @android:id/empty로 설정한 모습을 확인할 수 있습니다.

그리고, 이 예제의 윗부분에 EditText와 Button의 레이아웃을 보면 두 위젯이 각각 일정한 비율의 가로 크기를 가지고 있는 것을 볼 수 있습니다. 이는 LinearLayout 내의 요소에 적용되는 속성인 weight 속성을 적용했기 때문입니다.

01.<EditText android:layout_height="wrap_content" 
02.    android:id="@+id/inputText" 
03.    android:layout_width="0dp" 
04.    android:layout_weight="5" 
05.    android:hint="추가할 단어를 입력하세요."/>
06.          
07.<Button android:layout_height="wrap_content" 
08.    android:layout_width="0dp" 
09.    android:layout_weight="1" 
10.    android:id="@+id/inputButton" 
11.    android:text="Add"/>

위와 같이 각각의 너비 (layout_width)를 0으로 하고, layout_weight 속성을 지정해 주면, weight 의 크기에 따라 레이아웃 내에서 해당 요소의 너비가 정해지게 됩니다. 위의 경우 전체 너비에서 EditText와 Button이 5:1 비율로 화면을 차지하게 구성된 모습입니다.

그럼 이제 본격적으로 예제 어플리케이션의 코드를 보도록 하겠습니다. 예제 어플리케이션은 위의 EditText에 텍스트를 입력하고, 버튼을 누르면 입력한 항목이 List에 추가되도록 하였습니다.

[ListViewExample.java]

01.package com.androidhuman.example.ListViewExample;
02.  
03.import java.util.ArrayList;
04.  
05.import android.app.ListActivity;
06.  
07.import android.os.Bundle;
08.import android.view.View;
09.import android.view.View.OnClickListener;
10.import android.widget.ArrayAdapter;
11.import android.widget.Button;
12.import android.widget.EditText;
13.  
14.public class ListViewExample extends ListActivity {
15.    private ArrayList<String> list;
16.    private ArrayAdapter<String> adapter;
17.    private EditText inputText;
18.    private Button inputButton;
19.      
20.    @Override
21.    public void onCreate(Bundle savedInstanceState) {
22.        super.onCreate(savedInstanceState);
23.        setContentView(R.layout.main);
24.          
25.        inputText = (EditText)findViewById(R.id.inputText);
26.        inputButton = (Button)findViewById(R.id.inputButton);
27.        list = new ArrayList<String>();
28.          
29.        inputButton.setOnClickListener(new OnClickListener(){
30.  
31.            @Override
32.            public void onClick(View v) {
33.                list.add(inputText.getText().toString());
34.                inputText.setText("");
35.                adapter.notifyDataSetChanged();
36.            }
37.              
38.        });
39.          
40.        adapter = new ArrayAdapter<String>(this
41.                android.R.layout.simple_list_item_1, list);
42.          
43.        setListAdapter(adapter);
44.    }
45.}


주요 부분에 대해 한번 다시 살펴보도록 하겠습니다. 어댑터를 생성하는 과정은 기존에 AutoCompleteTextView에서 봤던 과정과 동일합니다. 표시할 데이터 및 표시될 레이아웃을 설정해주고 있습니다. 

그리고, 해당 어댑터를 ListView의 어댑터로 지정하기 위해 setListAdapter()메소드에 우리가 만든 어댑터를 인자로 넘겨주고 있습니다. 이렇게 해서야 비로소 우리가 표시하고 싶은 데이터와 데이터를 표시해줄 ListView가 연결이 된 셈입니다.

그리고, 버튼의 리스너 부분을 한번 보도록 하죠.


1.@Override
2.public void onClick(View v) {
3.    list.add(inputText.getText().toString());
4.    inputText.setText("");
5.    adapter.notifyDataSetChanged();
6.}

버튼을 클릭하면 EditText에 입력된 내용을 데이터가 담긴 ArrayList인 list에 추가해주고, EditText 필드를 초기화시켜주는 것을 확인할 수 있습니다. 여기에서 무엇보다 주요한 것은 바로 notifyDataSetChanged() 메소드입니다.

우리가 표시할 데이터를 담고 있는 리스트인 list 객체에 데이터를 추가함으로써 데이터에 변화가 생기게 되었고, 이러한 변화는 어댑터가 자동으로 감지하지 못하므로 어댑터에게 이 사실을 알려야 합니다. notifyDataSetChanged() 메소드를 호출하게 되면 어댑터가 다시 리스트로부터 최신의 데이터를 받아오고, 업데이트된 내용이 다시 ListView에 표시될 수 있게 해줍니다.

따라서, 표시할 데이터를 수정하였다면 이 메소드를 호출해야만 ListView에 수정된 내용이 정상적으로 표시되므로 데이터를 변경하였을 때에는 이 메소드를 호출해주는 것을 잊지 말아야 합니다.

예제의 실행 모습은 아래와 같습니다.

ListViewExample 예제의 실행 모습


ListView 선택 이벤트 처리

ListView에 표시된 항목을 클릭했을 때 어떤 동작을 구현하고 싶다면 어떻게 해야할까요? 어렵게 생각하실지도 모르겠지만, 정말 간단합니다. ListActivity 내의 메소드인 onListItemClick() 메소드를 오버라이드한 후 구현하면 됩니다. 아래에서는 위의 예제에 이어 항목을 선택하면 선택한 항목의 문자열을 토스트(Toast)를 통해 표시해주도록 하고 있습니다.

1.@Override
2.protected void onListItemClick (ListView l, View v, int position, long id){
3.    super.onListItemClick(l, v, position, id);
4.    Toast.makeText(this, list.get(position), Toast.LENGTH_SHORT).show();
5.}


onListItemClick() 메소드는 총 4개의 인자를 받으며, 각각은 아래와 같은 값을 가집니다.

  • ListView : 리스트 항목 선택 이벤트가 발생한 ListView
  • View : 선택한 "항목"의 뷰 인스턴스 (리스트의 한 항목)
  • position : 선택한 항목의 인덱스 값
  • id : 데이터베이스 등을 표시하는 ListView일 경우 선택한 항목의 id값

위의 메소드를 추가한 후 예제를 실행시켜 보면 아래와 같은 결과를 볼 수 있습니다.

두 번째 항목을 클릭했을 때의 화면


어때요? 생각보다 쉽지 않나요? 어댑터라는 개념 때문에 처음에는 생소하고 어려워 보일지 몰라도 알고보면 그리 어렵지 않은녀석(?)이랍니다. :)

기리 11-04-11 01:14