View

什麼是View

        View是Android中全部控件的基類,view自己能夠是單控件也能夠是由多控件組成的控件android

 

View的位置參數:api

ide

View自身提供的獲取座標的方法:函數

getTop():獲取view自身的頂邊到其父佈局頂邊的距離。佈局

getLeft():獲取view自身的左邊到其父佈局左邊的距離。post

getRight():獲取view自身的右邊到其父佈局左邊的距離。性能

getBottom():獲取view自身的底邊到其父佈局頂邊的距離。動畫

 

MotionEvent

手指接觸屏幕鎖產生的事件,經常使用的以下:this

ACTION_DOWN——手指剛接觸屏幕google

ACTION_MOVE——手指在屏幕上移動

ACTION_UP——手指從屏幕上鬆開的一瞬間

 

MotionEvent提供的方法:

getX() :獲取點擊事件距離控件左邊的距離,即視圖座標。

getY() :獲取點擊事件距離控件頂邊的距離,即視圖座標。

getRawX():獲取點擊事件距離整個屏幕左邊的距離,即絕對座標。

getRawY():獲取點擊事件距離整個屏幕頂邊的距離,即絕對座標。

 

 

TouchSlop

        根據方法註釋理解這個touchSlop是一個滑動距離值的常量,也就是說當咱們手觸摸在屏幕上滑動時,若是滑動距離沒有超過touchSlop值的話 ,android系統自己是不會認爲咱們在屏幕上作了手勢滑動,所以只有當咱們在屏幕上的滑動距離超過touchSlop值時,android系統自己纔會認爲咱們作了滑動操做並去響應觸摸事件,不過要注意的是不一樣的設備,touchSlop的值多是不一樣的,一切以上述的函數獲取爲準

 

VelocityTracker

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

        手勢監聽類,用於輔助檢測用戶的單擊、滑動、長按、雙擊等行爲

      使用:先建立一個GestureDetector對象並實現OnGestureListener接口,根據須要還能夠實現OnDoubleTapListener從而可以監聽雙擊行爲:

GestureDetector gestureDetector = new GestureDetector(this);
//解決長按屏幕後沒法拖動的現象
gestureDetector.setIsLongpressEnabled(false);

        接着,接管目標View的onTouchEvent方法,在須要等待監聽的View中的onTouchEvent方法中添加以下實現:

boolean consume = gestureDetector.onTouchEvent(event);
return consume;

 

OnGestureListener中的接口:

// 用戶輕觸觸摸屏,由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();
}

 

GestureDetector.OnDoubleTapListener中的接口:

// 單擊時發出通知。
@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

 

Scroller

        彈性滑動對象,用來實現View的彈性滑動,Scroller自己沒法讓view彈性滑動,它須要和view的computeScroll方法配合使用才能共同完成這個功能。

 

 

 

 

View的滑動

實現view滑動的三種方式:

  1. 經過view自己提供的scrollTo/scrollBy方式來實現
  2. 經過動畫給view施加平移效果來實現
  3. 經過改變view的LayoutParams使用view從新佈局從而實現滑動

 

使用ScrollTo/ScrollBy

        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);

 

三種滑動方式的對比:

  • scrollTo/scrollBy:操做簡單,適合對View內容的滑動;
  • 動畫:錯作簡單,主要適用於沒有交互的View和實現複雜的動畫效果;
  • 改變佈局參數:操做稍微複雜,適用於有交互的View
相關文章
相關標籤/搜索