在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ 安卓系統(tǒng)點(diǎn)擊事件處理
Launch mode 和 Intent flags專(zhuān)題
Canvas & Drawables
UTAustinX_UT.9.01x: Effective Thinking Through Mathematics
《JavaScript 語(yǔ)言精粹》
Memory leak專(zhuān)題
React基礎(chǔ)
《Test Driven Development: By Example》一書(shū)
Developer tools
安卓開(kāi)發(fā)技能樹(shù)
<a rel="nofollow" href="https://mp.weixin.qq.com/s?__biz=MzA3NDM
Best Practices for Interaction and Engagement
各個(gè)安卓版本引入的主要新特性
Building Apps with Connectivity &amp; the Cloud
List.toArray()再?gòu)?qiáng)轉(zhuǎn)是一定會(huì)失敗的
深入Android frameworks
Google dev 100 days系列視頻
Building Apps with Contacts &amp; Sign-In
關(guān)系型數(shù)據(jù)庫(kù)設(shè)計(jì)范式
《App研發(fā)錄》一書(shū)
REST API設(shè)計(jì)
Google IO 2015摘要
自定義View/ViewGroup以及高性能實(shí)現(xiàn)自定義UI
安卓系統(tǒng)點(diǎn)擊事件處理
《50 Android Hacks》一書(shū)
Building Apps with Content Sharing
Flux基礎(chǔ)
<a rel="nofollow" href="http://developer.android.com/training/in
依賴注入(以Dagger 2為例)
Java同步機(jī)制
Java對(duì)象內(nèi)存的使用情況
JSR133(Java memory model)
Google官方Material Design手冊(cè)(<a rel="nofollow" href="http://develop
Futurice公司安卓團(tuán)隊(duì)的建議
安卓性能優(yōu)化
  • 1.
Best Practices for Performance
<a rel="nofollow" href="http://www.vogella.com/tutorials/Android
<a rel="nofollow" href="http://blog.danlew.net/2014/11/19/styles
Handling Runtime Changes
<a rel="nofollow" href="http://www.vogella.com/tutorials/Android
Building Apps with Graphics &amp; Animation
<a rel="nofollow" href="http://tools.android.com/tech-docs/new-b
Android項(xiàng)目架構(gòu)
MVP(Model-View-Presenter)模式
<a rel="nofollow" href="http://www.infoq.com/cn/es6-in-depth/"">
《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》一書(shū)
Rx在Android中的最佳實(shí)踐
函數(shù)調(diào)用時(shí),傳遞參數(shù)應(yīng)該是不可變的(Immutable)
ProGuard
面向?qū)ο罅笤瓌t(SOLID+)
深入理解Java虛擬機(jī)
深入Java深淺拷貝、immutable、unmodifiable
Best Practices for User Input
UI上的一些高效方式/最佳實(shí)踐
<a rel="nofollow" href="https://blog.stylingandroid.com/ripples-
Best Practices for User Interface
安卓測(cè)試驅(qū)動(dòng)開(kāi)發(fā)/安卓測(cè)試驗(yàn)證
暗時(shí)間:學(xué)會(huì)正確思考
技術(shù)筆記
Aspect Oriented Programming(AOP)
Best Practices for Background Jobs
安卓系統(tǒng)動(dòng)效專(zhuān)題
Feed系統(tǒng)的設(shè)計(jì)
Data binding(MVVM,Model-View-ViewModel)
Effective Java一書(shū)筆記
<a rel="nofollow" href="http://developer.android.com/training/in
Rx (Reactive eXtention)
MultiDex專(zhuān)題
一些很棒的點(diǎn)子
WebRTC

安卓系統(tǒng)點(diǎn)擊事件處理

參考PPT

安卓系統(tǒng)點(diǎn)擊事件處理框架

  • 用戶的點(diǎn)擊事件均被包裝為MotionEvent
  • MotionEvent描述了用戶的行為
    • ACTION_DOWN
    • ACTION_UP
    • ACTION_MOVE
    • ACTION_POINTER_DOWN
    • ACTION_POINTER_UP
    • ACTION_CANCEL
    • 使用MotionEventCompat.getActionMasked(ev)獲取MotionEvent對(duì)應(yīng)的action
  • MotionEvent還包括以下信息
    • 點(diǎn)擊的位置(x, y坐標(biāo))
    • 觸點(diǎn)的數(shù)量(手指)
    • 事件發(fā)生的時(shí)間戳
  • 任何一個(gè)手勢(shì),都是以ACTION_DOWN起始,ACTION_UP結(jié)束
  • 事件從Activity的dispatchTouchEvent()函數(shù)開(kāi)始,沿著View層次樹(shù)依次向下傳遞
    • 父元素把事件dispatch到子元素
    • 事件能在任意階段被intercept
  • 事件會(huì)沿著View層次樹(shù)依次向下傳遞,然后又反向向上傳遞,直到被“消費(fèi)”
    • View如果對(duì)手勢(shì)感興趣,就必須消費(fèi)掉ACTION_DOWN的事件
    • 出于性能的考慮,同一手勢(shì)的后續(xù)事件將不會(huì)按照完整路徑進(jìn)行傳遞,而是直接傳遞到消費(fèi)了ACTION_DOWN事件的View
    • 如果所有的View(ViewGroup)都沒(méi)有消費(fèi)掉事件,那它將傳遞到Activity的onTouchEvent()函數(shù)中,并結(jié)束傳遞過(guò)程,即如果沒(méi)有被消費(fèi),也不會(huì)再繼續(xù)傳遞了
  • 可選的OnTouchListener能在任一View(ViewGroup)上intercept事件,事件被intercept之后,后面的調(diào)用將被傳入ACTION_CANCEL?啥意思??
  • Activity.dispatchTouchEvent()
    • 總是首先被調(diào)用
    • Sends event to root view attached to Window
    • 如果所有的View(ViewGroup)都沒(méi)有消費(fèi)該事件,那么Activity.onTouchEvent()將被調(diào)用,而且這個(gè)函數(shù)是最后一個(gè)被調(diào)用的函數(shù)
  • ViewGroup.dispatchTouchEvent()
    • 首先調(diào)用onInterceptTouchEvent()函數(shù),判斷是否需要攔截
      • 檢查是否應(yīng)該替代子view的處理
      • Passes ACTION_CANCEL to active child
      • 如果要消費(fèi)掉同一手勢(shì)的所有后續(xù)事件,需要返回true
    • 對(duì)所有的孩子,以添加順序的逆序進(jìn)行遍歷
      • 如果點(diǎn)擊在孩子的邊界內(nèi),則調(diào)用child.dispatchTouchEvent()
      • 如果沒(méi)有被當(dāng)前的孩子消費(fèi),則傳遞到下一個(gè)孩子
    • 如果所有的孩子都未消費(fèi)該事件,則傳遞給listener,OnTouchListener.onTouch()
    • 如果沒(méi)有l(wèi)istener,或者listener也未消費(fèi),則自己處理,調(diào)用ViewGroup.onTouchEvent()
    • Intercepted events jump over child step
  • View.dispatchTouchEvent()
    • 如果被設(shè)置了OnTouchListener,那么將先把事件發(fā)送到listener,調(diào)用View.OnTouchListener.onTouch()
    • 如果listener沒(méi)有消費(fèi)事件,將調(diào)用View.onTouchEvent(),即自己處理點(diǎn)擊事件
  • 例子
    • View對(duì)事件不感興趣
      http://wiki.jikexueyuan.com/project/notes/images/ignorant_view_example.png" alt="ignorant_view_example.png" />
    • View對(duì)事件感興趣
      http://wiki.jikexueyuan.com/project/notes/images/interested_view_example.png" alt="interested_view_example.png" />
    • 事件被ViewGroup intercept
      http://wiki.jikexueyuan.com/project/notes/images/intercept_example.png" alt="intercept_example.png" />
  • 小結(jié)
    • 手勢(shì)以ACTION_DOWN起始,以ACTION_UP結(jié)束
    • ACTION_DOWN,在每一層View上都會(huì)調(diào)用dispatchTouchEvent(),該View會(huì)判斷是否對(duì)接下來(lái)的手勢(shì)感興趣,后續(xù)的點(diǎn)擊事件將直接傳遞到感興趣的View
    • ViewGroup可以intercept一個(gè)手勢(shì),因?yàn)?code>onInterceptTouchEvent()是在dispatchTouchEvent()函數(shù)中最先被調(diào)用的,如果onInterceptTouchEvent()返回true,它的孩子將不會(huì)收到該手勢(shì)的后續(xù)事件

自定義點(diǎn)擊事件處理

  • 途徑
    • (View/ViewGroup子類(lèi),Target)重載onTouchEvent()函數(shù)
    • 為T(mén)arget設(shè)置OnTouchListener
  • 消費(fèi)事件(onTouchEvent()
    • ACTION_DOWN:如果對(duì)手勢(shì)感興趣,那么ACTION_DOWN的event就要返回true,即便對(duì)于ACTION_DOWN不感興趣
    • 后續(xù)的事件,同樣返回true,結(jié)束事件的處理流程(不會(huì)再傳遞給其他view或者parent view)
  • ViewConfiguration的一些有用方法
    • getScaledTouchSlop():判斷一個(gè)移動(dòng)距離是否為drag
    • getScaledMinimumFlingVelocity():判斷一個(gè)拖拽速度是否為fling
    • getLongPressTimeout():判斷一個(gè)touch時(shí)間段是否為long press
  • 傳遞點(diǎn)擊事件:調(diào)用target的dispatchTouchEvent(),不要直接調(diào)用target的onTouchEvent()
  • ViewGroup攔截點(diǎn)擊事件
    • 重載onInterceptTouchEvent()
    • 如果對(duì)當(dāng)前的手勢(shì)感興趣,onInterceptTouchEvent()返回true,之后的點(diǎn)擊事件將不再經(jīng)過(guò)onInterceptTouchEvent()函數(shù)
    • 其他的target(之前消費(fèi)事件的View/ViewGroup)將收到ACTION_CANCEL
  • 一些建議/警告
    • 盡量調(diào)用super的對(duì)應(yīng)方法,父類(lèi)中已經(jīng)做了很多基礎(chǔ)工作了
    • ACTION_MOVE的處理中,檢查移動(dòng)距離是否超過(guò)slop(getScaledTouchSlop()
    • 處理ACTION_CANCEL事件,父View可能會(huì)攔截事件,ACTION_CANCEL后需要重置狀態(tài),且之后該手勢(shì)將不會(huì)再收到任何事件
    • intercept之后,該手勢(shì)之后的所有事件都將被攔截,所以不要輕易攔截
  • 多觸點(diǎn)事件響應(yīng)
    • MotionEvent.getPointerCount():獲取當(dāng)前屏幕上的觸點(diǎn)數(shù)量
    • ACTION_POINTER_DOWN,ACTION_POINTER_UP用來(lái)響應(yīng)次觸點(diǎn)的事件,MotionEvent.getActionMasked(),MotionEvent.getActionIndex()
    • MotionEvent的有些方法會(huì)有兩個(gè)版本,帶index參數(shù)的,用于獲取第index個(gè)觸點(diǎn)的數(shù)據(jù);不帶參數(shù)的,獲取主觸點(diǎn)(第一個(gè)觸點(diǎn))的數(shù)據(jù)
  • 批量處理
    • 出于效率的考慮,ACTION_MOVE可以被打包到一個(gè)MotionEvent進(jìn)行處理
    • 最近一次(本次)事件的信息,通過(guò)標(biāo)準(zhǔn)的方法獲取:getX(), getY(), getEventTime()
    • 本次和最早一次ACTION_MOVE的信息,通過(guò)相應(yīng)historical的方法獲取
      • getHistorySize()獲取打包的數(shù)量
      • getHistorical*(pos)獲取第一個(gè)觸點(diǎn)的第pos個(gè)歷史事件的信息
      • getHistorical*(index, pos)獲取第index個(gè)觸點(diǎn)的第pos個(gè)歷史事件的信息
    • Can reconstruct all events as they occurred in time for maximum precision
  • System Touch Handlers
    • 不要首先就考慮使用自定義的事件處理方式
    • OnClickListener
    • OnLongClickListener
    • OnTouchListener
      • 監(jiān)聽(tīng)每一個(gè)MotionEvent,而不需要編寫(xiě)子類(lèi)
      • 可以在Listener中消費(fèi)事件
      • View的onTouchEvent處理中,優(yōu)先調(diào)用的是listener的處理函數(shù)
    • OnScrollListener / View.onScrollChanged()
    • GestureDetector
      • onDown(), onSingleTapUp(), onDoubleTap()
      • onLongPress()
      • onScroll() (緩慢滾動(dòng))
      • onFling() (快速滾動(dòng)后釋放手指)
    • ScaleGestureDetector
      • onScaleBegin(), onScale(), onScaleEnd()
    • 一個(gè)擴(kuò)展的gesture detector庫(kù):android-gesture-detectors
    • 通過(guò)OnTouchListener或者onTouchEvent()進(jìn)行處理
    • 缺點(diǎn)
      • Consume UP events and exposes no interface for CANCEL events
      • May require added touch handling if these cases need special handling (e.g. reset a View's appearance)
  • Touch Delegate

    • Specialized object to assist in forwarding touches from a parent view to its child
    • Allows for the touch area of a specific view to be different than its actual bounds
    • Called in onTouchEvent() of attached View(Events have to make it that far without being consumed by a child or listener)
    • TouchDelegate is designed to be set on the PARENT and passed the CHILD view that touches should be forwarded to
    ViewGroup parent;
    View child;
    Rect touchArea;
    parent.setTouchDelegate(new TouchDelegate(touchArea, child));

ViewDragHelper

快速處理view拖拽的輔助類(lèi)。參考blog。

  • 創(chuàng)建ViewDragHelper:
mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());
  • 把ViewGroup的點(diǎn)擊事件傳遞給ViewDragHelper:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (mDragHelper.shouldInterceptTouchEvent(event)) {
            return true;
    }
    return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mDragHelper.processTouchEvent(event);
    return true;
}
  • ViewDragHelper.Callback的實(shí)現(xiàn)類(lèi)DragHelperCallback中,重載感興趣的函數(shù),實(shí)現(xiàn)自己的邏輯

  • 有一個(gè)用于邊緣拖拽結(jié)束activity的庫(kù),邊緣拖拽使用的就是ViewDragHelper:Slidr