[Android] 안드로이드 Adapter와 AdapterView, BaseAdapter (2)

Android/Android · 2020. 6. 11. 03:57
반응형

https://survivalcoding.com/p/android_basic

 

될 때까지 안드로이드

될 때까지 안드로이드에 수록된 예제의 라이브 코딩 해설

survivalcoding.com

위 서적을 참고하였습니다.

 

 

 

 이번 포스트에서는 BaseAdapter를 활용해서 리스트에 더욱 다양한 기능을 추가하는 방법을 소개하겠습니다.

 

 먼저 지난 시간에 작성했던 소스들을 준비해 주시고, 모델 클래스를 하나 만들기 위해 Weather.java 파일을 하나 생성해 줍니다. 그리고 다음과 같은 코드를 삽입합니다.

 

 모델 클래스gettersetter를 구현하는 코드입니다. 이를 하는 이유는 캡슐화 때문인데요, 캡슐화를 간단히 설명하자면 외부에서 변수에 직접적으로 접근을 하지 못하게 만드는 기법입니다. 

 

package hello.world.study_adapter;

public class Weather {
    private String city, temp, weather;
}

 

이제 여기서 클래스 내부에 [Alt] + [Insert]를 누르게 되면 다음과 같은 장면이 나옵니다.

 

[Alt] + [Insert]

 

여기서 저희는 getter and setter를 만들어 줄 거기 때문에 getter and setter를 클릭합니다.

 

모두 선택

 

 그러면 위와 같은 화면이 뜰 것입니다. 우리는 모두 사용할 것이기 때문에 모두 선택해 주시고, OK를 눌러주시면

 

package hello.world.study_adapter;

public class Weather {
    private String city, temp, weather;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }
}

 

 이렇게 자동적으로 getter와 setter가 구현이 됩니다. 이와 같은 방법으로 생성자(Constructor)도  생성해 주세요. 제일 위에 있습니다.

 

 자, 이제 커스텀 어댑터를 구현해 봅시다. 먼저 커스텀 어댑터를 사용하려면 BaseAdapter를 상속받아야 합니다.(굳이 상속받지 않는 방법도 있는데 지금은 상속을 받아서 구현하겠습니다.)  AdapterActivity.java 파일을 생성해 줍니다. 그리고 클래스 이름 옆에 BaseAdapter를 상속받습니다. ( public class AdapterActivity extends BaseAdapter ) 그리고 빨간 줄 그인 부분에 [ Alt + Enter ] 를 눌러 필요 파일들을 import를 해주면 다음과 같이 소스코드가 작성됩니다.

 

AdapterActivity.java

package hello.world.study_adapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class AdapterActivity extends BaseAdapter {
    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}

 

자 이제 커스텀 레이아웃을 만들어 보겠습니다. adapter_view 레이아웃 파일을 생성해 줍니다.

 

adapter_view.xml

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

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@mipmap/ic_launcher"/>

    <LinearLayout
        android:orientation="vertical"
        android:layout_gravity="center"
        android:padding="8dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        <TextView
            android:id="@+id/city_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30dp"
            android:text="도시명"/>
        
        <TextView
            android:id="@+id/temp_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="end"
            android:text="기온"
            android:textSize="8dp"/>
        
    </LinearLayout>
</LinearLayout>

 

adapter.xml 결과

 

 자 그러면 다음과 같은 사진의 결과물이 나올 건데요, 이를 activity_main.xml에 적용시키는 방법은 ListView 항목에 tools:listitem="@layout/adapter_view" 를 지정해주면 다음과 같이 나옵니다.

 

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@layout/adapter_view"/>

ListView 적용

 

 여기까지 잘 나오면 이제 중간단계까지 성공입니다. 이제 이것들을 가지고 한 번 꾸며보겠습니다.

 

 이제 ImageView에 들어갈 사진 파일들을 추가할텐데요, 제가 사용하는 사진 올려둘 테니 사용하실 분들은 사용하셔도 됩니다.(글 하단부에 있습니다.) 사진 파일들이 준비가 되셨으면 res/drawable에 투척해주세요.

 

 

사진 파일들

 여기서 주의하실 점들은 파일 형식은 png, 파일 이름은 무조건 소문자로만 이루어져야 합니다. 그렇지 않으면 나중에 빌드할 때 에러가 발생하니 이 점 꼭 유의하시기 바랍니다.

 

 이제 코드를 작성해야하는데요, MainActivity에 가서 다음과 같은 코드를 작성해주세요.

 

package hello.world.study_adapter;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    //Weather 클래스 사용
    ArrayList<Weather> arrayList;
    //AdapterActivity adapter 객체 생성
    AdapterActivity arrayAdapter;
    ListView listView;

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

        arrayList = new ArrayList<>();
        //arrayList에 항목 추가
        arrayList.add(new Weather("서울", "26도", "맑음"));
        arrayList.add(new Weather("부산", "28도", "맑음"));
        arrayList.add(new Weather("대구", "25도", "비"));
        arrayList.add(new Weather("경기도", "66도", "구름"));
        arrayList.add(new Weather("가평", "27도", "구름"));
        arrayList.add(new Weather("울산", "28도", "맑음"));
        arrayList.add(new Weather("남양주", "24도", "맑음"));
        arrayList.add(new Weather("인천", "25도", "비"));

        //Adapter생성
        arrayAdapter = new AdapterActivity(arrayList);

        listView = (ListView) findViewById(R.id.list_view);
        //ListView에 Adapter연결
        listView.setAdapter(arrayAdapter);



        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, position+ "번째 Item", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

 

그리고 AdapterActivity에 가셔서 아래 코드와 같이 작성합니다.

 

package hello.world.study_adapter;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AdapterActivity extends BaseAdapter {

    private final List<Weather> Data;
    private Map<String, Integer> WeatherImageMap;

    // 생성자 생성
    public AdapterActivity(List<Weather> data) {
        Data = data;
        WeatherImageMap = new HashMap<>();
        //받아온 값대로 사진파일 설정
        WeatherImageMap.put("맑음", R.drawable.sun);
        WeatherImageMap.put("비", R.drawable.rain);
        WeatherImageMap.put("구름", R.drawable.cloud);
    }

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

    @Override
    public Object getItem(int position) {
        return Data.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        //초기에는 convertview가 null값을 가짐
        //ViewHolder에 등록해서 화면에 다시 layout을 그리는 일 방지
        if(convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_view, parent, false);

            ImageView imageView = (ImageView) convertView.findViewById(R.id.image_view);
            TextView city_view = (TextView) convertView.findViewById(R.id.city_view);
            TextView temp_view = (TextView) convertView.findViewById(R.id.temp_view);

            holder.imageView = imageView;
            holder.city_view = city_view;
            holder.temp_view = temp_view;

            convertView.setTag(holder);
        }
        //null이 아니면 이미 viewholder에 등록되있어서 Tag를 가져옴
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        Weather weather = Data.get(position);
        holder.city_view.setText(weather.getCity());
        holder.temp_view.setText(weather.getTemp());
        holder.imageView.setImageResource(WeatherImageMap.get(weather.getWeather()));
        //화면 출력
        return convertView;
    }

    static class ViewHolder {
        ImageView imageView;
        TextView city_view, temp_view;
    }
}

 

 자, 여기까지 잘 따라오셨으면 다음과 같은 앱이 실행됩니다.

 

결과

 

 잘 나왔죠? 여기까지 하는데 무리 없이 잘 따라오셨을 거라 믿습니다. 코드를 작성하는데 궁금한 점이 있으시다면 댓글로 남겨주시구요. 

 

 다음번에는 이제 AdapterView를 마무리 짓는 간단한 알람 앱을 만들어 보겠습니다. 이것이 실제로 알람이 울리거나 하지는 않습니다. 왜냐하면 요즘 안드로이드 트렌드, 그리고 구글이 권장하는 것은 RecyclerView이기 때문에 기본적인 레이아웃 디자인만 해 볼 것입니다. AdapterView를 다시 한번 구현해 보면서 마무리 짓고, 다양한 기능을 추가해 보면서 앱을 개발할 수 있는 능력(?)을 기를 수 있습니다. 기본적인 레이아웃은 다음과 같습니다.

 

 

 

알람 앱

 

 

 저번 포스트에서도 잠시 출현했었는데, 이제는 이것을 만들어 볼 겁니다. 이제 이 정도는 정말 쉬울 것 같지 않나요? 그럼 다음 포스트에서 뵙겠습니다.

 

감사합니다.

 

 

cloud.png
0.02MB
rain.png
0.02MB
sun.png
0.02MB

반응형