title: RecyclerView實(shí)現(xiàn)探探卡片滑動(dòng)功能
date: 2018-10-07 10:35:56
tags: RecyclerView
代碼實(shí)現(xiàn)
博客地址:https://blog.csdn.net/qq_39085422/article/details/78612132
我只掌握了RecyclerView基礎(chǔ)用法,所以參考別人博客的代碼實(shí)現(xiàn)。
我使用CardView代替RoundImageView實(shí)現(xiàn)圓角效果。
遇到的問題
1.CardView陰影顯示不完全
原因:將CardView作為最外層布局,可能是兩個(gè)CardView重疊時(shí),邊界會(huì)融合到一起。
解決方法:在外層再套一層布局,比如LinearLayout之類的。
解決后效果圖:

在文末會(huì)貼出我的布局代碼。
2.左右滑,滑出時(shí)卡頓(未解決)
原因:adapter.notifyDataSetChanged();
卡片滑出后需要?jiǎng)h除對(duì)應(yīng)的數(shù)據(jù),對(duì)數(shù)據(jù)源進(jìn)行remove()操作,之后通知adapter,這個(gè)時(shí)候會(huì)發(fā)生卡頓
3.向上下滑動(dòng)時(shí),動(dòng)畫銜接的不好
原因:臨界值計(jì)算公式不合理,只計(jì)算了在X軸的偏移量
解決:CardItemTouchHelperCallback類中的onChildDraw()里,
解決前代碼:
float ratio = dX / getThreshold(recyclerView, viewHolder);
解決后代碼:
float distance = (float)Math.sqrt(dX*dX+dY*dY);
float ratio = distance / getThreshold(recyclerView, viewHolder);
變化:增加了distance變量,計(jì)算位移兩點(diǎn)間的直線距離。
4.用Gilde加載網(wǎng)絡(luò)圖片時(shí),會(huì)閃爍,使用本地圖片時(shí)不會(huì)

原因:Gilde進(jìn)行加載網(wǎng)絡(luò)圖片時(shí),會(huì)保留緩存,使用時(shí)加載完整圖片,所以分辨率不同,會(huì)閃爍。
解決:
思路是類似于做一層緩存,先把圖片加載好放在一個(gè)List里面,使用時(shí)直接從數(shù)組里取出來,這樣子就模擬了本地圖片加載。
具體實(shí)現(xiàn)如下:
在adaputer中聲明兩個(gè)數(shù)組
//圖片的URL
private List<String> imgUrlList = new ArrayList<>();
//緩存數(shù)組
private List<GlideDrawable> glideDrawableList = new ArrayList<>();
//glideDrawableList的訪問方法,imgUrlList通過構(gòu)造函數(shù)傳入,不需要get,set
public List<GlideDrawable> getGlideDrawableList() {
return glideDrawableList;
}
public void setGlideDrawableList(List<GlideDrawable> glideDrawableList) {
this.glideDrawableList = glideDrawableList;
}
之后創(chuàng)建一個(gè)updateGlideDrawableList()方法,用于請(qǐng)求網(wǎng)絡(luò)圖片,CardConfig.DEFAULT_SHOW_ITEM是顯示的卡片數(shù)量,CardConfig.DEFAULT_CACHE_ITEM是而外的緩存數(shù)量,為了防止用戶滑動(dòng)太快,網(wǎng)絡(luò)請(qǐng)求速度跟不上。
public void updateGlideDrawableList(){
//每次最多循環(huán)的次數(shù)i<卡片顯示數(shù)量+額外緩存數(shù)量
for (int i = mCardShowInfoBeanList.size(); i < CardConfig.DEFAULT_SHOW_ITEM+CardConfig.DEFAULT_CACHE_ITEM; i++){
//防止list為空
if(imgUrlList.size() <= 0){
return;
}
//依次去除所有的url
String url = imgUrlList.remove(0);
//使用Gilde請(qǐng)求網(wǎng)絡(luò)圖片
Glide.with(mContext)
.load(url)
//Gilde將圖片剪裁成336,326
.into(new SimpleTarget<GlideDrawable>(336, 326) {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
//將圖片資源放入緩存數(shù)組
glideDrawableList.add(resource);
//通知adapter數(shù)據(jù)已經(jīng)更新,刷新顯示。
AdapterCardSwipeLive.this.notifyDataSetChanged();
}
});
}
}
之后只要在imgUrlList傳入之后,onBindViewHolder()之前使用該方法就好了,這里我選擇在構(gòu)造函數(shù)里調(diào)用:
public Adapter(Context context, List imgUrlList){
this.imgUrlList = imgUrlList;
this.mContext = context;
//我選擇今早的調(diào)用此方法,減少用戶的等待時(shí)間
updateGlideDrawableList();
}
到這里,核心代碼就已經(jīng)寫完了,接下來只需要將之前使ItemTouchHelperCallback中操作imgUrlList的地方進(jìn)行一些修改,替換成glideDrawableList就可以了:
//替換前
T remove = adaputer.getList().remove(layoutPosition);
adapter.notifyDataSetChanged();
//替換后
T remove = ((List<T>) adapterCardSwipeLive.getmCardShowInfoBeanList()).remove(layoutPosition);
//調(diào)用這個(gè)方法以補(bǔ)充被remove掉的GlideDrawable
updateGlideDrawableList();
adapter.notifyDataSetChanged();
這樣子就完成了,使用時(shí),傳進(jìn)adaputer來的只有imgUrlList,然后adapter向外只提供一個(gè)glideDrawableList,外面也只能對(duì)glideDrawableList進(jìn)行增刪改查。同時(shí)每刪除glideDrawableList中的一個(gè)元素,再通過updateGlideDrawableList()添加回來,就能實(shí)現(xiàn)盡可能少的緩存。這里只是提供一個(gè)思路,代碼不一定能毫無錯(cuò)誤的運(yùn)行出來,需要自己進(jìn)行適配。
拓展
如果你搜索卡片層疊效果,你會(huì)發(fā)現(xiàn)更多更詳細(xì)的內(nèi)容
總結(jié):
折騰了好久也無法像探探那樣流暢,只能朝四個(gè)方向滑出,而不能360°滑出,
流暢度效果也有不少差距。
應(yīng)該是實(shí)現(xiàn)思路的不同,我是基于recyclerView實(shí)現(xiàn)的,比較簡(jiǎn)單,另一種基于ListView實(shí)現(xiàn)的比較復(fù)雜,但效果很好??梢娮约核竭€有待提高。
相關(guān)代碼:
item_card_slide.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="336dp"
android:layout_height="426dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="7.5dp"
app:cardElevation="1dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_avatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:background="@color/pink"/>
<ImageView
android:id="@+id/iv_dislike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="15dp"
android:alpha="0"
android:background="@color/blue"/>
<ImageView
android:id="@+id/iv_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="15dp"
android:alpha="0"
android:background="@color/grey"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:paddingLeft="14dp"
android:paddingTop="15dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="小姐姐"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_marginTop="5dp"
android:background="@color/pink"
android:gravity="center"
android:text="♀ 23"
android:textColor="#FFFFFF"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_constellation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_marginLeft="4dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/tv_age"
android:background="@color/olivedrab"
android:gravity="center"
android:text="獅子座"
android:textColor="#FFFFFF"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_age"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="IT/互聯(lián)網(wǎng)"
android:textColor="#cbcbcb" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
