如何禁止內部viewPager滑動

来源:http://www.cnblogs.com/tangZH/archive/2016/10/06/5934144.html
-Advertisement-
Play Games

眾所周知,viewPager是能夠滑動的,但有時候我們需要禁止它的滑動(微笑地面對*—……—*)。 情況是這樣的: activity中有一個viewPager,viewPager中加入3個Fragment,第三個Fragment中又使用了一個viewPager,這個viewPager中又加入了幾個F ...


眾所周知,viewPager是能夠滑動的,但有時候我們需要禁止它的滑動(微笑地面對*—……—*)。

情況是這樣的:

activity中有一個viewPager,viewPager中加入3個Fragment,第三個Fragment中又使用了一個viewPager,這個viewPager中又加入了幾個Fragment(本人不是受虐狂,僅僅是功能需要)。如圖:

想實現的功能:

點擊activity的圖標或者滑動的時候能夠切換第一個viewPager中的Fragment,點擊Fragment3中的圖標能夠切換第二個viewPager里的Fragment,但是禁止這個viewPager滑動第二個viewPager里的Fragment1裡面有一個listView(有下拉刷新功能),要能夠上下滑動不受影響。

關鍵就是禁止內部viewPager滑動,但是其它的功能不受影響。

呵呵,已經元氣大傷......

探索過程已經不想吐槽。

 

這個問題涉及到事件的分發機制,需要重寫viewPager。那麼到底該重寫哪個viewPager呢?

首先分析一下這個問題的解決過程:

1.要禁止裡面的viewPager左右滑動,那麼即是說當我們左右滑動的時候,外面的viewPager要攔截事件,當我們上下滑動的時候外面的viewPager不能攔截事件,這樣事件才能傳遞到內部的viewPager,內部viewPager里的fragment包含的listView才能上下滑動。

2.當然點擊事件也不能夠攔截,這樣點擊Fragment3的圖標才能切換內部viewPager裡面的Fragment。

3.由於內部viewPager在Fragment3,所以我們在外部的viewPager切換到item3的時候再做1,2步的處理。

 

在這裡重寫外部viewPager會比較方便,即我們用外部攔截法。

接下來請看外部攔截神功。

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import neo.door.usermanager.UserManager;

public class MyViewPager extends ViewPager {
    private int mFirstX =0,mFirstY=0;
    private String TAG = "MyViewPager";

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if(this.getCurrentItem()==2) //如果滑動到了第三個Fragment
        {
            boolean isIntercept=false;
            int x=(int) event.getX();
            int y=(int) event.getY();
            Log.e(TAG, "onInterceptTouchEvent");
            switch (event.getAction()) {
/**
    * 父容器必須返回false,即不攔截ACTION_DOWN事件,
    * 否則後續的ACTION_MOVE,ACTION_UP事件都會直接交給父容器處理,
    * 事件沒辦法再傳遞給子元素了
    */
case MotionEvent.ACTION_DOWN:
Log.e(TAG,
"onInterceptTouchEvent_ACTION_DOWN"); isIntercept=false;
break;
/**
     * 根據需要覺定是否攔截
     */
case MotionEvent.ACTION_MOVE: if (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)) //左右滑動 { isIntercept = true; if(正在下拉) //想刷新時候(若不寫這一步,如果我們向下滑到一半突然左右滑動那麼listView就會卡在中間狀態不動。) isIntercept=false; } else //上下滑動 { isIntercept = false; } Log.e(TAG, "onInterceptTouchEvent_ACTION_MOVE"); break;
/**
     * 必須返回false,因為ACTION_UP本身沒有太大意義。
 * 
     */
case MotionEvent.ACTION_UP: isIntercept=false; Log.e(TAG, "onInterceptTouchEvent_ACTION_UP"); break; default: break; } mFirstX=x; mFirstY=y; Log.e(TAG, "onInterceptTouchEvent_return"); return isIntercept; } else //如果沒有滑動到了第三個Fragment,不作處理 return super.onInterceptTouchEvent(event); } }

首先要知道 onInterceptTouchEvent這個方法,返回true代表攔截,返回false代表不攔截。

註意:

1.ACTION_UP。

考慮一種情況:若是事件交給子元素處理,而父容器在ACTION_UP的時候返回了true,那麼子元素就會無法收到ACTION_UP事件,子元素的onClik事件無法觸發,也就是說在這道題中,Fragment3的圖標將無法點擊,並且listView的滑動會在手指離開屏幕的時候停留在中間態。

父容器比較特殊,一旦它開始攔截任何一個事件,那麼後續事件都會交給它處理,ACTION_UP作為最後一個事件也一樣可以傳遞給父容器,即便父容器的onInterceptTouchEvent方法在ACTION_UP時返回了false。

2.ACTION_MOVE之中。

假如我們要刷新listView,在我們下拉listView的時候手指突然間左滑或者右滑,那麼listView就會停留在中間狀態。放開手也不會回去,為什麼呢?

原因是這樣的:在我們手指下滑的時候,在ACTION_MOVE中判斷後不符合 (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)),所以父容器即外部的viewPager返回false,不攔截事件,listView能夠滑動。但是當我們在下滑的時候突然間左右滑,那麼在ACTION_MOVE中判斷後符合 (Math.abs(x - mFirstX) > Math.abs(y - mFirstY)),所以父容器即外部的viewPager返回true,攔截了事件,所以listView無法完成事件,只是停留在了手指左右滑動之前的那個瞬間狀態。(這種情況最後的ACTION_UP沒有執行,這點還不理解)

所以我們要加個判斷,判斷listview是否正要下拉刷新,如果是,不要攔截事件。

至於判斷方法挺多的,就不再寫。

【寫到這裡,也就差不多了,以後若是有得補充再來補充吧。@—^—@】


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近一段時間正在對JavaScript進行學習,知識太多,需要進行實際的使用和總結,國慶長假正好有時間,寫了下麵對JavaScript總結,可能對事件的理解還不夠完善,希望讀者多多指導,拍磚,我將不勝感激。好了直接如題吧。 JavaScript中的事件流 DOM2級事件規定事件流分為3個階段: 第一 ...
  • 【BaseFragment】: 【LoadingPage】: ...
  • 【原因】: 在工程中既有本地的lib.jar文件,又有compile鏈接。 ...
  • 剛從 eclipse 轉到 android studio 的同學,編寫代碼時使用的快捷鍵不同,一時難以適應,當然可以通過設置,將快捷鍵模板設置成與 eclipse 相同的,但我個人不贊成,因為 Android Studio 裡面還有一些快捷鍵是 eclipse 裡面沒有的,所以還是通過項目來熟悉An ...
  • 網上有很多例子來演示Android客戶端和伺服器端數據如何實現交互不過這些例子大多比較繁雜,對於初學者來說這是不利的,現在介紹幾種代碼簡單、邏輯清晰的交互例子,本篇博客介紹第四種: 一、伺服器端: 代碼1:添加名為“AndroidServerServlet.Java”的文件 [java] view ...
  • 1.先重寫uiviewcontrol的方法 - (UIViewController *)viewController { for (UIView* next = [self superview]; next; next = next.superview) { UIResponder *nextRes ...
  • 概述在動畫中,我們會指定動畫的持續時間。例如scaleAnimation.duration = self.config.appearDuration那麼這個時間是怎麼定義的呢?是指的絕對時間嗎?層級時間結構layer在屏幕上的顯示位置是根據父layer的位置以及本身相對於父layer偏移定義的。與此... ...
  • iOS多線程技術方案 === 目錄 "一、多線程簡介" "1、多線程的由來" "2、耗時操作的模擬試驗" "3、進程和線程" "4、多線程的概念及原理" "5、多線程的優缺點和一個Tip" "6、主線程" "7、技術方案" "二、Pthread" "1、函數" "2、參數和返回值" "3、使用" " ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...