Android View

View基礎知識

View的位置參數:

top、left、right、bottom,分別對應View的左上角和右下角相對於父容器的橫縱座標值。從Android 3.0開始,view增加了x、y、translationX、translationY四個參數,這幾個參數也是相對於父容器的座標。x和y是左上角的座標,而translationX和translationY是view左上角相對於父容器的偏移量,默認值都是0。

這裏寫圖片描述
這幾個參數的換算公式:
x=left+translationX
y=top+translation

View在平移過程中,top和left表示原始左上角的位置信息,其值並不會發生改變

MotionEvent和TouchSlop

MotionEvent是指手指接觸屏幕後所產生的一系列事件,主要有ACTION_UP、ACTION_DOWN、ACTION_MOVE等。
正常情況下,一次手指觸屏會觸發一系列點擊事件,主要有下面兩種典型情況:

  • 點擊屏幕後離開,事件序列是ACTION_DOWN->ACTION_UP;
  • 點擊屏幕後滑動一會再離開,事件序列是ACTION_DOWN->ACTION_MOVE->ACTION_MOVE-> … ->ACTION_UP;

TouchSlope是系統所能識別出的可以被認爲是滑動的最小距離,獲取方式是

ViewConfiguration.get(getContext()).getScaledTouchSlope()。

VelocityTracker

VelocityTracker用於追蹤手指在滑動過程中的速度,包括水平和垂直方向上的速度。速度可能爲負值,例如當手指從屏幕右邊往左邊滑動的時候。此外,速度是單位時間內移動的像素數,單位時間不一定是1秒鐘,可以使用方法computeCurrentVelocity(xxx)指定單位時間是多少,單位是ms。例如通過computeCurrentVelocity(1000)來獲取速度,手指在1s中滑動了100個像素,那麼速度是100,即100(像素/1000ms)。如果computeCurrentVelocity(100)來獲取速度,在100ms內手指只是滑動了10個像素,那麼速度是10,即10(像素/100ms)。

使用步驟:
1.獲取VelocityTracker實例:

VelocityTracker mVelocityTracker = VelocityTracker.obtain();

2.將MotionEvent事件納入到VelocityTracker中:

mVelocityTracker.addMovement(event);

3.計算瞬時速度:

mVelocityTracker.computeCurrentVelocity(units,maxVelocity);

4.獲取xy方向上的速度:

float vX = mVelocityTracker.getXVelocity(pointId);
float vY = mVelocityTracker.getYVelocity(pointId);

5.回收VelocityTracker:

mVelocityTracker.clear();
mVelocityTracker.recycle();

6.使用示例:

/**
     * 獲取速度追蹤器
     * @return
     */
    private VelocityTracker getVelocityTracker()
    {
        if(mVelocityTracker == null)
        {
            mVelocityTracker = VelocityTracker.obtain();
        }
        return mVelocityTracker;
    }

    /**
     * 回收速度追蹤器
     */
    private void recycleVelocityTracker()
    {
        if(mVelocityTracker != null)
        {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //1.獲取速度追蹤器
        getVelocityTracker();
        //2.將當前事件納入到追蹤器中
        mVelocityTracker.addMovement(event);

        int pointId = -1;

        switch (event.getAction())
        {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG,"ACTION_DOWN");
            pointId = event.getPointerId(0);
            break;
        case MotionEvent.ACTION_MOVE:
            Log.i(TAG,"ACTION_MOVE");
            //3.計算當前速度
            mVelocityTracker.computeCurrentVelocity(1000,mMaxFlingVelocity);
            //獲取x y方向上的速度
            float vX = mVelocityTracker.getXVelocity(pointId);
            float vY = mVelocityTracker.getYVelocity(pointId);
            Log.i(TAG,"vX = "+vX+",vY = "+vY);
            break;

        case MotionEvent.ACTION_UP:
            Log.i(TAG,"ACTION_UP");
            //4.回收速度追蹤器
            recycleVelocityTracker();
            break;
        default:
            break;
        }
        return super.onTouchEvent(event);
    }

GestureDetector

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

  • 首先需要實現GestureListener接口
mGestureDetector = new GestureDetector(this, new GestureScrollListener());
  • 在TouchEvent方法中接管手勢
 mGestureDetector.onTouchEvent(ev)

View的滑動

常見的實現view的滑動的方式有三種:

  • 1.通過view本身提供的scrollTo和scrollBy方法:操作簡單,適合對view內容的滑動;
  • 2.通過動畫給view施加平移效果來實現滑動:操作簡單,適用於沒有交互的view和實現複雜的動畫效果;
  • 3.通過改變view的LayoutParams使得view重新佈局從而實現滑動:操作稍微複雜,適用於有交互的view

scrollTo和scrollBy

  • scrollTo(int x, int y) 是將View中內容滑動到相應的位置
  • scrollBy(int x, int y)其實是對scrollTo的包裝,移動的是相對的位置

scrollTo和scrollBy源代碼:

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();  
        }  
    }  
} 
public void scrollBy(int x, int y) { 
    scrollTo(mScrollX + x, mScrollY + y);
}  

使用動畫

  • 使用動畫來移動view主要是操作view的translationX和translationY屬性,既可以使用傳統的view動畫,也可以使用屬性動畫。
  • 使用動畫還存在一個交互問題:在android3.0以前的系統上,view動畫和屬性動畫,新位置均無法觸發點擊事件,同時,老位置仍然可以觸發單擊事件。從3.0開始,屬性動畫的單擊事件觸發位置爲移動後的位置,view動畫仍然在原位置。
  • 動畫兼容庫nineoldandroids中的ViewHelper類提供了很多的get/set方法來爲屬性動畫服務,例如setTranslationX和setTranslationY方法,這些方法是沒有版本要求的。
    ViewHelper.getTranslationX(view);
    ViewHelper.setTranslationY(view,100);
    ViewHelper.setTranslationX(view,100);

改變佈局參數

通過params來設置margin改變位置

Scroller

  • Scroller:彈性滑動對象
  • v4中ScrollerCompat類兼容庫
  • 需要computeScroll配合更新位置

執行滑動:

 mScroller.startScroll( startX, startY,dx, dy, duration);

控制滑動這個流程:

@Override
 public void computeScroll() {
        super.computeScroll();
        // 判斷Scroller是否執行完畢
        if (mScroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo( mScroller.getCurrX(), mScroller.getCurrY());
            // 通過重繪來不斷調用computeScroll
            invalidate();//很重要
        }
    }

computeScroll:主要功能是計算拖動的位移量、更新背景、設置要顯示的屏幕(setCurrentScreen(mCurrentScreen);)。

重寫computeScroll()的原因:

調用startScroll()是不會有滾動效果的,只有在computeScroll()獲取滾動情況,做出滾動的響應

computeScroll在父控件執行drawChild時,會調用這個方法

發佈了46 篇原創文章 · 獲贊 23 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章