[ 실행 화면 (추가버튼 누를때마다 추가됨) ]
11번째 강의... recyclerView에 대해서 공부하고 구현해보기..
원래 카메라 강의가 있었는데 5년전 강의이기도 하고 그동안 업데이트된 목록이 많다보니 ㅠㅠ
카메라는 구현하고 따라하는데 좀 어려움이 있을 것 같아서 다음 강좌인 recyclerView를 듣게되었다.
근데 갑자기 난이도가 팍 올라가버린 느낌...
강의 + 다른 분 블로그까지 같이 보면서 이해를 해야했다.
나뿐만 아니라 댓글도 갑자기 강의 난이도가 올라갔다고 ㅠㅠ 안드로이드 강의가 다 그런 느낌이라고 했다.
어쨌든 시작해보기..
※ RecyclerView란 무엇인가?
ListView : 스크롤을 할 때 마다 화면 가장 위 아이템 삭제, 가장 아래에 아이템 생성
아이템을 삭제 및 생성하는 횟수가 늘어날수록 cost가 높아진다.
RecyclerView : 가장 위 아이템을 삭제하지 않고 아래로 재활용한다.
즉 아이템의 데이터만 수정하고 View 자체는 재활용하는 구조이다.
새로운 View 객체를 생성하지 않음 → ListView 대비 많은 cost를 아낄 수 있다.
※ RecyclerView의 구성 요소
RecyclerView는 데이터 목록을 아이템 단위의 View로 생성해서 화면에 표시하기 위해 Adapter를 사용한다.
Adapter에 의해 생성된 View 객체를 어떤 방식으로 나열할지 결정하기 위해 Layout Manager를 사용한다.
Layout Manager가 제공하는 형태로 Adapter가 생성한 View를 ViewHolder 객체에 저장되어 화면에 표시
1) RecyclerView
2. Adapter
3. LayoutManager
4) ViewHolder
※ 홍드로이드 강의 RecyclerView 예제
( 이미지 뷰 1 + 텍스트 뷰 2 로 구성된 아이템 )
- 추가 Button을 누르면 아이템 View 생성하고 RecyclerView에 표시
- 아이템 View를 누르면 아이템 명이 Toast로 나타남
- 아이템 View를 길게 누르면 아이템이 삭제됨
1. activity_main.xml (RecyclerView를 추가)
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarFadeDuration="0"
android:scrollbarSize="5dp"
android:scrollbarThumbVertical="@android:color/darker_gray"
android:scrollbars="vertical"
android:layout_weight="1">
</androidx.recyclerview.widget.RecyclerView>
<Button
android:id="@+id/btn_add"
android:layout_weight="8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="추가하기 버튼"/>
</LinearLayout>
<!--activity_drawer layout을 포함시켜라의 include-->
<!--즉 main.xml에서 activity_drawer을 연결시킨것-->
2. build.gradle.kts (app)
plugins {
alias(libs.plugins.android.application)
}
android {
namespace = "com.example.webviewexample"
compileSdk = 34
defaultConfig {
applicationId = "com.example.webviewexample"
minSdk = 27
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
implementation(libs.recyclerview)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
}
RecyclerView를 사용하기 위해서 build.gradle.kts (app)에서 추가해 줄 부분이 있다.
버전과 강의마다 달라서 우선은 홍드로이드 강의 참고하기...
링크는 제일 하단에 첨부하겠다.
3. item_list.xml (RecyclerView 아이템 View Layout)
<?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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="안드로이드 소정"/>
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="recyclerView"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- android:gravity="center_vertical" : 세로로 가운데 정렬-->
RecyclerView 아이템에 표시될 아이템 View Layout을 xml로 따로 만들어준다.
ImageView 1개와 TextView 2개로 구성되어있다.
4. MainData.java / 클래스로 정의해서 변경이 용이하도록 구성
관련 내용도 강의를 참고하면서 보는게 좋을듯..
package com.example.webviewexample;
public class MainData {
private int iv_profile;
//이미지뷰는 int로 선언해야함
private String tv_name;
private String tv_content;
public MainData(int iv_profile, String tv_name, String tv_content) {
this.iv_profile = iv_profile;
this.tv_name = tv_name;
this.tv_content = tv_content;
}
public int getIv_profile() {
return iv_profile;
}
public void setIv_profile(int iv_profile) {
this.iv_profile = iv_profile;
}
public String getTv_name() {
return tv_name;
}
public void setTv_name(String tv_name) {
this.tv_name = tv_name;
}
public String getTv_content() {
return tv_content;
}
public void setTv_content(String tv_content) {
this.tv_content = tv_content;
}
}
5. MainAdapter.java
RecyclerView에서는 개발자가 Adapter를 직접 구현해야 한다.
이때 새로 만드는 Adapter는 RecyclerView.Adapter를 상속해야한다.
아래는 Adapter를 상속해서 새로 만들때 오버라이드가 필요한 메서드이다.
메소드 | 설명 |
onCreateViewHolder(ViewGroup parent, int view Type) | viewType 형태의 아이템 View를 위한 ViewHolder 객체 생성 |
onBindViewHolder(ViewHolder holder, int position) | position에 해당하는 데이터를 ViewHolder의 아이템 View에 표시 |
getItemCount() | 전체 아이템 개수 리턴 |
package com.example.webviewexample;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.CustomViewHolder> {
//리스트 배열 담을 ArrayList만들기
private ArrayList<MainData> arrayList;
public MainAdapter(ArrayList<MainData> arrayList) {
this.arrayList = arrayList;
}
@NonNull
@Override
//리스트뷰가 처음 생성될때의 생명주기
public MainAdapter.CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//아이템 뷰를 위한 뷰홀더 객체를 생성하여 리턴
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
CustomViewHolder holder = new CustomViewHolder(view);
return holder;
}
@Override
//position에 해당하는 데이터를 뷰홀더의 아이템뷰에 표시
//실제 item이 화면에 추가될때의 동작
public void onBindViewHolder(@NonNull MainAdapter.CustomViewHolder holder, int position) {
holder.iv_profile.setImageResource(arrayList.get(position).getIv_profile());
holder.tv_name.setText(arrayList.get(position).getTv_name());
holder.tv_content.setText(arrayList.get(position).getTv_content());
//태그 지정
holder.itemView.setTag(position);
//아이템 view가 클릭됐을때 아이템 명 띄우기 (토스트)
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//클릭된 item의 이름 가져오기
String curName = holder.tv_name.getText().toString();
//activity가 아니라 view로부터 가져오기
Toast.makeText(view.getContext(), curName, Toast.LENGTH_SHORT).show();
}
});
//아이템 view가 길게 클릭되면 item 제거
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
remove(holder.getAdapterPosition());
return true;
}
});
}
//전체 데이터 개수 리턴
@Override
public int getItemCount() {
return (null != arrayList ? arrayList.size() : 0);
}
//item 제거
public void remove(int position) {
try {
arrayList.remove(position); //제거
notifyItemRemoved(position); //새로고침
//notify는 새로고침의 느낌
} catch(IndexOutOfBoundsException ex) {
ex.printStackTrace();
}
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
protected ImageView iv_profile;
protected TextView tv_name;
protected TextView tv_content;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
this.iv_profile = itemView.findViewById(R.id.iv_profile);
this.tv_name = itemView.findViewById(R.id.tv_name);
this.tv_content = itemView.findViewById(R.id.tv_content);
}
}
}
6. MainActivity.java
package com.example.webviewexample;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ArrayList<MainData> arrayList;
private MainAdapter mainAdapter;
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//RecyclerView에 LinearLayoutManager 객체를 지정
recyclerView = findViewById(R.id.rv);
linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
arrayList = new ArrayList<>();
//RecyclerView에 mainAdapter 객체를 지정
mainAdapter = new MainAdapter(arrayList);
recyclerView.setAdapter(mainAdapter);
Button btn_add = findViewById(R.id.btn_add);
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MainData mainData = new MainData(R.mipmap.ic_launcher, "안드로이드 소정", "recyclerView");
arrayList.add(mainData);
mainAdapter.notifyDataSetChanged();
}
});
}
}
지금도 아무생각없이 그냥 보면 이게 무슨 코드지..? 해서..
익숙해지기 전까지는 계속 강의랑 같이 보면서 코딩해야 할 것 같다.
이렇게 RecyclerView를 만들었으면 java 파일에서 구현한 것 처럼
- 추가 Button을 누르면 아이템 View 생성하고 RecyclerView에 표시
- 아이템 View를 누르면 아이템 명이 Toast로 나타남
- 아이템 View를 길게 누르면 아이템이 삭제됨
의 기능이 제대로 구현되는지 확인할 것!
[ 참고 강의 ]
https://www.youtube.com/watch?v=kNq9w1_nhL4&list=PLC51MBz7PMyyyR2l4gGBMFMMUfYmBkZxm&index=13
'안드로이드 스튜디오' 카테고리의 다른 글
[안드로이드 스튜디오] 폰트(font) 바꾸기 (3) | 2024.09.05 |
---|---|
[안드로이드 스튜디오] 앱만들기 #10. Navigation Menu 커스텀 (0) | 2024.09.03 |
[안드로이드 스튜디오] 앱만들기 #9. WebView (0) | 2024.09.03 |
[안드로이드 스튜디오] 앱만들기 #8. SharedPreferences (0) | 2024.08.29 |
[안드로이드 스튜디오] + ActionBar에 Menu 추가하기 (1) | 2024.08.29 |