https://github.com/lnjky/fashion_people
GitHub - lnjky/fashion_people: 패션 추천 어플
패션 추천 어플. Contribute to lnjky/fashion_people development by creating an account on GitHub.
github.com
코드 전체를 보려면 위에 링크를 통해 확인할 수 있습니다.
리사이클러뷰는 리스트뷰와 유사한 형태이지만 좀 더 개선된 위젯이다.
리스트뷰의 경우 스크롤을 내릴 때 화면에 보여지지 않는 객체들은 삭제되고 아래에 추가로 객체가 드러나는 형식을 사용하지만 리사이클러뷰는 화면에 보여지지 않는 객체들이 진행방향으로 재활용되어 나타난다.
이 사진을 보면 확실히 이해가 쉽다.
리스트뷰의 경우 스크롤을 아래로 내릴 경우 화면에서 떨어지는 객체들, 1, 2객체들은 제거가되고 9,10은 추가가 된다.
반면 리사이클러뷰의 경우 화면에서 보이지 않는 객체들이 재사용되어 스크롤을 내렸을 때 보여준다.
이론은 간단하게 설명하고 내가 직접 작성했던 코드들을 통해 만드는 방법을 설명하려고 한다.
우선 리사이클러뷰를 만들기 위해서는 라이브러리를 Implement해야 한다.
//RecyclerView
implementation "androidx.recyclerview:recyclerview:1.1.0"
build.gradle에 위의 문장을 추가하고 Sync해주도록 하자.
먼저 리사이클러뷰를 만들기 위해서는 Model / Adapter / Activity 총 3가지를 만들어주어야 한다.
여기서는 Model -> Adapter -> Activity 순으로 최상단의 Github에 올려둔 코드를 바탕으로 설명하고자 한다.
우선 모델부터 설명하도록 하겠다.
코드는 Github의 게시판 역할을 하기 위해 작성한 BoardFragment와 board, boardAdapter이다.
우선 Java Class파일을 만든다.
models 폴더를 생성하고 그 안에 클래스 파일을 만들었는데 이렇게 만든 이유는 우선 보기 편하고 여러개의 리사이클러뷰를 만들 때 관리하기 쉽기 때문이다.
이렇게 하면 이제 코드를 입력해 주면 되는데 먼저 리사이클러뷰에 나타날 변수들을 선언해준다.
나는 게시판을 만들기 위해서 사용될 변수들을 선언해주었다.
작성한 사용자의 documentID, 제목, 내용, 닉네임, 저장될 collectionId, 시간을 표현할 timestamp.
타임스탬프는 작성한 날짜를 저장하기 위해서 추가해주었다.
그리고 Alt + Insert를 누르면 여러개가 나오는데
여기서 우리는 Constructor / Getter and Setter / toString()을 만들어줄 것이다.
먼저 첫번째로 Constructor를 만들어주는데 여기서 Select None을 눌러서 한번, 전부 눌러서 한번 총 2번 만든다.
빈 생성자를 만들지 않으면 작동하지 않아서 꼭 Select None으로 한번 전부 선택해서 한번 만들어 준다.
두번째로 Getter and Setter를 만들어준다.
Getter와 Setter는 각각 데이터를 받아오고 세팅해주는 역할을 한다.
Adapter에서 사용할 것이기 때문에 빠져서는 안된다.
이렇게 나오는데 전부 선택하고 OK를 눌러주면 된다.
그리고 마지막으로 toString()을 만들어준다.
이렇게 전부 선택해주고 만들어주면 모델은 전부 만든 것이다.
그러면 다음으로 Adapter이다.
어댑터는 리사이클러뷰를 모델과 연결지어주는 중간다리 역할을 한다.
우선 자바 클래스파일을 만들어준다. 나는 이름을 boardAdapter로 adapter 패키지(폴더) 안에 생성해주었다.
그러며 이렇게 되어있는데 여기에 뒤에 내용을 붙여준다.
public class boardAdapter extends RecyclerView.Adapter<boardAdapter.boardViewholder> {
}
이렇게 뒤에 extends 이후로 붙여주면 된다.
위는 예시의 경우이기 때문에어댑터의 이름에 따라 boardAdatper / boardViewholder의 이름을 수정해주면 된다.
여기서 boardViewholder에서 Alt + Enter 해서 Import Method를 해준다.
여기있는 메소드를 다 생성해주고 빨간줄이 생기는 경우 전부 Alt + Enter를 해서 지워주면 된다.
그러면 이렇게 된다. 그 후 생성자와 리스트를 선언해준다.
private List<board> datas;
//어댑터에 대한 생성자
public boardAdapter(List<board> datas) {
this.datas = datas;
}
그리고 onCreateViewHolder의 return값을 바꿔준다.
@NonNull
@Override
public boardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new boardViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_board, parent, false));
}
그러면 이렇게 item_board에 빨간줄이 뜨는데 Alt + Enter를 눌러서 xml을 생성해주면 된다.
참고로 item_board는 꼭 이렇게 할 필요 없고 만들 때 구분이 잘되겠다 싶은 이름으로 설정해도 좋다.
item_board는 뒤에서 설명하도록 하고 어댑터를 계속 설명하도록 하겠다.
getItemCount()를 이렇게 return 0; -> return datas.size(); 으로 설정해준다.
@Override
public int getItemCount() {
return datas.size();
}
그리고 onBindViewHolder에서는 가져올 데이터를 세팅하는 곳이다.
// 각각의 홀더의 위치(position)에 데이터(컨텐츠, 타이틀)를 넣음
// title, nickname, contents 섞임현상으로 임시로 수정
board data = datas.get(position);
holder.board_title.setText("✔" + data.getTitle());
holder.board_contents.setText(data.getContents());
holder.board_nickname.setText(data.getNickname());
holder.board_uid.setText(data.getDocumentId());
holder.board_collectionid.setText(data.getCollectionId());
holder.board_timestamp.setText(data.getTimestamp());
여기서 사용되는 data.get~~ 는 models에서 선언한 Getter Setter에서 생성된다.
굳이 setText가 아니고 이미지를 사용하기 위해서 다른 형식으로도 사용한다.
이미지를 사용하기 위해서는 Glide 라이브러리를 사용하여 아래의 코드를 사용할 수도 있다.
이는 UploadAdapter에서도 확인할 수 있다.
Glide.with(holder.itemView)
.load(datas.get(position).getImage())
.into(holder.image);
그런데 이렇게 작성을 하면
막 빨간줄이 뜨는걸 확인할 수 있다.
이건 아직 선언을 하지 않아서인데 이는 boardViewholder에서 선언해주면 된다.
class boardViewHolder extends RecyclerView.ViewHolder {
private TextView board_title;
private TextView board_contents;
private TextView board_nickname;
private TextView board_uid;
private TextView board_timestamp;
private TextView board_collectionid;
나는 여기서 사용될 것이 TextView 뿐이라 이렇게 선언했는데 만약 Text가 아니라면 EditText나 Rating ImageView로 선언해도 된다.
그리고 여기서 findViewById를 통해 xml과 연결해주면 끝이다.
뷰홀더 전체의 모습은 다음과 같다.
public class boardViewholder extends RecyclerView.ViewHolder {
private TextView board_title;
private TextView board_contents;
private TextView board_nickname;
private TextView board_uid;
private TextView board_timestamp;
private TextView board_collectionid;
public boardViewholder(@NonNull View itemView) {
super(itemView);
// title, nickname, contents 섞임현상으로 임시로 수정
board_title = itemView.findViewById(R.id.item_board_nickname);
board_nickname = itemView.findViewById(R.id.item_board_contents);
board_contents = itemView.findViewById(R.id.item_board_title);
board_uid = itemView.findViewById(R.id.item_board_uid);
board_timestamp = itemView.findViewById(R.id.item_board_timestamp);
board_collectionid = itemView.findViewById(R.id.item_board_collectionid);
}
}
findViewById에서 itemView.을 사용하여 연결해주어야 한다.
이 때 id들은 xml에서 정해주어야 하는데 xml은 위에서 만들어주었던 item_board.xml이다.
이렇게 제목 / 닉네임 / 내용(미리보기) / 업로드 시간 을 출력하게 하였고
그 외에 선언했던 uid나 collectionid는 파이어스토어에 저장하고 관리하기 위해 따로 선언해둔 것이기 때문에 여기서는 설명하지 않도록 하겠다.
리사이클러뷰에서 보여질 ITEM의 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:id="@+id/linear_item"
android:orientation="vertical"
android:layout_width="match_parent"
android:background="@drawable/button_round"
android:layout_height="90dp">
<TextView
android:id="@+id/item_board_title"
android:layout_width="297dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginStart="8dp"
android:textColor="@color/black"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:text="TITLE">
</TextView>
<TextView
android:id="@+id/item_board_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:text="Nickname"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.279">
</TextView>
<TextView
android:id="@+id/item_board_contents"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginBottom="16dp"
android:textColor="@color/material_dynamic_neutral50"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.023"
app:layout_constraintStart_toStartOf="parent"
tools:text="Contents">
</TextView>
<TextView
android:id="@+id/item_board_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="timestamp"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.953"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.816">
</TextView>
<TextView
android:id="@+id/item_board_uid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible">
</TextView>
<TextView
android:id="@+id/item_board_collectionid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_board_timestamp"
app:layout_constraintTop_toBottomOf="@+id/item_board_nickname">
</TextView>
</androidx.constraintlayout.widget.ConstraintLayout>
마지막으로 설정해줘야 할 것은 Activity이다.
나는 Fragment에 리사이클러뷰를 띄워놓았기 때문에 Fragment로 설명하겠지만 Activity와 다른점이 거의 없다.
XML에서는 리사이클러뷰만 선언해주면 된다.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/board_RecyclerView"
android:layout_width="400dp"
android:layout_height="720dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
</androidx.recyclerview.widget.RecyclerView>
레이아웃 매니저를 포함시켜줘야 한다. 나는 LinearLayout을 사용하였다.
Java 코드에서 리사이클러뷰를 선언해줘야 한다.
먼저 리사이클러뷰에서 사용하기 위해 다음의 코드를 상단에 선언해준다.
private RecyclerView mBoardRecyclerView;
private boardAdapter mAdapter;
private List<board> mDatas;
그리고 findViewById를 통해 연결해준다.
mBoardRecyclerView = view.findViewById(R.id.board_RecyclerView);
나는 Fragment에서 선언했기 때문에 view.가 붙는데 Activity에서 사용할 때는 view.를 붙이면 안된다.
그리고 아래의 코드를 추가하여 리사이클러뷰를 완성시켜주면 된다.
mAdapter = new boardAdapter(mDatas);
mBoardRecyclerView.setAdapter(mAdapter);
나는 게시판 기능을 구현하기 위해 파이어스토어와 연결하여 데이터를 입력하도록 하였지만 간단히 데이터가 제대로 들어갔는지 확인하려면 아래의 형식으로 데이터를 입력해줘도 좋다.
mDatas.add("넣고싶은 내용");
위의 형식을 for문을 사용해서 여러개의 아이템을 추가해 볼 수도 있다.
List의 이름을 mDatas로 선언했기 때문에 이외의 이름으로 설저했다면 그부분만 바꿔주면 된다.
리사이클러뷰만 간단히 소개하려 했는데 내용이 점점 길어기도 하고 실제로 어플을 만들면서 작성했던 코드들을 통해 설명하려니 여러개가 연결되어있어 복잡해진 것 같습니다.
전체 코드는 최상단의 링크를 통해 확인할 수 있으며 혹시나 오류가 있거나 궁금한게 있으면 댓글에 남겨주시면 수정하거나 답변드리도록 하겠습니다.
Android Developers에서도 내용을 확인할 수 있습니다.
https://developer.android.com/guide/topics/ui/layout/recyclerview?hl=ko#java
RecyclerView로 동적 목록 만들기 | Android 개발자 | Android Developers
컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. RecyclerView로 동적 목록 만들기 Android Jetpack의 구성요소 RecyclerView를 사용하면 대량의 데이터 세트를 효율적
developer.android.com
'안드로이드' 카테고리의 다른 글
[안드로이드] 리사이클러뷰 레이아웃 매니저 종류 (0) | 2023.01.04 |
---|---|
[안드로이드] 리사이클러뷰 가로로 만들기 (0) | 2023.01.04 |
[안드로이드] 파이어베이스 / 로그아웃 만들기 (0) | 2023.01.03 |
[안드로이드] 파이어베이스 / 로그인 만들기 (1) | 2023.01.03 |
[안드로이드] 파이어베이스 / 회원가입 만들기 (0) | 2023.01.03 |