Android 群英傳筆記
第一章Android體系與系統(tǒng)架構
第二章 Android開發(fā)工具及技巧
第三章 Android控件架構與事件攔截機制
第四章 ListView 使用技巧
第五章 Android Scroll 分析
第六章 Android 繪圖機制與屏幕適配
第七章 Android 動畫機制與使用技巧
第八章 Activity與Activity調用棧分析
第九章 Android 系統(tǒng)信息與安全機制
第十章 Android性能優(yōu)化
本文出自:
http://www.reibang.com/u/a1251e598483
滑動效果是如何產生的
滑動一個View的本質其實就是移動一個View,改變其當前所在的位置,它的原理和動畫效果十分的相似,就是通過不斷的改變View的坐標來實現這一效果害捕,動態(tài)且不斷的改變View的坐標,從而實現View跟隨用戶觸摸滑動而滑動
但是在講解滑動效果之前贵白,需要先了解一下Android中窗口坐標體系和屏幕的觸控事件——MotionEvent
Android坐標系
在物理學上,要描述一個物體的運動,就必須選定一個參考系紊搪,所謂滑動卡儒,正是相對于參考系的運動田柔,在Android,系統(tǒng)將屏幕最左上角的頂點作為Android坐標系的原點骨望,從這個點向右是X軸正方向硬爆,從這個點向下是Y軸正方向,如圖
系統(tǒng)提供了getLocationOnScreen(intlocation[])來獲取Android坐標中的位置擎鸠,即該視圖左上角Android的坐標缀磕,另外,在觸摸事件中使用getRawX(),getRawY()方法來獲取坐標同樣是Android坐標系中的坐標劣光。
視圖坐標系
Android中除了上面所說的這種坐標系之外們還有一個視圖坐標系袜蚕,他描述了子視圖在父視圖的位置關系,這兩個坐標系并不復雜也不矛盾绢涡,他們的作用是相輔相成的牲剃,與Android坐標系類似,視圖坐標系同樣的以原點向右為X正方向垂寥,以原點向下為Y方法颠黎,只不過在視圖坐標系中另锋,原點不再是Android坐標系中的屏幕左上角,而是以父視圖左上角為坐標原點狭归,看圖
在觸控事件中通過getX,getY來獲取的坐標就是視圖坐標中的坐標
觸控事件——MotionEvent
觸控事件MotionEvent在用戶的交互中夭坪,占著舉足輕重的位置,學好觸控事件是掌握后續(xù)內容的基礎过椎,首先室梅,我們來看看MotionEvent中封裝的一些常量,他定義了觸摸事件的不同類型疚宇。
//單點觸摸按下的動作
public static final int ACTION_DOWN = 0;
//單點觸摸離開的動作
public static final int ACTION_UP = 1;
//單點觸摸移動的動作
public static final int ACTION_MOVE = 2;
//單點觸摸取消
public static final int ACTION_CANCEL = 3;
//單點觸摸超出邊界
public static final int ACTION_OUTSIDE = 4;
//多點觸摸按下的動作
public static final int ACTION_POINTER_DOWN = 5;
//多點觸摸離開的動作
public static final int ACTION_POINTER_UP = 6;
通常情況下亡鼠,我們會在onTouchEvent(MotionEvent event)方法中通過event.getAction()來獲取觸摸事件的類型,并使用switch來判斷敷待,這個代碼模塊是固定的 上一篇文章已經寫過了
@Override
public boolean onTouchEvent(MotionEvent event) {
//獲取當前輸入點的X,Y坐標(視圖坐標)
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//處理輸入的按下動作
break;
case MotionEvent.ACTION_MOVE:
//處理輸入的移動動作
break;
case MotionEvent.ACTION_UP:
//處理輸入的離開動作
break;
}
return true;
}
在不涉及多點觸控的前提下间涵,通常可以使用以下代碼來完成觸摸事件的監(jiān)聽榜揖,不過這里只是一個代碼模塊勾哩,后面我們會講具體的邏輯的
在Android中,系統(tǒng)提供了非常多的方法來獲取坐標值举哟,相對距離等思劳,方法豐富固然好桩皿,但也給初學者帶來了很多的困擾雇逞,不知道在什么情況下使用下圖總結人一下一些常用的API
這些方法可以分成兩個類別
View提供的獲取坐標方法
getTop():獲取到的是View自身的頂部到其父布局頂部的距離
getLeft():獲取到的是View自身的左邊到其父布局左邊的距離
getRight():獲取到的是View自身的右邊到其父布局右邊的距離
getBottom():獲取到的是View自身的底部到其父布局底部的距離
MotionEvent提供的方法
getX():獲取點擊事件距離控件左邊的距離粗悯,即視圖坐標
getY():獲取點擊事件距離控件頂部的距離魁兼,即視圖坐標
getRawX:獲取點擊事件整個屏幕左邊的距離斜做,即絕對坐標
getRawY:獲取點擊事件整個屏幕頂部的距離膘融,即絕對坐標
實現滑動的七種方法
當了解了Android坐標系和觸控事件之后坑夯,我們再來看一看如何使用系統(tǒng)提供的API來實現動態(tài)的修改一個View的坐標喂窟,即滑動效果森瘪,而不管采用哪種方式牡属,其實現的思路基本上是一樣的,當觸摸View的時候扼睬,系統(tǒng)幾下View的坐標逮栅,從而獲得到相對于之前坐標的偏移量,并通過偏移量來修改View的坐標窗宇,這樣不斷的重復就實現了滑動的過程措伐。
下面我們通過實例來看看Android中如何實現滑動的效果沒定義一個View,簡單的實現一個布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.younger.youngertest.MainActivity">
<com.example.younger.youngertest.MyView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@android:color/holo_orange_dark"
>
</com.example.younger.youngertest.MyView>
</LinearLayout>
默認的顯示樣子
layout方法
我們都知道军俊,在View的繪制上侥加,會調用onLayout()方法來設置顯示的位置,同樣可以修改View的left,top,right,bottom四個屬性來控制View的坐標粪躬,與前面提供的模板代碼一樣担败,每次調用onTouchEvent()的時候昔穴,我們來獲取點的坐標,這里的邏輯很清楚,真的提前,我們來看看
//觸摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
int lastX = 0;
int lastY = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//記錄觸摸點的坐標
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//計算偏移量
int officeX = rawX - lastX;
int officeY = rawY - lastY;
//在當前的left,top,right,bottom基礎上加上偏移量
layout(getLeft()+officeX,getTop()+officeY,getRight()+officeX,getBottom()+officeY);
//重新設置初始值
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_UP:
//處理輸入的離開動作
break;
}
return true;
}
offsetLeftAndRight()與offsetTopAndBottom()
這個方法相當于系統(tǒng)提供的一個對左右吗货,上下移動的封裝,當計算出偏移量的時候狈网,只需要使用如下的代碼就可以完成View的重新布局宙搬,效果和使用Layout()方法是一樣的
//同時對左右偏移
offsetLeftAndRight(officeX);
//同時對上下偏移
offsetTopAndBottom(officeY);
LayoutParams
LayoutParams保留了一個View的布局參數,因此可以在程序中拓哺,通過改變LayoutParams來動態(tài)改變一個布局的位置參數勇垛,從而改變View位置的效果,我們可以很方便的在程序中使用getLayoutParams()來獲取一個View的LayoutParams士鸥,當然闲孤,在計算偏移量的方法和Layout方法中計算offset是一樣的,當獲取到偏移量之后烤礁,可以通過setLayoutParams來改變LayoutParams崭放,代碼如下
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft()+officeX;
layoutParams.topMargin = getTop()+officeY;
setLayoutParams(layoutParams);
不過這里需要注意的是,通過getLayoutParams()獲取layoutParams時鸽凶,需要根據View所在的跟布局的類型來設置不同的類型,建峭,比如View放在LinearLayout里那就是 LinearLayout.LayoutParams玻侥,比如在RelativeLayout里就是 RelativeLayout.LayoutParams,不然系統(tǒng)是無法獲取到layoutParams的.
在通過一個layoutParams來改變一個View的位置時亿蒸,通常改變的是這個view的Margin屬性凑兰,所以除了使用布局的layoutParams屬性外,還需要 ViewGroup.MarginLayoutParams來實現這樣的功能
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft()+officeX;
layoutParams.topMargin = getTop()+officeY;
setLayoutParams(layoutParams);
我們可以發(fā)現边锁,用ViewGroup更好姑食,都不用去管父布局是什么
scrollTo與scrollBy
在一個View當中,系統(tǒng)提供了scrollTo與scrollBy這兩種方式來實現移動一個View的位置茅坛,這兩種方法的區(qū)別也很好理解音半,to和by, scrollTo(x,y);表示移動到一個具體的 點贡蓖,scrollBy(dx,dy);表示移動的增量
int officeX = rawX - lastX;
int officeY = rawY - lastY;
scrollBy(officeX,officeY);
但是曹鸠,當我們拖動View的時候,你會發(fā)現View并沒有移動斥铺,難道我們寫錯了彻桃?方法沒有寫錯,View也的確移動了晾蜘,但是他移動的并不是我們想要的東西邻眷,他只是移動了view的content眠屎,即讓View的內容移動了,如果用ViewGroup使用to和by的話肆饶,那所有的子View都將移動改衩,要是在View中使用的話,抖拴,那么移動的就是View的內容了燎字,我們舉個例子,比如TextView阿宅,content就是他的文本候衍,ImageView,drawable就是對象
相信通過上面的分析洒放,你也應該知道為什么不能再View里面使用這個兩個方法來拖動這個view了蛉鹿,那么我們就該View所在的ViewGroup中使用scrollBy方法來移動這個view
((View)getParent()).scrollBy(officeX,officeY);
但是,當再次拖動View的時候往湿,你會發(fā)現View雖然移動了妖异,但卻在亂動,并不是我們想要的跟隨觸摸點的移動而移動领追,這里需要先了解一下視圖移動的一些知識他膳,大家在理解這個問題的時候,不妨想象一下手機是一個中空的蓋板绒窑,蓋板下面是一個巨大的畫布棕孙,也就是我們想要顯示的視圖,當把這個蓋板蓋在畫布的某處時些膨,透過中間空著的矩形蟀俊,我們看見了手機屏幕上顯示的視圖,而畫布上其他的視圖订雾,則被蓋板蓋住了無法看見肢预,我們的視圖和這個例子事項相似,我們沒有看見視圖洼哎,但并不代表它不存在烫映,有可能只是在屏幕外面而已,當調用scrollBy的方法時谱净,可以想象外面的蓋板在移動窑邦,這么說比較抽象,我們來看一下具體的例子
上圖壕探,中間的矩形相當于屏幕冈钦,即可是區(qū)域,后面的content相當于畫布李请,代表視圖瞧筛,大家可以看到厉熟,只有視圖的中間部分目前是可視的,其他部分都不可見较幌,可見區(qū)域中設置一個button,他的坐標是(20.10)揍瑟,下面我們使用scrollBy方法來進行移動后如圖
我們會發(fā)現,雖然設置scrollBy(20.10)乍炉,偏移量均為XY的正方向绢片,但是屏幕的可視區(qū)域,Button卻向反方向移動了岛琼,這就是參考系選擇的不同底循,而產生的不同效果。
通過上面的分析槐瑞,可以發(fā)現熙涤,我們將scrollBy的參數dx,dy設置成正數,那么content將向坐標軸負方向移動困檩,反之祠挫,則正方向
int officeX = rawX - lastX;
int officeY = rawY - lastY;
scrollBy(-officeX,-officeY);
可以發(fā)現,效果和前面的幾種方法相同了悼沿,類似的等舔,我們使用scrollTo也是可以實現的
Scroller
既然提到scrollTo與scrollBy,那就不得不提一下Scroller類了糟趾,Scroller和scrollTo與scrollBy十分的相似软瞎,有著千絲萬縷的關系,那么他們有什么具體的區(qū)別尼拉讯?要解答這個問題,首先我們來看一個小栗子鳖藕,假設要完成這樣的一個效果:點擊button,讓一個viewgroup的子View移動100像素魔慷,問題看似很簡單,只要使用scrollBy的方法就可以著恩,的確院尔,用這個方法確實可以,可是那都是一瞬間完成的事情喉誊,很突兀邀摆,而Scroller就可以實現平滑的效果,而不再是一瞬間的事情.
說道Scroller的原理伍茄,其實他與前面使用scrollTo與scrollBy的方法原理是一樣的栋盹,下面我們通過一個小栗子來演示一下
- 初始化scroller
首先,通過他的構造方法來創(chuàng)建一個scroller對象
//初始化mScroller
mScroller = new Scroller(context);
- 重寫computeScroll敷矫,實現模擬滑動
下面我們需要重寫computeScroll這個方法例获,他是使用Scroller的核心汉额,系統(tǒng)在繪制View的同時,會在onDraw()方法中調用這個方法榨汤,這個方法實際上就是使用了ScrollTo()方法再結合Scroller對象蠕搜,幫助獲取到當前的滾動值,我們可以通過不斷的瞬息移動一個小的距離來實現整體上的平滑移動效果收壕,通常情況下妓灌,computeScroll的代碼可以利用標準的寫法:
/**
* 模擬滑動
*/
@Override
public void computeScroll() {
super.computeScroll();
//判斷Scroller是否執(zhí)行完畢
if(mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
}
//通過重繪來不斷調用computeScroll
invalidate();
}
Scroller類提供了computeScrollOffset()來判斷是否完成了整個頁面的滑動,蜜宪,同時也提供了getCurrX()虫埂,getCurrY()來獲取當前滑動坐標,上面唯一要注意的就是invalidate()了端壳,因為只能在computeScroll中獲得模擬過程中的scrollX,scrollY,坐標告丢,但computeScroll方法是不會自動調用的,只能通過invalidate——》OnDraw——》computeScroll來簡介調用损谦,所以需要這個invalidate岖免,而當模擬過程結束的時候,computeScrollOffset返回的是false照捡,從而結束循環(huán)
- startScroll開啟模擬過程
最后颅湘,萬事俱備只欠東風了,我們需要使用平滑移動事件栗精,使用Scroller類的startScroll()方法來開啟平滑過程闯参,startScroll有兩個重載的方法
public void startScroll(int startX,int startY,int dx,int dy,int duration)
public void startScroll(int startX,int startY,int dx,int dy)
可以看到他們的區(qū)別分別是具有指定的持續(xù)時長,而另一個沒有悲立,這個非常好理解鹿寨,與在動畫中的設置時間是一樣的,而其他四個坐標薪夕,就是起始和偏移量脚草,通過上述的步驟,就可以完成一個平移的效果了原献,下面我們回到實例馏慨,在構造分鐘初始化Scroller對象,然后重寫computeScroll方法姑隅,最后需要監(jiān)聽手指離開屏幕的事件写隶,并在該事件之后調用startScroll()完成平移,所以我們在ACTION_UP中
case MotionEvent.ACTION_UP:
//處理輸入的離開動作
View view = ((View)getParent());
mScroller.startScroll(view.getScrollX(),view.getScrollY(),view.getScrollX(),view.getScrollY());
invalidate();
break;
屬性動畫
在本書中第七章將會詳細介紹讲仰,這里就不重復了
ViewDragHelper
Google在其support庫中為我們提供了一個DrawerLayout和SlidingPaneLayout兩個布局來幫助開發(fā)者實現策劃效果慕趴,這兩個布局,大大的方便了我們自己創(chuàng)建自己的滑動布局,然而秩贰,這兩個強大的布局背后霹俺,卻隱藏著一個鮮為人知,卻功能強大的類——ViewDragHelper毒费,通過ViewDragHelper丙唧,基本可以實現各種不同的側滑,拖放需求觅玻,因此這個方法也是各種滑動解決方案的終極絕招
ViewDragHelper雖然很強大想际,但是使用也是本章節(jié)最復雜 的,我們需要了解ViewDragHelper的基本使用方法的基礎上溪厘,通過不斷的練習去掌握它胡本,我們這里就實現一個 QQ滑動側邊欄的布局,我么來看看具體怎么實現的
- 初始化ViewDragHelper
ViewDragHelper通常定義在一個ViewGroup中畸悬,通過其靜態(tài)方法初始化
mViewDragHelper = ViewDragHelper.create(this,callback);
他的第一個參數是要監(jiān)聽的View,第二個參數是一個Callback回調
- 攔截事件
要重寫攔截事件侧甫,將事件傳遞給ViewDragHelper進行處理
//事件攔截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
//觸摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//將觸摸事件傳遞給ViewDragHelper
mViewDragHelper.processTouchEvent(event);
return true;
}
- 處理computeScroll()
使用ViewDragHelper也是需要重寫computeScroll的,因為ViewDragHelper內部也是通過Scroller來實現平移的蹋宦,我們可以這樣使用
@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
- 處理回調Callback
//側滑回調
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
//何時開始觸摸
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果當前觸摸的child是mMainView開始檢測
return mMainView == child;
}
//處理水平滑動
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
//處理垂直滑動
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
//拖動結束后調用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手指抬起后緩慢的移動到指定位置
if(mMainView.getLeft() <500){
//關閉菜單
mViewDragHelper.smoothSlideViewTo(mMainView,0,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}else{
//打開菜單
mViewDragHelper.smoothSlideViewTo(mMainView,300,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
通過一步步的分析披粟,現在要實現QQ的側滑,是不是非常簡單了尼冷冗,下面自定義一個viewGroup來完成整個編碼的實例
//XML加載組建后回調
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mMainView = getChildAt(1);
}
//組件大小改變時回調
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mMenuView.getMeasuredWidth();
}
最后 整個view 的代碼
package com.example.younger.youngertest;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
/**
* Created by Younger on 2018/3/6.
*/
public class DragView extends FrameLayout {
private ViewDragHelper mViewDragHelper;
private View mMenuView, mMainView;
private int mWidth;
public DragView(@NonNull Context context) {
super(context);
initView();
}
public DragView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
public DragView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public DragView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mMainView = getChildAt(1);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mMenuView.getMeasuredWidth();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//將觸摸事件傳遞給ViewDragHelper,此操作必不可少
mViewDragHelper.processTouchEvent(event);
return true;
}
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
private void initView() {
mViewDragHelper = ViewDragHelper.create(this, callback);
}
private ViewDragHelper.Callback callback =
new ViewDragHelper.Callback() {
// 何時開始檢測觸摸事件
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果當前觸摸的child是mMainView時開始檢測
return mMainView == child;
}
// 觸摸到View后回調
@Override
public void onViewCaptured(View capturedChild,
int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}
// 當拖拽狀態(tài)改變守屉,比如idle,dragging
@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);
}
// 當位置改變的時候調用,常用與滑動時更改scale等
@Override
public void onViewPositionChanged(View changedView,
int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
// 處理垂直滑動
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
// 處理水平滑動
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
// 拖動結束后調用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手指抬起后緩慢移動到指定位置
if (mMainView.getLeft() < 500) {
//關閉菜單
//相當于Scroller的startScroll方法
mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(DragView.this);
} else {
//打開菜單
mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
ViewCompat.postInvalidateOnAnimation(DragView.this);
}
}
};
}
XML 的寫法
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.younger.youngertest.DragView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/view"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_light">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Menu" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_dark">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Main" />
</FrameLayout>
</com.example.younger.youngertest.DragView>
</RelativeLayout>
- 這里只是非常簡單的模擬了一下
//用戶觸摸到view回調
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}
- onViewDragStateChanged
//拖拽狀態(tài)改變時蒿辙,比如idle,dragging
@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);
}
- onViewPositionChanged
//位置發(fā)生改變拇泛,常用于滑動scale效果
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
好了 ,Scroll 分析到此結束.