View是Android中全部控件的基類,view自己能夠是單控件也能夠是由多控件組成的控件android
View的位置參數:api
‘ide
View自身提供的獲取座標的方法:函數
getTop():獲取view自身的頂邊到其父佈局頂邊的距離。佈局
getLeft():獲取view自身的左邊到其父佈局左邊的距離。post
getRight():獲取view自身的右邊到其父佈局左邊的距離。性能
getBottom():獲取view自身的底邊到其父佈局頂邊的距離。動畫
手指接觸屏幕鎖產生的事件,經常使用的以下:this
ACTION_DOWN——手指剛接觸屏幕google
ACTION_MOVE——手指在屏幕上移動
ACTION_UP——手指從屏幕上鬆開的一瞬間
MotionEvent提供的方法:
getX() :獲取點擊事件距離控件左邊的距離,即視圖座標。
getY() :獲取點擊事件距離控件頂邊的距離,即視圖座標。
getRawX():獲取點擊事件距離整個屏幕左邊的距離,即絕對座標。
getRawY():獲取點擊事件距離整個屏幕頂邊的距離,即絕對座標。
根據方法註釋理解這個touchSlop是一個滑動距離值的常量,也就是說當咱們手觸摸在屏幕上滑動時,若是滑動距離沒有超過touchSlop值的話 ,android系統自己是不會認爲咱們在屏幕上作了手勢滑動,所以只有當咱們在屏幕上的滑動距離超過touchSlop值時,android系統自己纔會認爲咱們作了滑動操做並去響應觸摸事件,不過要注意的是不一樣的設備,touchSlop的值多是不一樣的,一切以上述的函數獲取爲準
VelocityTracker是個速度跟蹤類,用於跟蹤手指滑動的速度,包括x軸方向和y軸方向的速度。
使用過程:在view的onTouchEvent方法中追蹤當前單擊事件的速度
VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event);
當咱們想知道當前的滑動速度時,能夠採用以下方式來獲取當前的速度:
velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); int yVelocity = (int) velocityTracker.getYVelocity();
若是不須要使用它時,須要調用clear方法來重置並回收內存:
velocityTracker.clear(); velocityTracker.recycle();
computeCurrentVelocity (int units),基於當前咱們所收集到的點計算當前的速率,當咱們肯定要得到速率信息的時候,在調用該方法,由於使用它須要消耗很大的性能。
參數:units 咱們想要指定的獲得的速度單位,若是值爲1,表明1毫秒運動了多少像素。若是值爲1000,表明1秒內運動了多少像素。這個方法還有一個重載函數 computeCurrentVelocity (int units, float maxVelocity), 跟上面同樣也就是多了一個參數。
參數:maxVelocity 該方法所能獲得的最大速度,這個速度必須和你指定的units使用一樣的單位,並且必須是整數.也就是,你指定一個速度的最大值,若是計算超過這個最大值,就使用這個最大值,不然,使用計算的的結果,
這個最大速度能夠經過ViewConfiguration.get(context).getScaledMaximumFlingVelocity()方式獲取。
getXVelocity()和getYVelocity() ,這兩個很簡單,得到橫向和豎向的速率。前提是必定要先調用computeCurrentVelocity (int units)函數計算當前速度!
速度的計算公式,能夠用下列公式來表示,因此說速度能夠時負數:
速度 = (終點位置 - 起點位置) / 時間段
手勢監聽類,用於輔助檢測用戶的單擊、滑動、長按、雙擊等行爲
使用:先建立一個GestureDetector對象並實現OnGestureListener接口,根據須要還能夠實現OnDoubleTapListener從而可以監聽雙擊行爲:
GestureDetector gestureDetector = new GestureDetector(this); //解決長按屏幕後沒法拖動的現象 gestureDetector.setIsLongpressEnabled(false);
接着,接管目標View的onTouchEvent方法,在須要等待監聽的View中的onTouchEvent方法中添加以下實現:
boolean consume = gestureDetector.onTouchEvent(event); return consume;
// 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發 public boolean onDown(MotionEvent arg0) { Log.i("MyGesture", "onDown"); Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show(); return true; } /* * 用戶輕觸觸摸屏,還沒有鬆開或拖動,由一個1個MotionEvent ACTION_DOWN觸發 * 注意和onDown()的區別,強調的是沒有鬆開或者拖動的狀態 */ public void onShowPress(MotionEvent e) { Log.i("MyGesture", "onShowPress"); Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show(); } // 用戶(輕觸觸摸屏後)鬆開,由一個1個MotionEvent ACTION_UP觸發 // 很是快的點擊Touchup:onDown>onSingleTapUp>onSingleTapConfirmed // 稍微慢點的點擊Touchup:onDown>onShowPress>onSingleTapUp>onSingleTapConfirmed public boolean onSingleTapUp(MotionEvent e) { Log.i("MyGesture", "onSingleTapUp"); Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show(); return true; } // 用戶按下觸摸屏、快速移動後鬆開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發 // 參數一:第一個MotionEvent // 參數二:最後一個MotionEvent // 參數三:velocityX X軸上的移動速度,像素/秒 // 參數四:velocityY Y軸上的移動速度,像素/秒 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.i("MyGesture", "onFling"); Toast.makeText(this, "onFling", Toast.LENGTH_LONG).show(); return true; } // 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發 // 滑屏:手指觸動屏幕後,稍微滑動後當即鬆開onDown-->onScroll-->onScroll-->onScroll-->onFling // 拖動: onDown-->onScroll-->onScroll-->onFiling public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.i("MyGesture", "onScroll"); Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show(); return true; } // 用戶長按觸摸屏,由多個MotionEvent ACTION_DOWN觸發 //觸發順序:onDown->onShowPress->onLongPress public void onLongPress(MotionEvent e) { Log.i("MyGesture", "onLongPress"); Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show(); }
// 單擊時發出通知。 @Override public boolean onSingleTapConfirmed(MotionEvent e) { return false; } // 發生雙擊時通知。 @Override public boolean onDoubleTap(MotionEvent e) { return false; } //當發生雙擊手勢中的事件(包括向下,向上和向上事件)時通知。 @Override public boolean onDoubleTapEvent(MotionEvent e) { return false; }
google官方api:
https://developer.android.com/reference/android/view/GestureDetector.OnDoubleTapListener
彈性滑動對象,用來實現View的彈性滑動,Scroller自己沒法讓view彈性滑動,它須要和view的computeScroll方法配合使用才能共同完成這個功能。
實現view滑動的三種方式:
scrollTo跟scrollBy其移動的本質都是View/ViewGroup中的內容,而且移動的過程都是瞬間完成的
scrollTo喝scrollBy都是View中的方法,不是Scroller中的方法,可是控制View的平滑移動與Scroller類密不可分。
scrollTo() : **指是的移動的絕對位置,若是位置沒有變化,屢次調用則不會起做用。
scrollBy() : **其本質依然是調用的scrollTo(),指的的移動當前位置的相對距離(每次都是先將當前的位置和設置的距離相加之和調用scrollTo(),這樣若是你屢次調用,你就會發現其每次都會移動一段距離,這是和scrollTo()的本質區別)
/** * Set the scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param x the x position to scroll to * @param y the y position to scroll to */ public void scrollTo(int x, int y) { if (mScrollX != x || mScrollY != y) { int oldX = mScrollX; int oldY = mScrollY; mScrollX = x; mScrollY = y; invalidateParentCaches(); onScrollChanged(mScrollX, mScrollY, oldX, oldY); if (!awakenScrollBars()) { postInvalidateOnAnimation(); } } } /** * Move the scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param x the amount of pixels to scroll by horizontally * @param y the amount of pixels to scroll by vertically */ public void scrollBy(int x, int y) { scrollTo(mScrollX + x, mScrollY + y); }
scrollBy實際上也是調用了scrollTo方法,它實現了基於當前位置的相對滑動,而scrollTo則實現了基於所傳遞參數的絕對滑動
view若是從左向右滑動,那麼mScrollX爲負值,不然爲正值;若是從上往下滑動,那麼mScrollY爲負值,不然爲正值
經過動畫可讓一個view進行平移,平移也能夠說是一種滑動,使用動畫來移動view,主要是操做view的translationX和translationY屬性,既能夠採用傳統的view動畫,也可使用屬性動畫
若是想給button向右移動,只須要將這個button的LayoutParams裏的marginLeft參數的值增長100px便可
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams(); params.width += 100; params.leftMargin += 100; button.setLayoutParams(params);