일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 안드로이드광고
- Clean Architecture
- component
- 다이나믹 링크
- 컴포넌트
- 젯팩컴포즈
- dynamiclink
- glide
- 동적 링크
- android daum map
- 애드몹광고
- 아키텍처
- Firebase
- 선언형UI
- JetpackCompose
- Android 애드몹
- 애드몹배너
- 클린 아키텍처
- android kakao map
- 파이어베이스
- thread
- 안드로이드컴포즈
- RecyclerView
- 안드로이드
- Android
- HTTP
- ImageView
- 안드로이드 라이브러리
- 안드로이드 카카오 지도
- android 지도
- Today
- Total
코딩스토리
[Android/안드로이드] Expandable RecyclerView 접기/펼치기(아코디언) 본문
이전 글에서 리사이클러뷰 사용법에 대해 설명을 했었습니다.
이번 글에서는 리사이클러뷰를 클릭했을 때 접고, 펼칠 수 있는 기능을 추가해 보도록 하겠습니다.
이전 글에서 만들어 놓았던 DataMovie클래스와 MainActivity클래스는 수정할 부분이 없으므로 생략하고 수정사항이 있는 부분말 적어놓도록 하겠습니다. DataMovie클래스와 MainActivity부분이 없으신 분들은 이전 글을 참조해주세요.
2019/12/19 - [Android/유용한 기술] - [Android/안드로이드] RecyclerView(리사이클러뷰) 뷰 재활용하기
우선 뷰홀더에 있는 버튼을 클릭했을 경우 Adapter에서도 알 수 있도록 이벤트 리스너를 만들겠습니다.
이벤트 리스너 생성
OnViewHolderItemClickListener.java
package com.example.recyclerviewtest;
public interface OnViewHolderItemClickListener {
void onViewHolderItemClick();
}
이제 Adapter에서 클릭했을 때 접고, 펼칠 수 있도록 아코디언 형식을 만들어 보겠습니다.
RecyclerVierAdapter.java
package com.lakue.recyclerviewarcodian;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerVierAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// adapter에 들어갈 list 입니다.
private ArrayList<DataMovie> listData = new ArrayList<>();
// Item의 클릭 상태를 저장할 array 객체
private SparseBooleanArray selectedItems = new SparseBooleanArray();
// 직전에 클릭됐던 Item의 position
private int prePosition = -1;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false);
return new ViewHolderMovie(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
ViewHolderMovie viewHolderMovie = (ViewHolderMovie)holder;
viewHolderMovie.onBind(listData.get(position),position, selectedItems);
viewHolderMovie.setOnViewHolderItemClickListener(new OnViewHolderItemClickListener() {
@Override
public void onViewHolderItemClick() {
if (selectedItems.get(position)) {
// 펼쳐진 Item을 클릭 시
selectedItems.delete(position);
} else {
// 직전의 클릭됐던 Item의 클릭상태를 지움
selectedItems.delete(prePosition);
// 클릭한 Item의 position을 저장
selectedItems.put(position, true);
}
// 해당 포지션의 변화를 알림
if (prePosition != -1) notifyItemChanged(prePosition);
notifyItemChanged(position);
// 클릭된 position 저장
prePosition = position;
}
});
}
@Override
public int getItemCount() {
return listData.size();
}
void addItem(DataMovie data) {
// 외부에서 item을 추가시킬 함수입니다.
listData.add(data);
}
}
이전 소스코드와 다른점은 SparseBooleanArray형의 객체를 생성했고, 이전에 클릭했던 아이템의 position을 저장하는 int형 prePosition 변수를 생성했습니다.
onBind부분에서 아까 생성했던 selectedItem객체의 position번째값을 넘겨주도록 합니다.
setOnViewHolderItemClickListener부분은 이제 ViewHolder에서 해당 Item을 클릭했을 경우 발생하는 리스너입니다.
클릭했을 경우 사용되는 기능은 주석을 통해 설명하였습니다.
ViewHolderMovie.java
package com.lakue.recyclerviewarcodian;
import android.animation.ValueAnimator;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class ViewHolderMovie extends RecyclerView.ViewHolder {
TextView tv_movie_title;
ImageView iv_movie,iv_movie2;
LinearLayout linearlayout;
OnViewHolderItemClickListener onViewHolderItemClickListener;
public ViewHolderMovie(@NonNull View itemView) {
super(itemView);
iv_movie = itemView.findViewById(R.id.iv_movie);
tv_movie_title = itemView.findViewById(R.id.tv_movie_title);
iv_movie2 = itemView.findViewById(R.id.iv_movie2);
linearlayout = itemView.findViewById(R.id.linearlayout);
linearlayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onViewHolderItemClickListener.onViewHolderItemClick();
}
});
}
public void onBind(DataMovie data,int position, SparseBooleanArray selectedItems){
tv_movie_title.setText(data.getTitle());
iv_movie.setImageResource(data.getImage());
iv_movie2.setImageResource(data.getImage());
changeVisibility(selectedItems.get(position));
}
private void changeVisibility(final boolean isExpanded) {
// ValueAnimator.ofInt(int... values)는 View가 변할 값을 지정, 인자는 int 배열
ValueAnimator va = isExpanded ? ValueAnimator.ofInt(0, 600) : ValueAnimator.ofInt(600, 0);
// Animation이 실행되는 시간, n/1000초
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// imageView의 높이 변경
iv_movie2.getLayoutParams().height = (int) animation.getAnimatedValue();
iv_movie2.requestLayout();
// imageView가 실제로 사라지게하는 부분
iv_movie2.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
}
});
// Animation start
va.start();
}
public void setOnViewHolderItemClickListener(OnViewHolderItemClickListener onViewHolderItemClickListener) {
this.onViewHolderItemClickListener = onViewHolderItemClickListener;
}
}
이전 글과는 UI가 조금 바뀌습니다. 아까 생성했던 이벤트 리스너를 선언해주고, 레이아웃을 클릭했을 때 onViewHolderItemClickListener.onViewHolderItemClick()를 호출하여 이벤트를 발생시킵니다. 발생된 이벤트는 RecyclerViewAdapter에서 setOnViewHolderItemClickListener로 받아서 처리하였습니다.
changeVisibility(final boolean isExpanded)함수에서는 adapter에서 받아온 isSelect값이 true이면 이미지를 보여주고, false일 경우 이미지를 gone시켜주는 기능을 하고있습니다.
item_movie.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:id="@+id/linearlayout"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_movie"
android:scaleType="centerCrop"
android:layout_width="100dp"
android:layout_height="80dp"/>
<TextView
android:padding="20dp"
android:gravity="center"
android:textSize="16dp"
android:id="@+id/tv_movie_title"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<ImageView
android:visibility="gone"
android:id="@+id/iv_movie2"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</LinearLayout>
결과화면
다음과 같이 아이템을 클릭하면 RecyclerView를 접었다 폈다 할 수 있는 기능을 구현해보았습니다.
궁금하신점이나 제가 실수한 부분이 있다면 댓글로 남겨주세요~~
코드작동 안되시는분들을 위해 Git에 저장해놓았습니다. 참고해주세요~~
'Android > 유용한 기술' 카테고리의 다른 글
[Android/안드로이드]RecyclerView 화면깜빡임 현상 방지 (0) | 2019.12.23 |
---|---|
[Android/안드로이드] 하나의 아답타로 여러개의 RecyclerView만들기/ RecyclerView Adapter 재사용 (4) | 2019.12.22 |
[Android/안드로이드] RecyclerView(리사이클러뷰) 뷰 재활용하기 (0) | 2019.12.19 |
[Android/안드로이드] 페이스북로그인 버튼 커스텀/Facebook Login Button Custom (0) | 2019.12.18 |
[Android/안드로이드] 페이스북 로그인 / Facebook Login 연동 (23) | 2019.12.17 |