版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接和本聲明。
本文連接:https://blog.csdn.net/android_freshman/article/details/94354088
RecyclerView item 可展開動畫效果的實現
前文提要:
1.相關說明:
1-1.佈局文件:
1-2.動畫工具類說明(代碼我基本上都添加了註釋):
1-3.問題:
2.如何使用:
2-1.viewHoler 須要實現 ExpandableViewHoldersUtil.Expandable 接口
2-2.adapter
2-3.ExpandableViewHoldersUtil
3.結束:
前文提要:
Android list 列表裏面空間的顯示和 隱藏,基本都是用的View.VISIBLE 和 View.GONE 實現的,展現的效果有點突兀,看了ios 同事作的相同的效果,他們的很順暢,因此決定作一個相同的效果.android
已經上傳到github 上面地址是 demo的項目地址 :https://github.com/luhui2014/ExpandableViewHolder/tree/masterios
1.相關說明:
參考資料:Android—RecyclerView之動畫(工具類)實現可展開列表git
1-1.佈局文件:
將須要展開收縮的那部分佈局的透明度在xml文件裏默認設置爲0,在代碼中設置同樣github
1-2.動畫工具類說明(代碼我基本上都添加了註釋):
這裏我就不贅述了,請參考原文 Android—RecyclerView之動畫(工具類)實現可展開列表數組
相關原理就是:利用屬性動畫,動態計算view展開後的高度,實現動畫效果。中間插了一段alpha 的動畫,爲了過渡顯示,關鍵代碼:緩存
//OpenHolder中動畫的具體操做方法
public static Animator ofItemViewHeight(RecyclerView.ViewHolder holder) {
View parent = (View) holder.itemView.getParent();
if (parent == null)
throw new IllegalStateException("Cannot animate the layout of a view that has no parent");ide
//測量擴展動畫的起始高度和結束高度
int start = holder.itemView.getMeasuredHeight();
holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(),
View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int end = holder.itemView.getMeasuredHeight();
final Animator animator = LayoutAnimator.ofHeight(holder.itemView, start, end); //具體的展開動畫工具
//設定該Item在動畫開始結束和取消時可否被recycle
animator.addListener(new ViewHolderAnimatorListener(holder));佈局
//設定結束時這個Item的寬高
animator.addListener(new LayoutParamsAnimatorListener(holder.itemView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return animator;動畫
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
還有一段比較有意思的地方是 處理了recyclerView 的的回收,增長了一個動畫監聽,在動畫結束的時候,讓recyclerView 自身去處理是否回收的問題
public static class ViewHolderAnimatorListener extends AnimatorListenerAdapter {
private final RecyclerView.ViewHolder mHolder; //holder對象
//設定在動畫開始結束和取消狀態下是否能夠被回收
public ViewHolderAnimatorListener(RecyclerView.ViewHolder holder) {
mHolder = holder;
}
@Override
public void onAnimationStart(Animator animation) { //開始時
mHolder.setIsRecyclable(false);
}
@Override
public void onAnimationEnd(Animator animation) { //結束時
mHolder.setIsRecyclable(true);
}
@Override
public void onAnimationCancel(Animator animation) { //取消時
mHolder.setIsRecyclable(true);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1-3.問題:
可是原做裏沒有處理好展開和收縮緩存的問題,已經解耦的問題。對應展開item以後是否須要其餘的動畫,這裏應該開放出來,自行去實現,因此我這裏就改了一下:
/**
* 響應ViewHolder的點擊事件
*
* @param holder holder對象
*/
@SuppressWarnings("unchecked")
public void toggle(VH holder) {
int position = holder.getPosition();
if (explanedList.contains(position + "")) {
opened = -1;
deletePositionInExpaned(position);
holder.doCustomAnim(true);
ExpandableViewHoldersUtil.getInstance().closeHolder(holder, holder.getExpandView(), true);
} else {
preOpen = opened;
opened = position;
addPositionInExpaned(position);
holder.doCustomAnim(false);
ExpandableViewHoldersUtil.getInstance().openHolder(holder, holder.getExpandView(), true);
//是否要關閉上一個
if (needExplanedOnlyOne && preOpen != position) {
final VH oldHolder = (VH) ((RecyclerView) holder.itemView.getParent()).findViewHolderForPosition(preOpen);
if (oldHolder != null) {
Log.e("KeepOneHolder", "oldHolder != null");
ExpandableViewHoldersUtil.getInstance().closeHolder(oldHolder, oldHolder.getExpandView(), true);
deletePositionInExpaned(preOpen);
}
}
}
}
}
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
32
33
34
開放出來一個回調接口處理:holder.doCustomAnim(true);,根據須要自行增長相關的動畫;
對於記錄展開和收縮狀態的問題,定義了一個全局的變量用於存儲,初始化的時候,進行判斷。在用戶點擊動畫的時候,進行相應的增長和刪除處理:
這裏用String 記錄是爲了處理刪除的時候數據越界的問題:
private void deletePositionInExpaned(int pos) {
//remove Object 直接寫int,會變成index,形成數組越界
explanedList.remove(pos + "");
}
1
2
3
4
源碼中有這麼一段,直接刪除int 會存在數值越界的問題;
2.如何使用:
2-1.viewHoler 須要實現 ExpandableViewHoldersUtil.Expandable 接口
回調的view,就是處理展開動畫的view,
不要忘記初始化 keepOne = ExpandableViewHoldersUtil.getInstance().getKeepOneHolder();
class ViewHolder extends RecyclerView.ViewHolder implements ExpandableViewHoldersUtil.Expandable {
TextView tvTitle;
ImageView arrowImage;
LinearLayout lvArrorwBtn;
LinearLayout lvLinearlayout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.item_user_concern_title);
lvLinearlayout = itemView.findViewById(R.id.item_user_concern_link_layout);
lvArrorwBtn = itemView.findViewById(R.id.item_user_concern_arrow);
arrowImage = itemView.findViewById(R.id.item_user_concern_arrow_image);
keepOne = ExpandableViewHoldersUtil.getInstance().getKeepOneHolder();
lvLinearlayout.setVisibility(View.GONE);
lvLinearlayout.setAlpha(0);
}
@Override
public View getExpandView() {
return lvLinearlayout;
}
@Override
public void doCustomAnim(boolean isOpen) {
if (isOpen) {
ExpandableViewHoldersUtil.getInstance().rotateExpandIcon(arrowImage, 180, 0);
} else {
ExpandableViewHoldersUtil.getInstance().rotateExpandIcon(arrowImage, 0, 180);
}
}
}
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
32
33
34
2-2.adapter
在 onBindViewHolder 的時候須要綁定對應的view,初始展開和收縮的狀態,天然點擊效果就是 keepOne.toggle(viewHolder);
@Override
public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) {
viewHolder.tvTitle.setText("中美經貿磋商 po=" + position);
keepOne.bind(viewHolder, position);
viewHolder.tvTitle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
keepOne.toggle(viewHolder);
}
});
viewHolder.lvArrorwBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
keepOne.toggle(viewHolder);
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2-3.ExpandableViewHoldersUtil
1.setNeedExplanedOnlyOne
//true 點擊第二個會收縮前一個
//false 不會
ExpandableViewHoldersUtil.getInstance().init().setNeedExplanedOnlyOne(false);
2.//清空記錄展開仍是關閉的緩存數據,這個每次在下拉刷新的時候,是否清空根據需求自行處理
ExpandableViewHoldersUtil.getInstance().resetExpanedList();
3.結束:
參照的相關的代碼並根據本身在使用過程當中遇到的問題,作了相關處理,原文連接已貼在開始。特地寫了一個簡單demo 上傳到git上,
還有問題請參考具體的實現demo :https://github.com/luhui2014/ExpandableViewHolder/tree/master ———————————————— 版權聲明:本文爲CSDN博主「android_小路」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/android_freshman/article/details/94354088