앱 만들기/안드로이드

커스텀 어댑터 뷰를 활용한 리스트뷰 구현하기-2

나도 처음이야 2022. 2. 15.

https://soo0100.tistory.com/1731

 

커스텀 어댑터 뷰를 활용한 리스트뷰 구현하기-1

https://soo0100.tistory.com/1716 안드로이드 어댑터 뷰 기초(리스트 뷰 만들기) https://soo0100.tistory.com/1713 스크롤 뷰 만들기 와 주의사항 화면에 넘치는 데이터를 처리하는 것 중 가장 기본적인 것이 바..

soo0100.tistory.com

지난 시간, 리스트 뷰의 화면과 데이터 구성을 모두 마쳤다.

오늘은 해당 데이터를 커스텀 어댑터 뷰 에 연결하고, 리스트 뷰와 어댑터를 연결하겠다.

3. 데이터 와 어댑터 를 연결한다.

우리가 만든 리스트 뷰는 이미지와 텍스트 데이터를 담고 있다.

개발자가 원하는 어댑터 뷰를 만들기 위해서는 BaseAdapter 클래스를 상속하여 필수 implements 함수들을 구현해주어야 한다.  커스텀 어댑터뷰를 구현하기 전에 리스트 한칸 한칸에 대한 사용자 지정 레이아웃을 설정해야 한다.

커스텀 어댑터 뷰는 리스트 전체를 그리는 것이 아닌 화면에 갱신되는 리스트들 만 화면에 그린다.

그렇기에 그 한칸 한칸에 대한 레이아웃 파일을 개발자가 구현 해주어야 한다.

레이아웃 구성에서 주의할점은 리스트 한줄에 대한 구성이므로, 부모 레이아웃의  android:layout_height 를 "wrap_content" 로 설정해야 한다.

<?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="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/weather_image"
        android:layout_width="89dp"
        android:layout_height="125dp"
        app:srcCompat="@drawable/images" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/city"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="city"
            android:textAlignment="center"
            android:textSize="34sp" />

        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="temp"
            android:textAlignment="center"
            android:textSize="34sp" />
    </LinearLayout>
</LinearLayout>

위 레이아웃을 바탕으로 구현된 커스텀 어댑터 뷰의 모습은 하기와 같다.

public class BaseAdapterTest extends BaseAdapter {

    private final List mData;

    public BaseAdapterTest(List mData) {
        //생성자에서 List에 담길 데이터 내용을 담는다.
        this.mData = mData;
    }

    @Override
    // 데이터의 개수를 알수 있다.
    public int getCount() {
        // 데이터의 개수는 어댑터 뷰의 아이템 개수가 된다.
        return mData.size();
    }

    @Override
    // i 번째의 아이템이 무엇인지 알수 있도록 해주는 메소드
    public Object getItem(int i) {
        // i 번째의 데이터를 반환한다.
        return mData.get(i);
    }

    @Override
    // i 번째의 ID를 알수를 있다. 일반 리스트에서는 i 값과 동일함.
    public long getItemId(int i) {
        return i; // 단, SQL 이라면 DB ID를 반환하다.
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        //Activity 이외의 클래스에서 컨텍스트를 통해서 레이아웃을 가져온다.
        view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.weather_item, viewGroup, false);
        ImageView image = view.findViewById(R.id.weather_image);
        TextView city = view.findViewById(R.id.city);
        TextView temp = view.findViewById(R.id.temp);

        Weather weather = (Weather)mData.get(i);
        city.setText(weather.getCity());
        temp.setText(weather.getTemp());
        return view;
    }
}

커스텀 어댑터 클래스의 중요한 함수는 getView() 함수이다.

이 함수에선 화면에 보여지는 리스트 하나 하나의 데이터를 보여준다.

지금 화면에 보여지는 데이터가 6개라면 6번이 호출된다.

스크롤을 하기로 내리면, 광주, 대구, 부산, 제주도가 나온다.

이때는 위 4개의 도시명 만큼만 getView()함수가 호출된다. 즉, 화면에 갱신되는 내용만 그려주기에 자원의 절약적인 측면에서도 효율적이다.

 

이처럼, 각각의 데이터를 불러와서 리스트뷰 한칸 한칸의 화면에 그려주어야 한다.

그렇기에 한칸 한칸에 대한 레이아웃을 인플레이트 해서 리스트에 데이터를 매칭해주어야 한다.

하기 코드는 액티비티가 아닌 일반 클래스에서 레이아웃을 로드하는 방법이다.

view = LayoutInflater.from(viewGroup.getContext())
        .inflate(R.layout.weather_item, viewGroup, false);

해당 view 를 이용해서, 인플레이트 한 레이아웃 안의 객체들에 접근이 가능하다.

ImageView image = view.findViewById(R.id.weather_image);
TextView city = view.findViewById(R.id.city);
TextView temp = view.findViewById(R.id.temp);

그런 다음, 데이터 리스트를 불러와서 리스트 화면에 매핑(설정) 하는 작업을 한다.

Weather weather = (Weather)mData.get(i);
city.setText(weather.getCity());
temp.setText(weather.getTemp());
return view;

데이터 와 어댑터뷰의 연결이 완료되었다.

물론, 커스텀 어댑터뷰 객체를 MainAcitivy 에서 인스턴스 시켜줘야 한다.

public class MainActivity extends AppCompatActivity {

    ListView listView;
    ArrayList<Weather>data = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ///임시 데이터 만들기.
        data.add(new Weather("서울","8도","맑음"));
        data.add(new Weather("인천","5도","맑음"));
        data.add(new Weather("수원","7도","맑음"));
        data.add(new Weather("오산","8도","맑음"));
        data.add(new Weather("대전","7도","맑음"));
        data.add(new Weather("전주","6도","맑음"));
        data.add(new Weather("광주","5도","맑음"));
        data.add(new Weather("대구","8도","맑음"));
        data.add(new Weather("부산","9도","맑음"));
        data.add(new Weather("제주도","10도","맑음"));

        BaseAdapterTest baseAdapterTest = new BaseAdapterTest(data);

    }
}

데이터 와 커스텀 어댑터뷰의 연결이 완료되었다.

그리고 커스텀 어댑터뷰 내부에서 실제 리스트에 쓰여질 데이터 매핑도 마친 상태이다.

이제는 메인 액티비티에서 리스트뷰의 어댑터 설정만 남았다.

4. 리스트 뷰의 setAdapter 함수를 사용해서 뷰와 어댑터를 연결한다.

listView = (ListView)findViewById(R.id.listview);
listView.setAdapter(baseAdapterTest);

 

고정 데이터 이지만, 제법 그럴싸한 리스트 뷰가 완성되었다.

감사합니다.

 

 

반응형

댓글