![](https://t1.daumcdn.net/cfile/tistory/998A054C5C99788335)
ListView
위와 같이 목록형태의 뷰를 구성하고 싶다면 xml 같은 정적선언으로는 무리가 있다.
View가 수십개인 경우, 또한 매번 그 개수가 변경되는 경우에는 일일히 애플리케이션을 수정해야 하기 때문이다.
동적으로 동일한 모양의 View를 여러 개 선언할 때는 ListView (비슷한 계열로 GridView와 RecyclerView 등이 있다.)를 사용한다.
보통 이런식의 단일 View를 여러 개로 구성할 때는 Adapter를 사용한다.
구성 방법
1. 메인 xml에 <ListView> 위젯을 추가
(1) res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical">
<TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#3e78d6" android:text="ListView!" android:textColor="#dae1ed" android:textSize="25sp" android:textStyle="bold" android:gravity="center"/> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="9"/> </LinearLayout>
|
(2) preview 확인
2. res/layout에 아이템 xml 추가
(1) xml 추가하기
![](https://t1.daumcdn.net/cfile/tistory/99AD8C475C9981F60C)
(2) 이름 짓기
![](https://t1.daumcdn.net/cfile/tistory/99AAA6475C9981F604)
참고) 이름은 아무거나 지어도 되고(단 소문자만) Root element는 검색기능이 지원된다!
(3) res/layout/item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:id="@+id/item_image_view" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/ic_launcher_foreground"/> <TextView android:id="@+id/item_text_view" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:text="이부분은 TextView" android:gravity="center_vertical"> </TextView> </LinearLayout>
|
(4) preview 확인
3. Adaper 클래스 추가
(1) java class 추가하기
![](https://t1.daumcdn.net/cfile/tistory/998F89425C99867815)
(2) Superclass는 자바 클래스 생성할 때도 지정할 수 있다. Adapter 종류는 많지만 가장 기본적인 BaseAdapter를 사용해보자.
![](https://t1.daumcdn.net/cfile/tistory/995985425C9986780F)
(3) 추상메서드 오버라이드
클래스를 생성하면 처음에 에러가 난다. BaseAdapter는 Adapter 인터페이스를 구현했으나 BaseAdapter 자체는 추상클래스이며, Adapter 인터페이스가 선언한 추상 메서드 4개를 구현하지 않고 남겨두었다. 이 추상메서드 4개를 우리가 직접 오버라이드해야 한다.
팁! alt + insert 를 누르면 다음처럼 generate 목록이 뜨는데, 이때 implement Methods를 선택하면 일괄 오버라이드가 가능하다.
![](https://t1.daumcdn.net/cfile/tistory/99FD7A425C99867912)
![](https://t1.daumcdn.net/cfile/tistory/998BC2425C99867916)
(4) MyAdapter.java
package com.sera.proj03listview;
import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView;
public class MyAdapter extends BaseAdapter {
private String[] textArray; private Context context;
MyAdapter(Context context, String... strings){ // 생성자 this.context = context; this.textArray = strings; }
@Override public int getCount() { // 전체 아이템의 개수 return textArray.length; }
@Override public Object getItem(int i) { return textArray[i]; }
@Override public long getItemId(int i) { return i; }
@Override public View getView(int i, View view, ViewGroup viewGroup) {
view = View.inflate(context, R.layout.item, null); TextView textView = view.findViewById(R.id.item_text_view); textView.setText(textArray[i]); return view; } }
|
- 생성자 : 생성자는 사용자 마음대로 정의해도 된다. 하지만 getView() 내부의 inflate() 인자로 Context가 들어가야해서 액티비티에게 Context를 받아오도록하는 인자를 선언해두었다. 'String...' 가변인자는 선택사항이다. 보통은 텍스트나 이미지를 한데 묶은 VO(Value Object) 클래스를 따로 정의하고 Activity단에서 ArrayList 형태로 넘겨준다.
- int getCount() : ListView에 넣을 아이템들의 개수다. 여기서는 배열의 원소 개수로 지정하였다.
- Object getItem(int i) : ListView의 아이템 중 i 번째 아이템을 리턴하도록한다. 이때 리턴자료형은 Object형이므로 어떠한 형태든 상관없지만 보통은 VO 단일 인스턴스를 리턴하도록한다. 여기서는 VO를 사용하지 않았으므로 String을 return 하였다.
- long getItemId(int i) : i번째 아이템의 id를 리턴한다. 이것은 사용자가 지정하는 id이기때문에 어떠한 정수를 넘겨주어도 괜찮다. 단 R에 등록되어있는 id가 있을 경우 해당 id를 리턴해주면 나중에 getId()를 통해 받아오기 쉽다.
- View getView(int i, View view, ViewGroup viewGroup) : 어댑터의 주인공 메서드다. 이곳에 ListView에 붙일 View를 생성한다. inflate()을 사용하여 View를 동적으로 생성하고 이를 리턴하도록한다. 그 사이 텍스트나 이미지, 배경 등을 세팅할 수 있다.
4. MainActivity 완성 (최종)
package com.sera.proj03listview;
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
ListView listView = findViewById(R.id.list_view); listView.setAdapter(new MyAdapter(this, "테스트1", "테스트2", "테스트3", "테스트4", "테스트5", "테스트6", "테스트7","테스트8", "테스트9", "테스트10"));
} }
|
결과
![](https://t1.daumcdn.net/cfile/tistory/998AAF485C998C0A17)
장점 : 다른 리스트형 뷰들에 비해 손쉽게 구현할 수 있다.
단점 : 스크롤링 기능이 내장되어있긴 하지만 아이템이 많아질 경우 아이템이 화면에 보일 차례가 될 때마다 매번 생성하므로 스크롤 시 딜레이가 발생한다. 이를 개선하기 위해서는 생성된 View를 버리지 않고 재사용하는 ViewHolder 패턴이 필요하다.