오늘이라도

[Android] 20. 리스트 뷰(List View) ② : 리스트 출력, 선택 항목 하이라이트, 항목 추가 본문

취업성공패키지 SW 개발자 교육/Android

[Android] 20. 리스트 뷰(List View) ② : 리스트 출력, 선택 항목 하이라이트, 항목 추가

upcake_ 2020. 6. 2. 10:32
반응형

https://github.com/upcake/Class_Examples

교육 중에 작성한 예제들은 깃허브에 올려두고 있습니다. 

gif 파일은 클릭해서 보는 것이 정확합니다.


 - 리스트 뷰(List View) ② : 리스트 출력, 선택 항목 하이라이트, 항목 추가 -

리스트뷰2 작동 화면

 

▼activity_main.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="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="추가"
        android:textSize="24sp" />

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:listSelector="@android:color/holo_blue_bright"/>

</LinearLayout>

 

▼MainActivity.java

package com.example.my27_listview2;

import androidx.appcompat.app.AppCompatActivity;

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

import java.util.ArrayList;

/*
1. DB를 만든다
2. DB의 테이블과 똑같은 DTO를 만든다
3. DTO에서 표현하고자 하는 부분을 xml로 만든다
4. 어댑터를 만든다
5. 어댑터에 3에서 만든 xml을 표시할 ViewHolder Class를 만든다
    5 - 1 : ViewHolder 작성
    5 - 2 : xml 찾기
    5 - 3 : getItem > Data 넣기
    5 - 4 : 필요한 메서드 만든다.

메인 액티비티 - 리스트 뷰(껍데기)
껍데기에 내용물을 만들어서 보여주는 것이 어댑터
 */

public class MainActivity extends AppCompatActivity {
    //객체 선언
    Button button1;
    ListView listView;

    ArrayList<SingerDTO> list;

    SingerAdapter adapter;

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

        //객체 초기화
        button1 = findViewById(R.id.button1);
        listView = findViewById(R.id.listView);

        list = new ArrayList<>();

        //어댑터의 list에 데이터 추가
        adapter = new SingerAdapter(MainActivity.this, list);
        adapter.addDTO(new SingerDTO("가수1", "010-1111-1111", 30, R.drawable.singer1));
        adapter.addDTO(new SingerDTO("가수2", "010-2222-2222", 21, R.drawable.singer2));
        adapter.addDTO(new SingerDTO("가수3", "010-3333-3333", 25, R.drawable.singer3));
        adapter.addDTO(new SingerDTO("가수4", "010-4444-4444", 33, R.drawable.singer4));
        adapter.addDTO(new SingerDTO("가수5", "010-5555-5555", 38, R.drawable.singer5));

        //리스트뷰에 어댑터를 붙여준다
        listView.setAdapter(adapter);

        //리스트뷰의 아이템 클릭했을때 이벤트 추가
        //AdapterView<?> parent : 클릭이 발생한 어댑터뷰
        //View view : 어댑터뷰 내부의, 클릭이 된 바로 그 뷰
        //int position : 어댑터 내부의 그 뷰의 위치(position)
        //long id : 클릭된 아이템의 row id
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SingerDTO dto = (SingerDTO) adapter.getItem(position);
                Toast.makeText(MainActivity.this, "선택 : " + position + "\n이름 : " + dto.getName()
                        + "\n전화번호 : " + dto.getPhoneNum() +"\n나이 : " + dto.getAge() + "\n이미지 : " +dto.getResId(), Toast.LENGTH_SHORT).show();
            }
        });

        //버튼1(추가 버튼)에 기능 추가
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = "가수6";
                String phoneNum = "010-6666-6666";
                int age = 35;
                int resId = R.mipmap.ic_launcher;

                SingerDTO dto = new SingerDTO(name, phoneNum, age, resId);
                adapter.addDTO(dto);
                //adapter.addDTO = (new SingerDTO(name, phoneNum, age, resId));
                //adapter.addDTO = (new SingerDTO("가수6", "010-6666-6666", 35, R.mipmap.ic_launcher);

                //리스트뷰 데이터 갱신
                adapter.notifyDataSetChanged();
            }
        });
    }
}

 

▼SingerAdapter.java

package com.example.my27_listview2;

import android.content.Context;
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 android.widget.Toast;

import java.util.ArrayList;

public class SingerAdapter extends BaseAdapter {
    //어댑터에 데이터를 받기위해 생성자 만든다.
    // 컨텍스트와 리스트는 받아오지만 인플레이터는 안받아온다.
    Context context;
    ArrayList<SingerDTO> list;

    LayoutInflater inflater;

    public SingerAdapter(Context context, ArrayList<SingerDTO> list) {
        this.context = context;
        this.list = list;

        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //인플레이터는 시스템에서 가져온다.
    }

    //리스트(list)에 항목을 추가해 줄 메서드 작성
    public void addDTO(SingerDTO dto) {
      list.add(dto);
    }

    //리스트의 항목을 삭제할 메서드 작성
    public void delDTO(int position) {
        list.remove(position);
    }

    //리스트의 항목을 모두 삭제할 메서드 작성
    public void removeDTOs() {
        list.clear();
    }

    //getCount() : 리스트에서 항목을 몇개나 가져와서 몇개의 화면을 만들 것인지 정하는 메서드
    @Override
    public int getCount() {
        return list.size();
    }

    //getItem() : 리스트에서 해당하는 인덱스의 데이터(사진, 이름, 전번)를 모두 가져오는 메서드
    //Object를 알아서 캐스팅해서 사용하라는 의미로 반환 타입이 Object
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        SingerViewHolder viewHolder;

        //화면 구성
        if(convertView == null) {
            convertView = inflater.inflate(R.layout.singerview, parent, false);
            viewHolder = new SingerViewHolder();
            viewHolder.tvName = convertView.findViewById(R.id.tvName);
            viewHolder.tvPhoneNum = convertView.findViewById(R.id.tvPhoneNum);
            viewHolder.imageView = convertView.findViewById(R.id.imageView);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (SingerViewHolder) convertView.getTag();
        }

        //DTO에서 데이터를 찾음
        SingerDTO dto = list.get(position);
        String name = dto.getName();
        String phoneNum = dto.getPhoneNum();
        int resId = dto.getResId();

        //XML의 화면에 찾은 데이터 표시
        viewHolder.tvName.setText(name);
        //viewHolder.tvName.setText(dto.getName()); // 이렇게 써도 같음
        viewHolder.tvPhoneNum.setText(phoneNum);
        viewHolder.imageView.setImageResource(resId);

        //이미지만 클릭했을때 번호, 이름만 표시되게 기능 추가
        viewHolder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, "선택 : " + position
                        + ", 이름 : " + list.get(position).getName(), Toast.LENGTH_SHORT).show();
            }
        });

        return convertView;
    }

    //따로 새 자바 파일을 만들지 않고 XML의 내용을 볼 수 있게끔 만든 클래스
    public class SingerViewHolder {
        public ImageView imageView;
        public TextView tvName, tvPhoneNum;
    }
}

 

▼SingerDTO.java

package com.example.my27_listview2;

public class SingerDTO {
    String name;
    String phoneNum;
    int age;
    int resId;

    public SingerDTO() {}

    public SingerDTO(String name, String phoneNum, int age, int resId) {
        this.name = name;
        this.phoneNum = phoneNum;
        this.age = age;
        this.resId = resId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getResId() {
        return resId;
    }

    public void setResId(int resId) {
        this.resId = resId;
    }
}

 

▼singerview.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/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/singer1"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvName"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:text="Name"
            android:textColor="@android:color/holo_green_light"
            android:textSize="35sp" />

        <TextView
            android:id="@+id/tvPhoneNum"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:text="PhoneNum"
            android:textColor="@android:color/holo_orange_light"
            android:textSize="25sp" />

    </LinearLayout>


</LinearLayout>
반응형