先貼圖
要實(shí)現(xiàn)上面的畫廊效果浇冰,傳統(tǒng)通過ViewPager clipChildren置為false實(shí)現(xiàn)。網(wǎng)上很多教程這個(gè)不多說洋魂,現(xiàn)在說說用RecyclerView實(shí)現(xiàn)上面的效果绷旗。這個(gè)效果分兩步:
- ViewPager滑動(dòng)最終居中停止
- 滑動(dòng)過程中縮放
ViewPager滑動(dòng)最終居中停止
Support RecyclerView 24.2.0中增加一個(gè)非常重要的類SnapHelper
喜鼓,他的作用是讓RecyclerView滑動(dòng)視圖后使停止位置正好停在某頁(yè)的正中間。使用方式很簡(jiǎn)單
重點(diǎn)在于new LinearSnapHelper().attachToRecyclerView(recyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
new LinearSnapHelper().attachToRecyclerView(recyclerView);
一行代碼搞定居中衔肢,LinearSnapHelper的源碼解析查看這里庄岖。
滑動(dòng)過程中縮放
毫無疑問,RecyclerView的滑動(dòng)縮放必須要監(jiān)聽RecyclerView的滑動(dòng)
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// dx>0則表示右滑, dx<0表示左滑, dy<0表示上滑, dy>0表示下滑
mCurrentItemOffset += dx;
computeCurrentItemPos();
onScrolledChangedCallback();
}
});
mCurrentItemOffset為滑動(dòng)總距離角骤,Card每頁(yè)滑動(dòng)的距離是固定的隅忿,根據(jù)這個(gè)可以計(jì)算出當(dāng)前顯示的位置“钭穑縮放看onScrolledChangedCallback
這個(gè)函數(shù)背桐,有了滑動(dòng)位置就能實(shí)時(shí)計(jì)算滑動(dòng)某頁(yè)的百分比
float percent = (float) Math.max(Math.abs(offset) * 1.0 / mOnePageWidth, 0.0001);
得到百分比, 再獲取當(dāng)前位置相鄰的視圖調(diào)用setScaleY
函數(shù)實(shí)現(xiàn)縮放
/**
* RecyclerView位移事件監(jiān)聽, view大小隨位移事件變化
*/
private void onScrolledChangedCallback() {
int offset = mCurrentItemOffset - mCurrentItemPos * mOnePageWidth;
float percent = (float) Math.max(Math.abs(offset) * 1.0 / mOnePageWidth, 0.0001);
View leftView = null;
View currentView;
View rightView = null;
if (mCurrentItemPos > 0) {
leftView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos - 1);
}
currentView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos);
if (mCurrentItemPos < mRecyclerView.getAdapter().getItemCount() - 1) {
rightView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos + 1);
}
if (leftView != null) {
// y = (1 - mScale)x + mScale
leftView.setScaleY((1 - mScale) * percent + mScale);
}
if (currentView != null) {
// y = (mScale - 1)x + 1
currentView.setScaleY((mScale - 1) * percent + 1);
}
if (rightView != null) {
// y = (1 - mScale)x + mScale
rightView.setScaleY((1 - mScale) * percent + mScale);
}
}