본문 바로가기
코리아 IT아카데미/android

10일차 | ListView

by Sharon kim 2022. 2. 28.

 

Windows + Alt + R을 눌러서 화면 녹화

 


코드추가

AndroidManifest.xml 

<uses-permission android:name="android.permission.INTERNET" />

build.gradle(Module:~) 

dependencies {
//glide
implementation 'com.github.bumptech.glide:glide:4.13.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
}

adapter>FoodListAdapter.java

package com.example.mylistview.adapter;

import android.content.Context;
import android.util.Log;
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 com.bumptech.glide.Glide;
import com.example.mylistview.R;
import com.example.mylistview.model.Food;

import java.util.ArrayList;

public class FoodListAdapter extends BaseAdapter {

    ArrayList<Food> data;
    Context context;

    public FoodListAdapter(ArrayList<Food> data, Context context) {
        this.data = data;
        this.context = context;
    }

    /* 전체 갯수를 알아야 adapter 가 조정할 수 있다. */
    @Override
    public int getCount() {
        return data.size();
    }

    /* 데이터 하나을 알려준다. */
    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    /* 목록의 각 행에 대한 고유한 ID를 정의하는 메소드를 구현합니다.*/
    @Override
    public long getItemId(int position) {
        return position;
    }


//    @Override
//    public View getView(int position, View convertView, ViewGroup parent) {
//        LayoutInflater inflater = LayoutInflater.from(context);
//        View itemView = inflater.inflate(R.layout.item_food, null);
//
//        ImageView imageView = itemView.findViewById(R.id.thumbnailImageview);
//        TextView titleTextView = itemView.findViewById(R.id.titleTextView);
//        TextView subTitleTextView = itemView.findViewById(R.id.subTitleTextView);
//        TextView detailTextView = itemView.findViewById(R.id.detailTextView);
//
//        Food food = data.get(position);
//
//        Glide.with(context)
//                .load(food.getThumbnail())
//                .centerCrop()
//                .into(imageView);
//
//        titleTextView.setText(food.getTitle());
//        subTitleTextView.setText(food.getSubTitle());
//        detailTextView.setText(food.getDetail());
//
//        Log.d("TAG", "getView 호출 :" + position);
//
//        return itemView;
//    }

    // 뷰홀더 개념을 이용해서 성능개선
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View itemView;
        FoodListViewHolder holder;
        // convertView 가 한번도 만들어 지지 않았다면
        if(convertView == null) {
            holder = new FoodListViewHolder();
            LayoutInflater inflater = LayoutInflater.from(context);
            itemView = inflater.inflate(R.layout.item_food, null);
            holder.imageView = itemView.findViewById(R.id.thumbnailImageview);
            holder.titleTextView = itemView.findViewById(R.id.titleTextView);
            holder.subTitleTextView = itemView.findViewById(R.id.subTitleTextView);
            holder.detailTextView = itemView.findViewById(R.id.detailTextView);
            // 중요 ~
            // 찾을 수 있도록 태그를 달아 놓는다.
            itemView.setTag(holder);
        } else {
            holder = (FoodListViewHolder) convertView.getTag();
            itemView = convertView;
        }

        Food food = data.get(position);

        Glide.with(context)
                .load(food.getThumbnail())
                .centerCrop()
                .into(holder.imageView);

        holder.titleTextView.setText(food.getTitle());
        holder.subTitleTextView.setText(food.getSubTitle());
        holder.detailTextView.setText(food.getDetail());

        return itemView;
    }
}


adapter>FoodListAdapter2.java

package com.example.mylistview.adapter;

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

public class FoodListAdapter2 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>FoodListViewHolder.java

package com.example.mylistview.adapter;

import android.widget.ImageView;
import android.widget.TextView;

public class FoodListViewHolder {
    ImageView imageView; // 주소 담겨 있다.
    TextView titleTextView;
    TextView subTitleTextView;
    TextView detailTextView;
}


decorator>BMW.java

package com.example.mylistview.decorator;

public class BMW implements ICar {

    int price;

    public BMW( int price) {
        this.price = price;
    }

    @Override
    public int getPrice() {
        return this.price;
    }

    @Override
    public void showPrice() {
        System.out.println("BMW 기본 가격은 " + this.price + " 입니다.");
    }
}

 

decorator>BMW3.java

package com.example.mylistview.decorator;

public class BMW3 extends BMWDecorator {

    public BMW3(ICar bmw, String modelName) {
        super(bmw, modelName, 2_000);
    }
}


decorator>BMW4.java

package com.example.mylistview.decorator;

public class BMW4 extends BMWDecorator {

    public BMW4(ICar bmw, String modelName) {
        super(bmw, modelName, 3_000);
    }
}


decorator>BMW5.java

package com.example.mylistview.decorator;

public class BMW5 extends BMWDecorator {

    public BMW5(ICar bmw, String modelName) {
        super(bmw, modelName, 4_000);
    }
}


decorator>BMWDecorator.java

package com.example.mylistview.decorator;

public class BMWDecorator implements ICar {

    protected ICar bmw;
    protected String modelName;
    protected int modelPrice;

    public BMWDecorator(ICar bmw, String modelName, int modelPrice) {
        this.bmw = bmw;
        this.modelName = modelName;
        this.modelPrice = modelPrice;
    }

    @Override
    public int getPrice() {
        return bmw.getPrice() + modelPrice;
    }

    @Override
    public void showPrice() {
        System.out.println(modelName + " 의 가격은 " + getPrice() + " 만원 입니다.");
    }
}


decorator>ICar.interface

package com.example.mylistview.decorator;

public interface ICar {

    int getPrice();
    void showPrice();
}


decorator>MainTest.java

package com.example.mylistview.decorator;

public class MainTest {

    public static void main(String[] args) {

        ICar bmw = new BMW(1_000);
        bmw.showPrice();

        // 3
        ICar bmw3 = new BMW3(bmw, "BMW3");
        bmw3.showPrice();

        // 4
        ICar bmw4 = new BMW4(bmw, "BMW4");
        bmw4.showPrice();

        // 5
        ICar bmw5 = new BMW5(bmw, "BMW5");
        bmw5.showPrice();
    }
}


model>DetailActivity.java

package com.example.mylistview;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.example.mylistview.model.Food;

public class DetailActivity extends AppCompatActivity {

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

        if (getIntent() != null) {
            // 역직렬화(Deserialization)
            // 직렬화한 데이터를 본래의 객체로 되돌리는 작업을 역직렬화라고 한다.
            Food food = (Food) getIntent().getSerializableExtra("serialOBJ");
            Log.d("TAG", food.getThumbnail());
            Log.d("TAG", food.getTitle());
            Log.d("TAG", food.getSubTitle());
            Log.d("TAG", food.getDetail());

            ImageView imageView = findViewById(R.id.thumbnailImageview);
            TextView titleTextView = findViewById(R.id.titleTextView);
            TextView subTitleTextView = findViewById(R.id.subTitleTextView);
            TextView priceTextView = findViewById(R.id.priceTextView);


            Glide.with(this)
                    .load(food.getThumbnail())
                    .centerCrop()
                    .into(imageView);

            titleTextView.setText(food.getTitle());
            subTitleTextView.setText(food.getSubTitle());
            priceTextView.setText(String.valueOf(food.getPrice()) + " 원");


        }

    }
}

 

model>MainActivity.java

package com.example.mylistview;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import com.example.mylistview.adapter.FoodListAdapter;
import com.example.mylistview.model.Food;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    // 리스트 뷰

    /*
    * 1. 리스트로 만들고 싶은 아이템 리스트를 준비한다. (xml, 데이터)
    * 2. 코드상에서 인플레이터를 준비해야 한다. (xml 을 메모리에 올리기 위함)
    * 3. 인플레이터로 아이템 하나의 해당하는 뷰를 만들어 준다.
    * 4. 위에서 만든 뷰를 컨테이너 뷰에 붙여준다.
    *
    * : 어댑터 를 이용한다.
    *
    * */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 데이터
        // 샘플 데이터 가져오기
        ArrayList<Food> foods = Food.getData();
        FoodListAdapter foodListAdapter = new FoodListAdapter(foods, this);
        ListView listView = findViewById(R.id.foodListView);
        listView.setAdapter(foodListAdapter);


        // 리스트 뷰에서 이벤트 리스너 사용방법
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Log.d("TAG", "selected Id : " + position);

                Intent intent = new Intent(view.getContext(), DetailActivity.class);
                intent.putExtra("serialOBJ", foods.get(position));
                startActivity(intent);
            }
        });

    }
}


activity_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".DetailActivity">

    <ImageView
        android:id="@+id/thumbnailImageview"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="@color/purple_200"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/titleTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        tools:text="[TOP 마트] 연어 스테이크 "
        android:textColor="@color/black"
        android:textSize="18dp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/thumbnailImageview" />

    <TextView
        android:id="@+id/subTitleTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        tools:text="노르웨이산 부드러운 연어 스테이크 입니다."
        app:layout_constraintStart_toStartOf="@id/titleTextView"
        app:layout_constraintTop_toBottomOf="@id/titleTextView" />

    <TextView
        android:id="@+id/priceTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        tools:text="16,000원"
        android:textColor="@color/black"
        android:textSize="18dp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="@id/titleTextView"
        app:layout_constraintTop_toBottomOf="@id/subTitleTextView" />

    <Button
        android:layout_margin="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundTint="@color/purple_200"
        android:text="구매하기"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <ListView
        android:id="@+id/foodListView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="match_parent"
        android:layout_height="0dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>


activity_food.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    xmlns:tools="http://schemas.android.com/tools">

    <ImageView
        android:id="@+id/thumbnailImageview"
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:maxWidth="120dp"
        android:minWidth="100dp"
        tools:src="@drawable/ic_launcher_background"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/textContainer"
        app:layout_constraintHorizontal_weight="1.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:gravity="center_vertical"
        android:id="@+id/textContainer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/detailTextView"
        app:layout_constraintHorizontal_weight="3"
        app:layout_constraintStart_toEndOf="@id/thumbnailImageview"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/titleTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:gravity="start|bottom"
            android:maxLines="2"
            tools:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy"
            android:textSize="20dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/subTitleTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:gravity="start|top"
            android:maxLines="2"
            tools:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy"
            android:textSize="16dp"
            android:textStyle="bold" />

    </LinearLayout>

    <TextView
        android:id="@+id/detailTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="detail"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="0.8"
        app:layout_constraintStart_toEndOf="@id/textContainer"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>