<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      公子姓王

      導航

      為什么屬性動畫可以響應觸摸事件

      關于Android 的動畫及原理,可以參考:

      逐幀動畫(AnimationDrawable)

      View動畫,插值器(Animation)

      屬性動畫淺談(Animator)

      Android中的動畫和原理(幀動畫和補間動畫)

      屬性動畫源碼分析

      補間動畫和屬性動畫內存泄露分析

      屬性動畫與 VIew動畫的關鍵區別之一,就是 屬性動畫 view 可以在動畫過程中收到點擊事件,而 view 動畫過程中,點擊事件仍在原地;基于此,很多人認為屬性動畫改變了 view 的屬性,導致view 的位置發生了變化,所以屬性動畫可以收到點擊事件,這種說法其實是錯誤的;

      為什么如此說呢,我們這里給一個例子:

      ObjectAnimator.ofFloat(v, "translationX", 0, 1000f)
      		.setDuration(1000)
      		.start();
      

      在開發者選項中,我們打開顯示布局位置:

      運行如下:

      發現上面顯示的 view 的位置并沒有發生改變;

      那么上面動畫到底做了什么呢,我們都知道,上面動畫會調用 View 的 setTranslationX 方法,我們來看源碼:

          public void setTranslationX(float translationX) {
              if (translationX != getTranslationX()) {
                  invalidateViewProperty(true, false);
                  // Sets the translation value for the display list on the X axis.
                  // 在display list 上設置了 translationX
                  mRenderNode.setTranslationX(translationX);
                // 這里的invalidateViewProperty會調用invalidate方法,也就是會導致 view 重繪,但是,并不會導致 view 的位置發生改變(沒有 onLayout 調用)
                  invalidateViewProperty(false, true);
                  invalidateParentIfNeededAndWasQuickRejected();
                  notifySubtreeAccessibilityStateChangedIfNeeded();
              }
          }
      

      上面可以看出,并沒有改變 view 位置,而是在display list 上設置了 translationX

      關于 display list,這個就有些復雜了,暫不分析

      那么還有一個問題需要 解決,就是為什么能收到點擊事件,這就需要看父布局(ViewGroup)如何判斷一個觸控坐標是否在子 view 范圍內了,在 ViewGroup 的 dispatchTouchEvent 事件中,有如下源碼 :

      if (!canViewReceivePointerEvents(child)// 判斷是否可見,是否有動畫(View 動畫,即 Animation)正在播放
          || !isTransformedTouchPointInView(x, y, child, null)// 判斷坐標是否在 child 內
         ) {
      		continue;
      }
      
      protected boolean isTransformedTouchPointInView(float x, float y, View child,
                                                      PointF outLocalPoint) {
        final float[] point = getTempPoint();
        point[0] = x;
        point[1] = y;
        transformPointToViewLocal(point, child);// 將觸摸事件的坐標點按 child 中的相反矩陣轉換
        final boolean isInView = child.pointInView(point[0], point[1]);// 判斷轉換后的點是否在 view 的位置內
        if (isInView && outLocalPoint != null) {
          outLocalPoint.set(point[0], point[1]);
        }
        return isInView;
      }
      
      public void transformPointToViewLocal(float[] point, View child) {
        point[0] += mScrollX - child.mLeft;
        point[1] += mScrollY - child.mTop;
      
        if (!child.hasIdentityMatrix()) {// 如果設置了 translationX,這里肯定為 true
          child.getInverseMatrix().mapPoints(point);// 將觸控坐標點做相反矩陣計算,這里是核心
        }
      }
      
      final boolean hasIdentityMatrix() {
        return mRenderNode.hasIdentityMatrix();
      }
      

      上面可以看出,這里在判斷子view 是否可以收到觸控事件時,做了觸控矩陣轉換,如果轉換后的觸控位置在子view 范圍內,則認為可以收到觸控事件;

      上面涉及到矩陣 Matrix 類,很多人可能不是很清楚這個,關于這些,可能需要讀者自行學習,打開 Matrix 源碼,我們可以看到這樣一些方法:

      public void setRotate(float degrees)
      public void setScale(float sx, float sy)
      public void setTranslate(float dx, float dy)
      

      其實,在安卓中,關于 View 方面,很多平移,旋轉,放大縮小,都是通過Matrix 做坐標變換來完成的,包括 Canvas,Paint等繪圖基礎.

      posted on 2020-02-16 15:18  公子姓王  閱讀(673)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 色狠狠色婷婷丁香五月| 蜜桃臀av在线一区二区| 亚洲综合高清一区二区三区| 国产AV福利第一精品| 日本不卡一区| 小伙无套内射老熟女精品| 久久毛片少妇高潮| 久久精品无码av| 成人免费在线播放av| 久久精品国产亚洲夜色AV网站| 日韩精品无码区免费专区 | 97免费在线观看视频| 玩弄丰满少妇人妻视频| 精品尤物TV福利院在线网站| 伊人狠狠色j香婷婷综合| 国产精品午夜福利91| 久久精品国产精品亚洲艾| 亚洲欧洲日产国码久在线| xxxx丰满少妇高潮| 国产精品一线天在线播放| 国产欧美日韩在线在线播放| 在线中文一区字幕对白| 女同性恋一区二区三区视频| 国产白丝jk捆绑束缚调教视频| 国产精品一区二区久久毛片| 国产91午夜福利精品| 永川市| 中文字幕亚洲综合久久| 国产AV影片麻豆精品传媒| 亚洲成在人线AV品善网好看| 91中文字幕一区在线| 日本一区二区不卡精品| 无码中文字幕热热久久| 精品欧美一区二区三区久久久| 无码一区中文字幕| 亚洲国产精品成人综合色在| 亚洲日本va午夜在线电影| 日韩有码中文字幕av| 成人网站免费观看永久视频下载| 免费无码高潮流白浆视频| 日本久久香蕉一本一道|