<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                *哈哈,第一次使用markdown,看著挺高大上的啊。如果順手了,會直接切換默認為markdown。* 話說關于android事件分發的博客真的不在少數,基本都是基于源碼分析+實例代碼的形式講解。今天的這篇博客呢,主要的側重點并不是在事件分發上,而是在事件的轉換上。 為什么需要事件轉換? 打個比方吧: > 我們點擊一個TextView的左上角,加入這個TextView在它老子的中間位置,那我們點擊的x/y應該是多少呢? 在它老子那這兩個值可能是100/100,而在TextView上打印就會是1/1了,也就是說在事件分發給兒子之前會有一次事件的剪裁過程,這個過程稍后我們也會在源碼中找到。 大家都知道事件的分發都是從 `dispatchTouchEvent()` 方法開始的,但是我們一般很少去重寫 `dispatchTouchEvent` 方法,原因就是盡量避免破壞android原生的事件分發機制。但是今天我們就來試這重寫一下 `dispatchTouchEvent` 方法,從最簡單的代碼探究事件的剪裁。(做好心理準備, 就兩行代碼)。 ~~~ public class MyViewGroup extends LinearLayout { private View mFirstView; public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onFinishInflate() { super.onFinishInflate(); mFirstView = getChildAt(0); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean handled = false; float x = ev.getX(); float y = ev.getY(); System.out.println("老子:x = " + x + ", y = " + y); if(x < mFirstView.getLeft() || x > mFirstView.getRight()) return true; if(y < mFirstView.getTop() || y > mFirstView.getBottom()) return true; int offetX = getScrollX() - mFirstView.getLeft(); int offetY = getScrollY() - mFirstView.getTop(); ev.offsetLocation(offetX, offetY); handled = mFirstView.dispatchTouchEvent(ev); ev.offsetLocation(-offetX, -offetY); return handled; } } ~~~ 代碼很簡單,我們只需要關注`dispatchTouchEvent` 方法就ok, 可以看到 在`dispatchTouchEvent` 方法中,我們并沒有任何 `super.dispatchTouchEvent` 的調用地方,也就是說,我們完全重寫了android默認的事件分發機制。 現在我們來分析一下這段的代碼。 前面的略過,21行代碼打印了我們觸摸的坐標。 23~24行,我們先不去管它。先去看下面的代碼。 26~28行代碼: ~~~ int offetX = getScrollX() - mFirstView.getLeft(); int offetY = getScrollY() - mFirstView.getTop(); ev.offsetLocation(offetX, offetY); ~~~ 首先我們計算了offsetX和offsetY值,這兩個值為什么要這么計算得出呢,我是怎么知道要這么計算的呢? 這里的答案是:看的android源碼的事件剪裁~~~ 我是直接copy出android的源碼來放這的,然后咱們再去理解他,要去理解它,我們還需要一張生動形象高端大氣的圖才ok。 ![高端圖](https://box.kancloud.cn/2016-02-18_56c55b3fb5084.jpg "") 來看圖, scrollX代表這綠色部分在屏幕外面的部分,假如這里是50, left是藍色部分距離他老子(綠色部分)左邊的值,即`getLeft`這里是100, 當我們觸摸屏幕的時候,坐標是從屏幕的左上角開始計算,從這張圖來看,我們觸摸的位置在綠色部分其實是50(100 - 10)的位置. ok,在來看看`offsetX` 如果還是拿這張圖來說的話, `offsetX = 50 - 100 = -50` 。offsetY的值也相同。 說到這里,我們大概明白`MotionEvent.offsetLocation` 的作用了,它的作用就是根據你的兩個參數去偏移坐標。這里,我們的x偏移了-50,計算一下,如果將這個剪裁后的事件分發給子view,那對于子view而言,點擊的位置就是0了。哈哈,終于走通了。 那接下來,我們就通過log來驗證咱們的猜想吧。 ![](https://box.kancloud.cn/2016-02-18_56c55b3fcbd86.jpg "") ![](https://box.kancloud.cn/2016-02-18_56c55b4072862.jpg "") 看log驗證了我們的猜想,事件的坐標的確是經過了剪裁。 而,我們代碼中那兩個判斷: ~~~ if(x < mFirstView.getLeft() || x > mFirstView.getRight()) return true; if(y < mFirstView.getTop() || y > mFirstView.getBottom()) return true; ~~~ 主要作用就是防止該事件沒有發生到該view身上,而強制分發出去了。 最后,我們再去看看源碼中是怎么操作的,是不是和我們的邏輯一樣。 ~~~ private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel, View child, int desiredPointerIdBits) { final boolean handled; ... ... ... // If the number of pointers is the same and we don't need to perform any fancy // irreversible transformations, then we can reuse the motion event for this // dispatch as long as we are careful to revert any changes we make. // Otherwise we need to make a copy. final MotionEvent transformedEvent; if (newPointerIdBits == oldPointerIdBits) { if (child == null || child.hasIdentityMatrix()) { if (child == null) { handled = super.dispatchTouchEvent(event); } else { final float offsetX = mScrollX - child.mLeft; final float offsetY = mScrollY - child.mTop; event.offsetLocation(offsetX, offsetY); handled = child.dispatchTouchEvent(event); event.offsetLocation(-offsetX, -offsetY); } return handled; } transformedEvent = MotionEvent.obtain(event); } else { transformedEvent = event.split(newPointerIdBits); } // Perform any necessary transformations and dispatch. if (child == null) { handled = super.dispatchTouchEvent(transformedEvent); } else { final float offsetX = mScrollX - child.mLeft; final float offsetY = mScrollY - child.mTop; transformedEvent.offsetLocation(offsetX, offsetY); if (! child.hasIdentityMatrix()) { transformedEvent.transform(child.getInverseMatrix()); } handled = child.dispatchTouchEvent(transformedEvent); } // Done. transformedEvent.recycle(); return handled; } ~~~ 看18~22行,代碼和我們的一樣!!!(其實是我們抄的源碼,哈哈)。完結。 哦,對了,本篇博客并沒有什么實質性的意義,就是去探究一下android事件在分發過程的剪裁,樹立一個思想: > 對于view而言,事件發生到我身上,我就把它看作我自己的,你點我拿,我就給你報哪。 在實際代碼中,我們還是盡可能的避免重寫`dispatchTouchEvent`方法,畢竟這里是android默認的事件分發機制。 真正完畢了,吃飯去鳥~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看