自定義ScrollView 實現上拉下拉的回彈效果--並且子控制項中有Viewpager的情況

来源:https://www.cnblogs.com/ganchuanpu/archive/2018/05/01/8977283.html
-Advertisement-
Play Games

onInterceptTouchEvent就是對子控制項中Viewpager的處理:左右滑動應該讓viewpager消費 ...


onInterceptTouchEvent就是對子控制項中Viewpager的處理:左右滑動應該讓viewpager消費

  1 public class MyScrollView extends ScrollView {
  2 
  3     private View childView;
  4 
  5     public MyScrollView(Context context) {
  6         super(context);
  7     }
  8 
  9     public MyScrollView(Context context, AttributeSet attrs) {
 10         super(context, attrs);
 11     }
 12 
 13     public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
 14         super(context, attrs, defStyleAttr);
 15     }
 16 
 17 //    @Override
 18 //    protected void onLayout(boolean changed, int l, int t, int r, int b) {
 19 //        super.onLayout(changed, l, t, r, b);
 20 //    }
 21 
 22     //獲取子視圖
 23     @Override
 24     protected void onFinishInflate() {
 25         super.onFinishInflate();
 26         if (getChildCount() > 0) {
 27             childView = getChildAt(0);
 28         }
 29     }
 30 
 31     private int lastY;//上一次y軸方向操作的坐標位置
 32     private Rect normal = new Rect();//用於記錄臨界狀態的左、上、右、下
 33     private boolean isFinishAnimation = true;//是否動畫結束
 34 
 35     private int lastX, downX, downY;
 36 
 37     //攔截:實現父視圖對子視圖的攔截
 38     //是否攔截成功,取決於方法的返回值。返回值true:攔截成功。反之,攔截失敗
 39     @Override
 40     public boolean onInterceptTouchEvent(MotionEvent ev) {
 41         boolean isIntercept = false;
 42         int eventX = (int) ev.getX();
 43         int eventY = (int) ev.getY();
 44         switch (ev.getAction()) {
 45             case MotionEvent.ACTION_DOWN:
 46                 lastX = downX = eventX;
 47                 lastY = downY = eventY;
 48                 break;
 49             case MotionEvent.ACTION_MOVE:
 50                 //獲取水平和垂直方向的移動距離
 51                 int absX = Math.abs(eventX - downX);
 52                 int absY = Math.abs(eventY - downY);
 53 
 54                 if(absY > absX && absY >= UIUtils.dp2px(10)){
 55                     isIntercept = true;//執行攔截
 56                 }
 57 
 58                 lastX = eventX;
 59                 lastY = eventY;
 60                 break;
 61         }
 62 
 63         return isIntercept;
 64     }
 65 
 66     @Override
 67     public boolean onTouchEvent(MotionEvent ev) {
 68         if (childView == null || !isFinishAnimation) {
 69             return super.onTouchEvent(ev);
 70         }
 71 
 72         int eventY = (int) ev.getY();//獲取當前的y軸坐標
 73         switch (ev.getAction()) {
 74             case MotionEvent.ACTION_DOWN:
 75                 lastY = eventY;
 76                 break;
 77             case MotionEvent.ACTION_MOVE:
 78 
 79                 int dy = eventY - lastY;//微小的移動量
 80 
 81                 if (isNeedMove()) {
 82                     if (normal.isEmpty()) {
 83                         //記錄了childView的臨界狀態的左、上、右、下
 84                         normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
 85 
 86                     }
 87                     //重新佈局
 88                     childView.layout(childView.getLeft(), childView.getTop() + dy / 2, childView.getRight(), childView.getBottom() + dy / 2);
 89                 }
 90 
 91                 lastY = eventY;//重新賦值
 92                 break;
 93             case MotionEvent.ACTION_UP:
 94                 if (isNeedAnimation()) {
 95                     //使用平移動畫
 96                     int translateY = childView.getBottom() - normal.bottom;
 97                     TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
 98                     translateAnimation.setDuration(200);
 99 //                translateAnimation.setFillAfter(true);//停留在最終位置上
100 
101                     translateAnimation.setAnimationListener(new Animation.AnimationListener() {
102                         @Override
103                         public void onAnimationStart(Animation animation) {
104                             isFinishAnimation = false;
105                         }
106 
107                         @Override
108                         public void onAnimationEnd(Animation animation) {
109                             isFinishAnimation = true;
110                             childView.clearAnimation();//清除動畫
111                             //重新佈局
112                             childView.layout(normal.left, normal.top, normal.right, normal.bottom);
113                             //清除normal的數據
114                             normal.setEmpty();
115                         }
116 
117                         @Override
118                         public void onAnimationRepeat(Animation animation) {
119 
120                         }
121                     });
122 
123                     //啟動動畫
124                     childView.startAnimation(translateAnimation);
125                 }
126 
127 
128                 break;
129         }
130 
131 
132         return super.onTouchEvent(ev);
133     }
134 
135     //判斷是否需要執行平移動畫
136     private boolean isNeedAnimation() {
137         return !normal.isEmpty();
138 
139     }
140 
141     private boolean isNeedMove() {
142         int childMeasuredHeight = childView.getMeasuredHeight();//獲取子視圖的高度
143         int scrollViewMeasuredHeight = this.getMeasuredHeight();//獲取佈局的高度
144 
145         Log.e("TAG", "childMeasuredHeight = " + childMeasuredHeight);
146         Log.e("TAG", "scrollViewMeasuredHeight = " + scrollViewMeasuredHeight);
147 
148         int dy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0
149 
150         int scrollY = this.getScrollY();//獲取用戶在y軸方向上的偏移量 (上 + 下 -)
151         if (scrollY <= 0 || scrollY >= dy) {
152             return true;//按照我們自定義的MyScrollView的方式處理
153         }
154         //其他處在臨界範圍內的,返回false。即表示,仍按照ScrollView的方式處理
155         return false;
156     }
157 }

 


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

-Advertisement-
Play Games
更多相關文章
  • 原文鏈接:http://www.cnblogs.com/xrq730/p/8944539.html,轉載請註明出處,謝謝 本文目錄 上一篇文章以認識Redis為主,寫了Redis系列的第一篇,現在開啟第二部分的學習,在本文中,我們將看到以下內容: Redis數據結構String、Hash、List、 ...
  • 連接查詢:同時設計兩個及以上的表的查詢 連接條件或連接謂詞:用來連接兩個表的條件一般格式: [<表名1>]<列名1> <比較運算符> [<表名2>]<列名2> [<表名1>]<列名1> between [<表名2>]<列名2> and [<表名2>]<列名3> 等值連接: 連接運算符為= 查詢每個學 ...
  • linux上安裝redis,本地遠程訪問問題總結,redis超時連接問題 ...
  • MongoDB運行的兩種方式 檢查是否有MongoDB:which mongod 創建資料庫存儲目錄:mkdir -p /data/db 檢查磁碟目錄是否有空間(一般要大於4G):df -lh 啟動:a直接啟動:mongod --dbpath=/data/db --port=27017 b守護進程的 ...
  • 對oracle資料庫,PL/SQL用法的快速學習 ...
  • 一、超級管理員創建及開啟登錄驗證 如果MongoDB要開啟登錄驗證,必須在開啟登錄驗證之前先創建好超級管理員,否則無法登錄資料庫! 例如,創建一個超級管理員admin,關聯給admin資料庫,角色設置為root(超級管理員) 首先,進入到目標庫admin,use admin 然後,輸入指令 db.c ...
  • 在Android開發過程中,耗時操作是不允許寫在主線程(UI線程)中的,以免由於等待時間過長而發生ANR。所以耗時操作需要創建子線程來完成,然而往往這些操作都需要與主線程進行通訊交互(例如更新主線程的UI),但android規定除了UI線程外,其他線程都不可以對UI控制項進行訪問或操控,所以我們需要通 ...
  • 上一篇主要分析了Robust的使用方法,這一篇就來總結一下Robust的源碼分析。 我個人傾向於將Robust框架分為兩個部分,自動插入代碼和動態載入Patch。 一、Robust源碼分析 目前我的分析將Robust動態載入分為兩個部分,一部分是插樁後的代碼邏輯,一部分是拉取Patch的邏輯。 我們 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...