본문 바로가기
Android/Concepts

ListView 사용법

by JuHy_ 2019. 8. 21.

ListView란?

ListView는 리스트 형태의 데이터를 보여주기 위한 위젯이다.

따라서 list 형태의 원본 데이터가 있어야 하며 이를 adapter를 통해 각각의 아이템에 지정해준다.

이 때 어댑터는 데이터를 관리할 뿐만 아니라 뷰도 생성해준다.

이와 같은 형태로 쓰이는 위젯이 많기 때문에 리스트뷰를 통해 기본적인 사용법을 익히는 것이 좋다.

 

ListView 사용법

리스트뷰의 기본적인 구성은 다음과 같다.

 

1. 표현할 레이아웃 파일 내의 리스트뷰 객체

2. 아이템 각각의 구성을 표현할 레이아웃 파일

3. 데이터를 아이템에 지정해줄 어댑터

 

이 구성을 토대로 하나씩 만들어보자.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

먼저 액티비티의 레이아웃 파일에 리스트뷰를 추가한다.

다음으로 아이템의 구성을 정하기 위한 레이아웃 파일을 만들어보자.

 

<?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="wrap_content"
    android:weightSum="4"
    android:padding="10dp">

    <TextView
        android:id="@+id/textview_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <TextView
        android:id="@+id/textview_gender"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <TextView
        android:id="@+id/textview_phone"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"/>

</LinearLayout>

고객의 정보(이름, 성별, 전화번호)를 표현하기 위한 TextView 3개를 넣어주었다.

 

그 다음으로 데이터를 ArrayList에 저장하기 위한 Customer 클래스를 만들어주자.

public class Customer {

    String name;
    String phone;
    String gender;
    
    Customer(String name, String phone, String gender){
        this.name = name;
        this.phone = phone;
        this.gender = gender;
    }
    
}

이름, 성별, 전화번호 변수와 이를 초기화하기 위한 생성자까지 만들어주었다.

 

이제 데이터를 각각의 View에 연결시켜줄 어댑터를 만들어보자.

 

public class MyListViewAdapter extends BaseAdapter {

    ArrayList<Customer> items;
    Context context;

    public MyListViewAdapter(ArrayList<Customer> items, Context context){
        this.items = items;
        this.context = context;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Object getItem(int i) {
        return items.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.item_customer, viewGroup, false);

        TextView tv_name = view.findViewById(R.id.textview_name);
        tv_name.setText(items.get(i).name);

        TextView tv_gender = view.findViewById(R.id.textview_gender);
        tv_gender.setText(items.get(i).gender);

        TextView tv_phone = view.findViewById(R.id.textview_phone);
        tv_phone.setText(items.get(i).phone);

        return view;
    }

}

BaseAdapter라는 클래스를 상속받아 MyListViewAdapter를 만들어보자.

 

먼저 아이템들의 데이터를 저장할 ArrayList와 Context 객체를 만들고

생성자를 통해 액티비티로부터 받아와 넣어주도록 했다.

 

그 다음으로는 기본적으로 만들어야 할 함수들을 정의해준다.

먼저 getCount()는 데이터의 갯수를, getItem은 i번째 아이템을 getItemId는 i번째 아이템의 아이디를 반환하도록 한다.

마지막으로 getView() 함수에 i번째 아이템을 어떻게 보여줄 것인지 지정해야 한다.

LayoutInflater를 통해 레이아웃 파일을 객체화하고 그 안의 TextView들의 내용을 설정해주었다.

 

마지막으로 리스트뷰 객체와 어댑터를 연결해주면 된다.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView listview = findViewById(R.id.listview);

        ArrayList<Customer> items = new ArrayList<>();
        items.add(new Customer("고객 1", "010-1234-5678", "남자"));
        items.add(new Customer("고객 2", "010-4321-8765", "남자"));
        items.add(new Customer("고객 3", "010-8765-4321", "여자"));

        MyListViewAdapter adapter = new MyListViewAdapter(items, getApplicationContext());

        listview.setAdapter(adapter);

    }

}

리스트뷰 객체를 만들고, 표현할 데이터도 만들어주었다.

그 다음 우리가 만든 어댑터를 불러와 데이터와 Context를 넘겨주었다.

그리고 이 어댑터를 리스트뷰에 setAdapter() 함수를 통해 지정해주었다.

 

이제 실행해보면 위와 같이 정보가 순서대로 잘 나타나고 있는 것을 볼 수 있다.

 

그렇다면 아이템을 클릭했을 때의 이벤트 처리는 어떻게 할까.

이는 액티비티의 리스트뷰 객체의 onItemClickListener를 지정하여 처리할 수 있다.

listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
    @Override
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {

        items.remove(i);
        adapter.notifyDataSetChanged();

        Toast.makeText(getApplicationContext(), i+"번째 아이템이 삭제되었습니다", Toast.LENGTH_SHORT).show();

        return true;
    }
});

위의 코드는 아이템을 길게 눌렀을 때 해당 아이템을 삭제하는 코드이다.

함수의 파라미터로 들어오는 i값을 통해 몇번째 아이템이 클릭되었는지 알 수 있다.

이를 이용하여 아이템이 길게 눌렸을 때 ArrayList의 i번째 값을 삭제해주고,

어댑터에 notifyDataSetChanged() 함수를 통해 데이터가 변경되었음을 알려 리스트뷰를 다시 불러온다.

 

첫번째 아이템을 길게 눌렀더니 정상적으로 아이템이 삭제된 것을 볼 수 있다.

 

※ 이처럼 리스트뷰를 통해 보여줄 데이터는 해당 ArrayList를 통해 관리하여야 한다.

리스트뷰는 스크롤 시 화면에 보이지 않는 부분은 없애고 보여질 부분은 새로 생성하기 때문에

예를 들어 checkbox에 체크했던 것이 스크롤 시 사라지는 등 의도와는 다르게 작동할 수 있다.

따라서 리스트뷰에 표시될 모든 내용은 데이터가 변경될 때마다 ArrayList에 저장하여 데이터를 잃지 않도록 주의하자.

또한 스크롤 할 때마다 View를 새로 생성하기 때문에 ViewHolder 등을 사용하여 메모리를 절약하는 것이 좋다.

 

 

Reference

[부스트코스]안드로이드 프로그래밍

https://www.edwith.org/boostcourse-android

'Android > Concepts' 카테고리의 다른 글

GridView 사용법  (0) 2020.03.24
Spinner 사용법  (0) 2020.03.24
Inflation과 Layout Inflater  (1) 2019.08.09
Button을 상속받아 커스텀 Button 만들어보기  (0) 2019.08.08
나인패치(Nine Patch) 이미지란?  (0) 2019.08.08