[안드로이드 프로그래밍] 리스트뷰, 어댑터를 이용해서 커스텀 리스트뷰 만들기.

     




리스트뷰는 상당히 많이 사용되는 안드로이드의 기능이다.


일반적인 리스트 뷰가 아니라 사용자가 커스텀한 뷰를 리스트로 보여주는 커스텀 리스트를 만들어보려고 한다. 


원래 리스트 뷰를 사용할 때, Do IT 안드로이드 책을 보고 작성하였는데, 생각보다 쓸대없는 코드가 많이 섞여있어서 다시 만들어 보았다.


일단 리스트 뷰는 다른 뷰와는 다르게 adapter를 사용해서 화면을 구성한다. 따라서 필요한 것은 리스트 뷰에 들어하는 항목에 대한 레이아웃과 객체, 어댑터 3가지가 필요하다. 


먼저 내가 구현하고자 하는 화면은 텍스트 뷰 하나로 이루어진 간단한 레이아웃이다. 커스텀 뷰를 사용한 이유는 스타일을 사용하기 위해서이다.


일단 리스트 뷰에 하나의 항목에 해당하는 레이아웃을 만든다.




listlayout.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="50dp">
    <TextView android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            style="@style/btnStyle"
            android:textSize="20sp"
 
            android:gravity="center|left"/>
 
</LinearLayout>



간단하게 만들었다. 사실 레이아웃만드는 부분을 그렇게 중요하지 않기 때문에 바로 넘어가도록 하겠다.


이제 이 레이아웃을 보여주는 클래스와 레이아웃을 구성하는 변수들을 관리하는 클래스를 만들어 준다.


ListViewLayout.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package cho.tkdlek.dailydeveloper;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;
 
/**
 * Created by Cho on 14. 12. 2..
 */
public class ListViewLayout extends LinearLayout {
 
    private TextView btn;
    public ListViewLayout(Context context, ListItem item){
        super(context);
 
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.listlayout,this,true);
 
        btn = (TextView)findViewById(R.id.btn);
        btn.setText(item.getText());
    }
 
    public void setText(String text){
        btn.setText(text);
    }
}
 



ListItem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package cho.tkdlek.dailydeveloper;
 
/**
 * Created by Cho on 14. 12. 2..
 */
public class ListItem {
 
    private String btnText;
 
    public ListItem(String text){
        btnText = text;
    }
 
    public String getText(){
        return btnText;
    }
 
}
 


첫번째 코드는 레이아웃을 항목을 화면에 보여주는 클래스이고, 두번째는 첫번째 클래스를 구성하는데 필요한 변수들을 관리하는 클래스이다. 여기서는 텍스트 뷰 하나만을 사용하기 때문에 그렇게 복잡하지 않지만, 이미지 뷰와 버튼 등 여러가지 뷰를 사용하는 화면을 구성한다면, 상당히 많은 코드가 생긴다.


이제 제일 중요한 Adapter를 만들어야 한다. 사실 커스텀 리스트 뷰는 커스텀 Adapter를 만드는 것을 뜻하기도 한다. BaseAdapter를 상속한 새로운 Adapter클래스를 만든다.


ListViewAdapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package cho.tkdlek.dailydeveloper;
 
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * Created by Cho on 14. 12. 2..
 */
public class ListViewAdapter extends BaseAdapter {
    private Context mContext;
    private List<ListItem> listItem = new ArrayList<ListItem>();
 
    public ListViewAdapter(Context context){
        mContext = context;
    }
 
    public void addItem(ListItem item){
        listItem.add(item);
    }
 
    public int getCount() {
        return listItem.size();
    }
 
    public Object getItem(int i) {
        return listItem.get(i);
    }
 
    public long getItemId(int i) {
        return i;
    }
 
    public View getView(int i, View view, ViewGroup viewGroup) {
        ListViewLayout itemView;
        if(view ==null){
            itemView = new ListViewLayout(mContext,listItem.get(i));
        }else{
            itemView = (ListViewLayout) view;
 
            itemView.setText(listItem.get(i).getText());
        }
 
        return itemView;
    }
}
 


어댑터의 생성자는 Context를 인자값으로 사용한다. 아래 4개의 메소드는 오버라이드 되는 메소드들인데 가장 중요한 것은 getView이다. getView메소드가 실질적으로 화면에 뷰를 나타내는 메소드이다. if문이 사용된 곳은 새로운 뷰를 생성할 때 기존에 사용되었던 뷰를 재사용하기 위함이다. 


쉽게 설명하면 화면에 5개의 리스트항목이 표시되고 아래로 스크롤하면 6번째 항목이 보인다. 그와 동시에 1번째 항목은 화면 밖으로 없어진다. 따라서 6번째 항목을 만들때 기존에 1번째 항목에서 사용했던 뷰를 가져와서 사용하면 메모리가 절약되며 성능이 향상된다. 물론 실제로 화면에서 벗어나자마자 재사용하지는 않지만 이해를 돕기위해 이렇게 설명했다.


위 코드를 어느정도 분석하면 알 수 있는 것이, 보이는 리스트 뷰와 실질적인 리스트 항목들은 같지 않다. 다만 연결되어 있을 뿐이다. 쉽게 생각한다면 리스트에 10개의 항목이 있을때, 10개에 대한 레이아웃을 전부 만들어서 리스트에 채우는 것이 아니라, 5~6개의 레이아웃만 만들고 안에 내용만 바꿔주게 된다. 즉 실질적으로 리스트의 내용을 나타내는 것은 ArrayList로 선언된 레이아웃에 변수를 담당하는 클래스다. 즉 레이아웃을 나타내기 위해 만들었던 뷰는 단순히 사용자에게 보여지는 일만 하고, 실제로 데이터에 접근하거나 몇 번째 리스트가 어떤 자료를 가지고 있는지는 레이아웃 변수를 담당하는 ListItem의 ArrayList가 담당한다.


마지막으로 만든 리스트를 사용하는 방법은 사용하고 싶은 액티비티에서 adapter를 선언하고 ListView에 붙이면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package cho.tkdlek.dailydeveloper;
 
import android.app.Activity;
import android.graphics.drawable.PaintDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
 
/**
 * Created by Cho on 14. 12. 2..
 */
public class ContentListActivity extends Activity {
 
 
    ListView list;
    ListViewAdapter adapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        list = new ListView(this);
        adapter = new ListViewAdapter(this);
 
 
        adapter.addItem(new ListItem(" 1. 리스트1"));
 
        adapter.addItem(new ListItem(" 2. 리스트2"));
 
        adapter.addItem(new ListItem(" 3. 리스트3"));
 
        adapter.addItem(new ListItem(" 4. 리스트4"));
 
        adapter.addItem(new ListItem(" 5. 리스트5"));
 
 
        list.setAdapter(adapter);
        list.setSelector(new PaintDrawable(0x0000000)) ;
 
        list.setDivider(new PaintDrawable(0x00000000));
        list.setDividerHeight(10);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                ListItem curItem = (ListItem) adapter.getItem(i);
                Toast.makeText(getApplicationContext(), "Selected :" + curItem.getText(), Toast.LENGTH_SHORT).show();
                Log.d("tag""뭔가선택됨");
            }
        });
 
 
 
        setContentView(list,params);
 
    }
}



지금 만든 리스트뷰는 상당히 간단한 것으로 슬라이드를 통해 삭제가 가능한 리스트뷰나 리스트뷰 안에 있는 뷰들의 이벤트를 처리하는 뷰도 만들 수 있다. 

반응형

댓글

Designed by JB FACTORY