使用RecyclerView實現Gallery畫廊效果

先貼圖


要實現上面的畫廊效果,傳統通過ViewPager clipChildren置為false實現。網上很多教程這個不多說,現在說說用RecyclerView實現上面的效果。這個效果分兩步:

  1. ViewPager滑動最終居中停止
  2. 滑動過程中縮放

ViewPager滑動最終居中停止

Support RecyclerView 24.2.0中增加一個非常重要的類SnapHelper,他的作用是讓RecyclerView滑動視圖后使停止位置正好停在某頁的正中間。使用方式很簡單
重點在于new LinearSnapHelper().attachToRecyclerView(recyclerView);

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);

new LinearSnapHelper().attachToRecyclerView(recyclerView);

一行代碼搞定居中,LinearSnapHelper的源碼解析查看這里

滑動過程中縮放

毫無疑問,RecyclerView的滑動縮放必須要監聽RecyclerView的滑動

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為滑動總距離,Card每頁滑動的距離是固定的,根據這個可以計算出當前顯示的位置。縮放看onScrolledChangedCallback這個函數,有了滑動位置就能實時計算滑動某頁的百分比
float percent = (float) Math.max(Math.abs(offset) * 1.0 / mOnePageWidth, 0.0001);

得到百分比, 再獲取當前位置相鄰的視圖調用setScaleY函數實現縮放

/**
 * RecyclerView位移事件監聽, 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);
    }
}

完整代碼下載

https://github.com/huazhiyuan2008/RecyclerViewCardGallery

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容