1. 程式人生 > >Android24.2.0支援庫中的SnapHelper學習和使用

Android24.2.0支援庫中的SnapHelper學習和使用

一、前言

Google最新發布的support v4包更新到24.2.0,由原來的一個大包分割成多個小module。這樣做真是太貼心不過了,以後不會再因為單獨使用某一個功能而將整個v4包匯入專案中,而是我想用哪個就匯入哪個,很大程度上減小了APK的大小。

com.android.support:support-compat:24.2.0
com.android.support:support-core-utils:24.2.0
com.android.support:support-core-ui:24.2.0
com.android.support:support-media-compat:24.2.0
com.android.support:support-fragment:24.2.0

SnapHelper就是這次更新裡面的一個,其實它是對RecyclerView功能的一種拓展。
想要詳細瞭解其他更新的,可以點選這個連結

二、SnapHelper介紹

SnapHelper的實現原理是監聽RecyclerView.OnFlingListener中的onFling介面。LinearSnapHelper是抽象類SnapHelper的具體實現。
通過LinearSnapHelper,可以使RecyclerView實現類似ViewPager的功能,無論怎麼滑動最終停留在某頁正中間。
區別就在於,ViewPager一次只能滑動一頁,RecyclerView+SnapHelper方式可以實現一次滑動好幾頁。

三、實現效果

這裡主要是介紹實現兩種效果。

  • 自帶的LinearSnapHelper實現
    可以看到類似ViewPager,將某頁居中顯示,實現也是很簡單,只要下面的兩行程式碼
        LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();
        mLinearSnapHelper.attachToRecyclerView(mRecyclerView);

這裡寫圖片描述

  • 自定義SnapHelper實現

    既然可以居中顯示,那我們能不能讓它橫向左對齊顯示呢,答案當然是可以的,這就需要我們自己定義一個左對齊的SnapHelper。
    先來看個效果,o(∩_∩)o 哈哈。
    這裡寫圖片描述

四、實現過程

SnapHelper 是一個抽象類,直接繼承需要實現三個方法:

  1. 當拖拽或滑動結束時會回撥該方法,返回一個out = int[2],out[0]x軸,out[1] y軸 ,這個值就是需要修正的你需要的位置的偏移量
    public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager, @NonNull View targetView);

  2. 上面方法有一個targetView吧 就是這個方法返回的
    public abstract View findSnapView(LayoutManager layoutManager);

  3. 用於Fling,根據速度返回你要滑到的position
    public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX, int velocityY);

但是,我們不直接繼承SnapHelper,而是繼承它的實現類LinearSnapHelper,程式碼如下:


/**
 * Created by hiwhitley on 2016/9/4.
 */
public class MySnapHelper extends LinearSnapHelper {

    private OrientationHelper mHorizontalHelper;

    @Nullable
    @Override
    public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
        int[] out = new int[2];
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }

        return out;
    }

    private int distanceToStart(View targetView, OrientationHelper helper) {
        return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
    }

    @Nullable
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        return findStartView(layoutManager, getHorizontalHelper(layoutManager));
    }

    private View findStartView(RecyclerView.LayoutManager layoutManager,
                               OrientationHelper helper) {

        if (layoutManager instanceof LinearLayoutManager) {
            int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            if (firstChild == RecyclerView.NO_POSITION) {
                return null;
            }
            if (lastChild == layoutManager.getItemCount() - 1) {
                return layoutManager.findViewByPosition(lastChild);
            }

            View child = layoutManager.findViewByPosition(firstChild);

            if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
                    && helper.getDecoratedEnd(child) > 0) {
                return child;
            } else {
                return layoutManager.findViewByPosition(firstChild + 1);
            }
        }

        return super.findSnapView(layoutManager);
    }


    private OrientationHelper getHorizontalHelper(
            @NonNull RecyclerView.LayoutManager layoutManager) {
        if (mHorizontalHelper == null) {
            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }
        return mHorizontalHelper;
    }
}

基本就是參考著自帶的LinearSnapHelper實現的,
這裡有幾點需要特別注意一下,

第11~24行:我們只考慮橫向左對齊,所以只要處理out[0]的值,distanceToStart()方法返回修正的偏移量。

第41~43行:這是為了解決當翻到最後一頁的時候,最後一個Item不能完整顯示的問題(不信,你可以註釋了試試就知道啦)。

            if (lastChild == layoutManager.getItemCount() - 1) {
                return layoutManager.findViewByPosition(lastChild);
            }

第47~52行:得到此時需要左對齊顯示的條目

         if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
                    && helper.getDecoratedEnd(child) > 0) {
                return child;
            } else {
                return layoutManager.findViewByPosition(firstChild + 1);
            }

最後只要用上我們自己的SnapHelper,就可以輕鬆搞定了。

        MySnapHelper mMySnapHelper = new MySnapHelper();
        mMySnapHelper.attachToRecyclerView(mRecyclerView);

五、原始碼下載

GitHub下載
原始碼下載
如果您覺得對你有所幫助,歡迎Star和留言,來鼓勵一下我。o(∩_∩)o

六、拓展閱讀

相關推薦

Android24.2.0支援SnapHelper學習使用

一、前言 Google最新發布的support v4包更新到24.2.0,由原來的一個大包分割成多個小module。這樣做真是太貼心不過了,以後不會再因為單獨使用某一個功能而將整個v4包匯入專案中,而是我想用哪個就匯入哪個,很大程度上減小了APK的大小。

Asp.net core 2.0.1 Razor 的使用學習筆記(一)

提升 完成後 安全 provider razor 官方 one text .cn 環境:vs2017 版本:15.5.6 這裏說明下, Razor頁面模式跟mvc出現了嚴重的不同。正如微軟官方說的一樣“Razor 頁面是 ASP.NET Core MVC 的一

Asp.net core 2.0.1 Razor 的使用學習筆記(三)

post 應用程序 新的 entity gin start 密碼強度 ice httponly ASP.net core 2.0.1 中 asp.net identity 2.0.1 的基本使用(二)—用戶賬戶及cookie配置 修改用戶賬戶及cookie配置

Spring Boot 2.0 Intellij Idea 圖文詳解打包成可執行Jar

off aps cycle 找到 sna 打包 AS main 切換 我們使用Spring Boot 2.0 創建好我們的項目後,我們一般需要打包,然後部署到服務器上。 打包步驟: 1. 選中項目,右鍵——> Open Module Settings. 2. 切換

Asp.Net Core 2.0實現HttpResponse繁切換

== sed 存儲 中文簡體 選擇 .net tin contains nts 隨筆背景:因為項目中有個簡單的功能是需要實現中文簡體到繁體的切換,數據庫中存儲的源數據都是中文簡體的,為了省事就想著通過HttpHeader的方式來控制Api返回對應的繁體數據。 實現方式:通過

ESP8266_RTOS_SDK-2.0.0driver使用

在SDK中編譯MQTT例程,直接呼叫driver庫中的函式 UART_SetBaudrate(0,9600);如下圖所示: 編譯時提示undefine的錯誤,如下圖: 解決辦法: 1.把driver_lib資料夾下的driver資料夾copy到mqtt_demo

springboot 1.5.2升級2.0.4 mongodbQueryBuilderDBObject被棄用,改為Document構造及解決方式

今天封裝mongo工具包,發現QueryBuilder中DBObject被棄用,改為Document構造。為什麼,我們稍微分析一下  Document實現Map,與基本的DBObject相比,可編寫的程式碼更少 DBObject雖然不被推薦,那些從2.x驅動程式系列可能繼續使用DB

Missing artifact com.oracle:ojdbc6:jar:11.2.0.3 Maven不能引入ojdbc解決方法

今天在建立Maven專案的時候出現了一個問題,在POM檔案的overview窗口出現**Missing artifact com.oracle:ojdbc6:jar:11.2.0.3。**提示,著實不知道是啥情況。 在網上找了半天資料才知道,原來objdc6.j

spring 4.2.0後jdbcTemplate不用queryForLong了(之系統升級發現)

在spring 3.2.2之後,jdbcTemplate.queryForInt已經被取消了! 原來是這樣寫的: Java程式碼  String sql = "SELECT count(*) FROM USERS WHERE username = ?";

VUE 2.0 外掛

VUE 2.0 外掛庫 – https://blog.csdn.net/hjh15827475896/article/details/78207066 UI元件 element - 餓了麼出品的Vue2的web UI工具套件 Vux - 基於Vue和WeUI的元件庫 mint-ui

Apache Spark 2.0前瞻:為機器學習模型注入永續性

簡介研究機器學習用例:資料科學家建立了一個ML模型,並交給了一個工程團隊在生產環境部署。 資料工程師將使用Python的模型訓練工作流和Java模型服務工作流整合。 資料科學家專門設立崗位來訓練後期需要被儲存和評估的ML模型。 在所有的這些例子中,如果有了模型的

OpenCV3.2.0在VS2015的開發環境配置

最近想做一個有關影象變形的實驗,首先想到了OpenCV。全稱是:Open Source Computer Vision Library。OpenCV是開源的跨平臺計算機視覺庫,可以執行在Linux、Windows、Android和Mac OS作業系統上。輕量級而

基於opencv3.2.0版本FindContours()method引數導致程式異常解決

以上方案沒有解決問題。 問題 FindContours()中method引數導致程式異常 解決方法 int b; int g; int r; for (int i = 0; i < srcImage.rows; i++) { for (int

袋鼠雲數據臺專欄2.0 | 數據臺之數據集成

mongo redirect chat 信息交互 臟數據 ast 情況下 png 問題 關於袋鼠雲數據中臺專欄V2.0 數據中臺如何定義?企業數據化與數據中臺的關系是什麽?數據中臺如何支撐企業戰略轉型?袋鼠雲近兩年來,先後為國內數十家大型龍頭企業提供數據中臺咨詢與實施落地服

數據的事務並發問題探討

back zab 時間 www 同時存在 sql 執行 table keyword 數據庫中的事務和並發問題探討 引子 最近有同事寫了段代碼,負責創建訂單的邏輯,代碼審查時發現可能會有並發的問題。同事並不認同,他認為他的邏輯是寫在存儲過程中的,應該沒有問題。 代碼的邏輯大概

數據基礎知識:數據的約束三大範式

設計 一個 生效 訂單 詳細介紹 求長 山東 英文名稱 相關 一.數據庫中的範式:   範式, 英文名稱是 Normal Form,它是英國人 E.F.Codd(關系數據庫的老祖宗)在上個世紀70年代提出關系數據庫模型後總結出來的,範式是關系數據庫理論的基礎,也是我們在設計

SQLlite數據的附加分離

sqllite attach detach 在SQLlite數據庫中往往一個數據文件就是一個schema,但是在平時的業務或者是一些條件中可能是不同的內容存放在不同的schema中,即不同的數據文件,有的場景下需要數據關聯時就可以使用SQLlite的數據附加來建立一個臨時的鏈接。如下,在使用

PHP-Websockets 上傳檔案2 優化支援php socket客戶端websocket連線websocket伺服器 以守護程序方式執行編碼

WebsocketServer: users.php <?php class WebSocketUser { public $socket; public $id; public $headers = array(); public $handsh

SQL SERVER 將一個數據的表資料複製到另一個數據

第一種情況:將A資料庫.dbo.A表的資料追加到B資料庫.dbo.B表中 (條件:此時B資料庫中已建立好了B表) insert into B資料庫.dbo.B表 select * from A資料庫.dbo.A表 [where條件] 此T-SQL語句會有異常   &n

向動態連結新增類資源-並訪問動態連結的類資源

1#define  EXPORTDLL _declspec(dllimport); //定義一個巨集EXPORTDLL class CShowDlg{ public:  virtual void _stdcall ShowNote(char *pszText)//客戶端想要訪