View的概念
View是Android中非常重要的敏沉,它算是Android學(xué)習(xí)體系中比較難啃的一塊骨頭了娜氏,但是用戶與一個app的交互就是與View的交互顽聂,也就是說用戶無時無刻不在與app中的View打交道烙丛,所以把View的知識掌握透徹是一個Android開發(fā)者必要任務(wù)憎账。View所有不在趴捅,基本上一個app里面我們能看見的都是View垫毙,圖片-ImageView、文字-TextView拱绑、列表-ListView/GridView/RecyclerView综芥、按鈕-Button、選擇框-CheckBox猎拨、輸入框-EditText……當(dāng)然還有更重要的一種是自定義View膀藐。除了View,還有ViewGroup红省,比如LinearLayout额各、RelativeLayout、FrameLayout吧恃,它們是可以包含多個ViewGroup或者View的控件虾啦,ViewGroup也繼承了View,也就是說View可以是單個控件,也可以是由多個控件組成的一組控件傲醉。
View的位置參數(shù)
View的位置由它的四個頂點決定针饥,即View的四個屬性:top、left需频、right丁眼、bottom,top表示左上角縱坐標(biāo)昭殉,left表示左上角橫坐標(biāo)苞七,right表示右下角橫坐標(biāo),bottom表示右下角縱坐標(biāo)挪丢。
這些坐標(biāo)都是相對于View的父容器來說的蹂风,所以它是一種相對坐標(biāo)。
View的這四個參數(shù)在源碼中對應(yīng)著mLeft乾蓬、mRight惠啄、mTop和mBottom,獲取的方式直接get任内,比如mLeft=getLeft()撵渡。從Android3.0開始View增加了額外幾個參數(shù),x死嗦、y趋距、translationX、translationY越除,其中x和y是View左上角的坐標(biāo)节腐,而translationX和translationY是View左上角相對于父容器的偏移量,這幾個參數(shù)也是相對于父容器的坐標(biāo)摘盆,且translationX和translationY的初始值是0翼雀,它們也有對應(yīng)的getter/setter方法,這幾個參數(shù)的換算關(guān)系:
x = left + translationX;
y = top + translationY;
View在平移的過程中孩擂,left和top表示的是原始左上角的位置信息狼渊,值不會發(fā)生改變,此時發(fā)生改變的是x肋殴、y囤锉、translationX和translationY。
觸摸事件MotionEvent
在手指接觸屏幕后所產(chǎn)生的一系列事件中护锤,典型的事件類型有以下幾種:
- ACTION_DOWN 手指剛接觸屏幕時觸發(fā)該事件
- ACTION_MOVE 手指在屏幕上移動時觸發(fā)該事件
- ACTION_UP 手指從屏幕抬起時觸發(fā)該事件
當(dāng)手指點擊屏幕滑動一會然后再抬起這一系列動作,屏幕觸發(fā)的事件依次是ACTION_DOWN酿傍、ACTION_MOVE……烙懦、ACTION_UP,只有ACTION_MOVE這個方法會觸發(fā)多次赤炒,其他只會觸發(fā)一次氯析。通過MotionEvent對象我們可以獲取到點擊事件的x和y坐標(biāo)亏较,系統(tǒng)提供了兩組方法:getX/getY和getRaw/getRawY,它們的區(qū)別是:getX/getY返回的是相對于當(dāng)前View左上角的x和y掩缓,而getRaw/getRawY返回的是相對于手機(jī)屏幕左上角的x和y雪情。
TouchSlop
TouchSlop是系統(tǒng)所能識別出的被認(rèn)為是滑動的最小距離,默認(rèn)是8dp你辣,當(dāng)手指在屏幕上滑動時巡通,如果兩次觸發(fā)ACTION_MOVE事件的距離小于TouchSlop這個常量,那么系統(tǒng)就不會認(rèn)為是在進(jìn)行滑動操作舍哄。這個常量和設(shè)備有關(guān)宴凉,獲取該常量的方式如下:
ViewConfiguration.get(getBaseContext()).getScaledTouchSlop();
該常量的意義
當(dāng)我們在處理滑動時,可以利用這個常量來做一些過濾表悬,比如當(dāng)兩次滑動事件的滑動距離小于這個值時我們就可以認(rèn)為未達(dá)到滑動距離的臨界值弥锄,因此可以不認(rèn)為是滑動動作,這樣會有更好的用戶體驗蟆沫。
VelocityTracker
VelocityTracker表示速度追蹤籽暇,用于追蹤手指在滑動過程中的速度,包括水平和垂直方向的速度饭庞,它的使用如下:
在View的onTouchEvent方法中追蹤當(dāng)前單擊事件的速度:
VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);
int xVelocity = (int) velocityTracker.getXVelocity();
int yVelocity = (int) velocityTracker.getYVelocity();
獲取水平方向和豎直方向的速度時图仓,首先要計算速度,即computeCurrentVelocity這個方法必須先調(diào)用但绕,才能接著調(diào)getXVelocity/getYVelocity救崔。computeCurrentVelocity方法的參數(shù)表示的是一個時間單元,單位是ms捏顺。另外這里所說的速度指的是一段時間內(nèi)手指滑過的像素數(shù)六孵,比如講時間設(shè)為1000ms時,表示在1s內(nèi)幅骄,手指在水平方向滑動100像素劫窒,那么水平速度就是100。
速度可以是負(fù)數(shù)拆座,當(dāng)手指從下往上滑動或從右往左滑動時速度就為負(fù)值主巍。
速度 = (終點位置 - 起點位置)/ 時間段
當(dāng)我們最后不需要再使用VelocityTracker時,要記得調(diào)用clear方法來重置并回收內(nèi)存
velocityTracker.clear();
velocityTracker.recycle();
GestureDetector
GestureDetector表示手勢檢測,用于輔助檢測用戶的單擊江场、滑動嘁捷、長按、雙擊等動作搞旭。使用方法如下:
首先創(chuàng)建一個GestureDetector對象并實現(xiàn)GestureDetector.OnGestureListener接口,根據(jù)需要我們還可以實現(xiàn)OnDoubleTapListener接口從而能夠監(jiān)聽雙擊動作。
GestureDetector mGestureDetector = new GestureDetector(getBaseContext(), this);
mGestureDetector.setIsLongpressEnabled(false);
接著接管目標(biāo)View的onTouchEvent方法肄渗,在待監(jiān)聽View的onTouchEvent方法中添加如下代碼:
boolean consume = mGestureDetector.onTouchEvent(event);
return consume;
然后我們就可以有選擇的實現(xiàn)OnGestureListener和OnDoubleTapListener方法中的方法了镇眷。
下面是OnGestureListener接口中的方法:
@Override
public boolean onDown(MotionEvent e) {
// 手指輕輕觸摸屏幕的一瞬間,由一個ACTION_DOWN觸發(fā)
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// 手指輕輕觸摸屏幕翎嫡,尚未松開或拖動欠动,由一個ACTION_DOWN觸發(fā),和onDown的區(qū)別是手指沒有松開或拖動
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// 手指輕輕觸摸屏幕后松開惑申,伴隨著一個ACTION_UP觸發(fā)具伍,這是單擊行為
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// 手指按下屏幕并拖動,有一個ACTION_DOWN和多個ACTION_MOVE觸發(fā)硝桩,這是拖動行為
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// 長按事件
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// 快速滑動行為沿猜,由一個ACTION_DOWN、多個ACTION_MOVE和一個ACTION_UP觸發(fā)
return false;
}
下面是OnDoubleTapListener接口中的方法:
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// 嚴(yán)格的單擊行為碗脊,如果觸發(fā)了這個方法啼肩,那么不可能再緊跟著另一個單擊行為,即這只可能是單擊衙伶,而不可能是雙擊中的一次單擊
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
// 雙擊祈坠,由兩次連續(xù)的單擊組成,該方法不可能和onSingleTapConfirmed同時觸發(fā)
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// 表示發(fā)生了雙擊行為矢劲,在雙擊的期間赦拘,ACTION_DOWN、ACTION_MOVE芬沉、ACTION_UP都會觸發(fā)這個方法
return false;
}
實際開發(fā)中躺同,可以不使用GestureDetector,可以自己在View的onTouchEvent方法中實現(xiàn)所需要的監(jiān)聽丸逸,如果是監(jiān)聽滑動相關(guān)的蹋艺,還是自己在onTouchEvent方法中實現(xiàn)比較好,如果是單純的監(jiān)聽某個行為(雙擊黄刚、長按……)捎谨,就使用GestureDetector。
Scroller
彈性滑動對象憔维,用于實現(xiàn)View的彈性滑動涛救,當(dāng)使用View的scrollTo/scrollBy方法來進(jìn)行滑動時,其過程是瞬間完成的业扒,這個沒有過渡效果的滑動用戶體驗不好检吆。這個時候就可以使用Scroller來實現(xiàn)有過渡效果的滑動,其過程不是在一瞬間完成凶赁,而是在一定的時間內(nèi)完成咧栗。Scroller本身無法讓View彈性滑動逆甜,它需要和View的computeScroll
方法配合使用才能共同完成這個功能虱肄。關(guān)鍵代碼如下:
mScroller = new Scroller(context);
private void smoothScrollTo(int destX, int destY) {
int scrollX = getScrollX();
int delta = destX - scrollX;
mScroller.startScroll(scrollX, 0, delta, 0, 1000);
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
以上就是Android系統(tǒng)中關(guān)于View的幾個重要的基礎(chǔ)知識點致板,不過這也僅僅是View中最基礎(chǔ)的東西,接下來View的滑動咏窿、事件分發(fā)等才是更需要深入理解的知識斟或。