View的事件體系

1,x,y代表的View相對于屏幕左上角的坐標,translationX和translationY是View左上角相對于父控件的偏移量,因此

? ? x = getLeft()+translationX

? ? y = getTop()+translationY

View在平移的過程中,getLeft()和getTop()的值并不會發生變化,變化的是translationX,x,translationY,y的值。

2,getX和getY返回的是View相對于父控件的x和y坐標,getRawX和getRawY返回的是View相對于屏幕左上角的坐標。

3,通過ViewConfiguration.get(getCpntext()).getScaledTouchSlop()來獲取系統能識別出被認為是滑動的最小距離。

4,實現View滑動的三種方式

? ? a,使用scrollTo/scrollBy ?//只能改變View內容位置不能改變View本身位置

? ? scrollBy內部也是通過scrollTo實現的,是一種相對滑動, scrollTo是絕對滑動。

? ? getScrollX的值等于View左邊緣和View內容左邊緣在水平方向上的距離,getScrollY的值等于View上邊緣和View內容上邊緣在豎直方向上的距離。

? ? scrollBy和scrollTo只能改變View內容的位置而不能改變View的位置。

? ? 當View的左邊緣在View內容的左邊緣的右邊時,getScrollX為正值;當View的上邊緣在View內容的上邊緣的下邊時,getScrollY為正值。

? ? b,使用動畫 ? // 適用于實現復雜,但是沒有交互的View

? ? c,改變布局參數 ?// 適用于有交互的View

MarginLayoutParams params = (MarginLayoutParams)mButton.getLayoutParams();

params.width += 100;

params.leftMargin +=? 100;

mButton.requestLayout()

5,彈性滑動的三種方式

? ? a,使用Scroller

? ? 僅僅使用startScroll()是無法讓View滑動的,需要緊接著調用invalidate方法,invalidate方法會調用computeScroll方法,這個方法需要我們自己來重寫,標準寫法如下:

public void computeScroll(){

? ? if(mScroller.computeScrollOffset()){

? ? ? ? ? scrollTo(mScroller.getCurrentX(),mScroller.getCurrentY());

? ? ? ? ? postInvalidate();

? ? }

}

computeScroll內部會去獲取mScroller當前的scrollX和scollY,然后通過scrollTo來實現滑動,緊接著調用postInvalidate()方法,又會再次調用computeScroll方法,如此反復,直到滑動結束。

需要注意:CurrentX和CurrentY的計算過程是在computeScrollOffset方法中進行的

? ? b,通過動畫

ObjectAnimator.ofFloat(targetView,"translationX",0,100).setDuration(100).start();

? ? c,使用延時策略

6,View事件分發機制

? 如果一個View設置了onTouchListener,那么onTouchListener的onTouch方法便會被調用,如果onTouch返回false,則調用onTouchEvent方法,如果onTouch返回true,則onTouchEvent方法不會被調用。可見onTouch的優先級高于onTouchEvent。

? 事件傳遞順序:Activity-Window-View

? 總結:

(1)同一個事件序列是指手機接觸屏幕那一刻起,到手指離開屏幕的那一刻結束,在這個過程中所產生的一系列事件,這個事件序列以down開始,中間含有數不清的move事件,最終以up事件結束。

(2)正常情況下,一個事件序列只能被一個View攔截且消耗,因為一旦有一個元素攔截了某次事件,那么同一個事件序列的所有事件都會直接交給他處理,因此同一個事件序列中的事件不能分別由兩個View同時處理,但是可以通過特殊手段做到,比如一個View將本該自己處理的事件通過onTouchEvent強行傳遞給其他View。

(3)onInterruptTouchEvent只會調用一次。

這個可以通過查看ViewGroup的dispatchTouchEvent方法的源代碼

final boolean intercepted;

if(actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchEvent != null){

? ? final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPET) !=0;

? ? if(!disallowIntercept){

? ? ? ? ?intercepted = onInterceptTouchEvent(ev);

? ? ? ? ?ev.setAction(action);

? ? }else{

? ? ? ? intercepted = false;

? ? }

else

? ? intercepted = true;

}

? ? mFirstTouchEvent只有在ViewGroup將事件傳遞給子元素之后才不為空,也就是說,如果ViewGroup在Down事件選擇攔截,mFirstTouchEvent就一定為空,在之后的MOVE和UP事件,actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchEvent != null這個條件一定為false,不會再次調用onInterceptTouchEvent方法,所以如果我們想在ViewGroup提前處理所有的點擊事件,不能在onInterceptTouchEvent方法中進行,可以選擇dispatchTouchEvent方法。

? ? FLAG_DISALLOW_INTERCEPET這個標記可以用來禁止ViewGroup攔截除ACTION_DOWN以外的事件,為什么無法禁止ACTION_DOWN事件?因為處理ACTION_DOWN事件的時候,ViewGroup會重置FLAG_DISALLOW_INTERCEPET這個標記,導致子元素設置的FLAG_DISALLOW_INTERCEPET標記不生效。

(4)如果一個View不消耗Down事件,那么同一個事件序列的其他事件都不會再交給它處理,而是調用父View的onTouchEvent.

(5)如果一個View不消耗除Down事件以外的事件,那么這個事件會消失,并最終將這些消失的點擊事件傳遞給Activity處理。

(6)ViewGroup默認不攔截任何事件。

(7)View沒有onInterceptTouchEvent方法,一旦有點擊事件傳遞給它,那么他的onTouchEvent方法就會被調用。

(8)View的onTouchEvent方法默認都返回為true,除非他是不可點擊的,根據clickable屬性來判斷

(9)View的enable屬性并不影響onTouchEvent的默認返回值

(10)onClick發生的前提條件是View是可點擊的,并且收到了down和up事件

(11)事件傳遞的過程是由外向內的,通過requestDisallowInterceptTouchEvent方法可以在子元素中干預父元素的事件分發過程,但是ACTION_DOWN事件除外

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容