View屬性知識手札
View的位置引數:
- event.getX() :表示的是觸控的點距離自身左邊界的距離;
- event.getRawY() :表示的是觸控點距離螢幕上邊界的距離;
- View.getLeft() :子View的左邊界到父View的左邊界的距離;
- View.getTranslationX() :表示在X軸的偏移量。初始值為0,向左偏移為負,向右偏移為正。
View在平移過程中,View.getLeft()的值不會改變,此時改變的是translationX和View的座標值。
View的左上角x座標 = View.getLeft() + View.getTranslationX();
TouchSlop:系統所能識別出的最小滑動距離,該值和裝置有關。
int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
VelocityTracker:表示手指在滑動過程中的速度(pix/ms),包括水平方向和豎直方向的速度。
//初始化 VelocityTracker velocityTracker = VelocityTracker.obtain(); @Override public boolean onTouchEvent(MotionEvent event) { velocityTracker.addMovement(event);//速度追蹤 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: //獲取1000ms內的平均速度(從右向左滑動時,水平方向速度為負值) velocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) velocityTracker.getXVelocity(); Log.d("test", "xVelocity=" + xVelocity); break; } velocityTracker.clear(); //velocityTracker.recycle(); return super.onTouchEvent(event); }
GestureDetector:手勢檢測,用於檢測使用者的單擊、滑動、長按、雙擊等行為。
//初始化,引數宜繼承SimpleOnGestureListener類,根據需要重寫父類方法。 GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //可在此判斷左滑還是右滑 return super.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } }); //在onTouchEvent方法內監聽事件處理 gestureDetector.onTouchEvent(event);
- onScroll: 手指按下螢幕並拖動,由一個ACTION_DOWN、多個ACTION_MOVE事件觸發,這是拖動行為。在拖動過程中onScroll會反覆 被呼叫。
- onFling: 手指按下觸控式螢幕、快速滑動後鬆開,由1個ACTION_DOWN、多個ACTION_MOVE和1個ACTION_UP觸發,這是快速滑動行為。在一次滑動中onFling被呼叫一次,適合在此方法中處理手勢相關操作。
Scroller:用於實現View的彈性滑動,提升滑動過渡效果。
一般用於scrollTo/scrollBy方法,需要和View.computeScroll()配合完成View的彈性滑動。
Scroller scroller = new Scroller(context);//初始化
/** * 彈性滑動到指定位置 * * @param x * @param y */ public void smoothScrollTo(int x, int y) { //根據提供的初始位置、滑動距離和持續時間彈性滑動 scroller.startScroll(getScrollX(), getScrollY(), x - getScrollX(), y - getScrollY(), 2000); invalidate(); } /** * Scroller類滑動原理(針對view內容的滑動) * 1.invalidate()會促使view的重繪; * 2.view的重繪會在draw方法中呼叫computeScroll(); * 3.外部重寫computeScroll(),通過scrollTo將view內容滑動到相應位置, * 並呼叫postInvalidate觸發重繪,123迴圈執行; */ @Override public void computeScroll() { super.computeScroll(); //類似插值器,true表示滑動未結束,繼續滑動 if (scroller.computeScrollOffset()) { scrollTo(scroller.getCurrX(), scroller.getCurrY()); postInvalidate(); } }
view.smoothScrollTo(-500,-500);//外部呼叫
scrollTo/scrollBy:將View中的內容滑動到相應的位置或距離,正值向左移動,負值向右移動(不改變View的位置)。
view.scrollTo(100,0);//將view中的內容移動到(100,0)位置。 view.scrolloBy(100,0);//將view中的內容x方向移動了100pix。 public void scrollBy(int x, int y) { //mScrollX是view在x方向的偏移量 scrollTo(mScrollX + x, mScrollY + y); }
實現View的滑動的常見思路:
-
通過View本身提供的scrollTo/scrollBy方法實現滑動。
場景: 適合對View內容的滑動。 -
通過動畫給View施加平移效果來實現滑動。
場景: 適合沒有互動的View、簡單些的動畫效果。 -
通過改變View的LayoutParams使得View重新佈局從而實現滑動。
場景: 適合有互動的View。
//2.採用動畫實現2000ms內橫向滑動500pix ObjectAnimator.ofFloat(view, "translationX", 0, 500) .setDuration(2000) .start(); //3.設定佈局引數實現滑動 ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) t.ok.getLayoutParams(); params.leftMargin += 5; t.ok.requestLayout(); t.ok.setLayoutParams(params);
View的彈性滑動是將一次大的滑動分成若干次小的滑動並在一個時間段內完成,提升互動體驗。一般採用Scroller、Handler#postDelayed以及Thread#sleep等。