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

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

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

      安卓筆記俠

      專注安卓開發

      導航

      Android View體系(四)從源碼解析Scroller

      在Android View體系(二)實現View滑動的六種方法這篇文章中我們講到了用Scroller來實現View的滑動,所以這篇文章我們就不介紹Scroller是如何使用的了,本篇就從源碼來分析下Scroller為何能夠實現View的滑動。

      1.Scroller的構造函數

      要想使用Scroller,必須先調用new Scroller(),我們先來看看Scroller的構造函數:

      /**
        * Create a Scroller with the default duration and interpolator.
        */
       public Scroller(Context context) {
           this(context, null);
       }
      
       /**
        * Create a Scroller with the specified interpolator. If the interpolator is
        * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
        * be in effect for apps targeting Honeycomb or newer.
        */
       public Scroller(Context context, Interpolator interpolator) {
           this(context, interpolator,
                   context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
       }
      
       /**
        * Create a Scroller with the specified interpolator. If the interpolator is
        * null, the default (viscous) interpolator will be used. Specify whether or
        * not to support progressive "flywheel" behavior in flinging.
        */
       public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
           mFinished = true;
           if (interpolator == null) {
               mInterpolator = new ViscousFluidInterpolator();
           } else {
               mInterpolator = interpolator;
           }
           mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
           mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
           mFlywheel = flywheel;
      
           mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
       }
      View Code

      Scroller有三個構造函數,通常情況我們都用第一種,第二種需要傳進去一個差值器Interpolator ,如果不傳則采用默認的差值器(viscous)。

      2.Scroller的startScroll方法

      public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            mMode = SCROLL_MODE;
            mFinished = false;
            mDuration = duration;
            mStartTime = AnimationUtils.currentAnimationTimeMillis();
            mStartX = startX;
            mStartY = startY;
            mFinalX = startX + dx;
            mFinalY = startY + dy;
            mDeltaX = dx;
            mDeltaY = dy;
            mDurationReciprocal = 1.0f / (float) mDuration;
        }
      View Code

      在startScroll()方法中并沒有調用類似開啟滑動的方法,而是保存了傳進來的各種參數:startX和startY表示滑動開始的起點,dx和dy表示滑動的距離,duration則表示滑動持續的時間。所以startScroll()方法只是用來做前期準備的并不能使View進行滑動。關鍵是我們在startScroll()方法后調用了 invalidate()方法,這個方法會導致View的重繪,而View的重繪會調用View的draw()方法,draw()方法又會調用View的computeScroll()方法,我們重寫computeScroll()方法:

      @Override
      public void computeScroll() {
            super.computeScroll();
            if(mScroller.computeScrollOffset()){
                ((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
                 //通過不斷的重繪不斷的調用computeScroll方法
                invalidate();
            }
        }
      View Code

      我們在computeScroll()方法中通過Scroller來獲取當前的ScrollX和ScrollY然后調用scrollTo()方法來進行View的滑動,接著調用invalidate方法來讓View進行重繪,重繪就會調用computeScroll()方法來實現View的滑動。這樣我們就通過不斷的移動一個小的距離并連貫起來就實現了平滑移動的效果。但是在Scroller中我們如何能獲取當前的位置的ScrollX和ScrollY呢?我們忘了一點就是在調用scrollTo()方法前會調用Scroller的computeScrollOffset()方法,接下來我們就來看看computeScrollOffset()方法。

      3.Scroller的computeScrollOffset方法

      public boolean computeScrollOffset() {
             if (mFinished) {
                 return false;
             }
             //動畫持續的時間
             int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
         
             if (timePassed < mDuration) {
                 switch (mMode) {
                 case SCROLL_MODE:
                     final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
                     //根據插值器來算出timePassed這段時間移動的距離
                     mCurrX = mStartX + Math.round(x * mDeltaX);
                     mCurrY = mStartY + Math.round(x * mDeltaY);
                     break;
                 case FLING_MODE:
                     final float t = (float) timePassed / mDuration;
                     final int index = (int) (NB_SAMPLES * t);
                     float distanceCoef = 1.f;
                     float velocityCoef = 0.f;
                     if (index < NB_SAMPLES) {
                         final float t_inf = (float) index / NB_SAMPLES;
                         final float t_sup = (float) (index + 1) / NB_SAMPLES;
                         final float d_inf = SPLINE_POSITION[index];
                         final float d_sup = SPLINE_POSITION[index + 1];
                         velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
                         distanceCoef = d_inf + (t - t_inf) * velocityCoef;
                     }
      
                     mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
                     
                     mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
                     // Pin to mMinX <= mCurrX <= mMaxX
                     mCurrX = Math.min(mCurrX, mMaxX);
                     mCurrX = Math.max(mCurrX, mMinX);
                     
                     mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
                     // Pin to mMinY <= mCurrY <= mMaxY
                     mCurrY = Math.min(mCurrY, mMaxY);
                     mCurrY = Math.max(mCurrY, mMinY);
      
                     if (mCurrX == mFinalX && mCurrY == mFinalY) {
                         mFinished = true;
                     }
      
                     break;
                 }
             }
             else {
                 mCurrX = mFinalX;
                 mCurrY = mFinalY;
                 mFinished = true;
             }
             return true;
         }
      View Code

      首先會計算動畫持續的時間timePassed,如果動畫持續時間小于我們設置的滑動持續時間mDuration,則執行Swich語句,因為在startScroll()方法中mMode為SCROLL_MODE所以執行分支語句SCROLL_MODE,然后根據插值器Interpolator來計算出在該時間段里面移動的距離,賦值給mCurrX和mCurrY,這樣我們就能通過Scroller來獲取當前的ScrollX和ScrollY了。另外,computeScrollOffset()的返回值如果為true則表示滑動未結束,false則表示滑動結束,所以如果滑動未結束我們就得持續的調用scrollTo()方法和invalidate()方法來進行View的滑動。

       

      posted on 2016-11-06 10:49  安卓筆記俠  閱讀(660)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 亚洲AV日韩AV激情亚洲| 亚洲鸥美日韩精品久久| 午夜免费无码福利视频麻豆| 中文字幕国产在线精品| 精品国产迷系列在线观看| 伊人久久久av老熟妇色| 麻豆精品久久久久久久99蜜桃| 久久热在线视频精品视频| 亚洲人成网站在线观看播放不卡 | 久久激情影院| 欧美黑吊大战白妞| 99久久伊人精品综合观看| 久久精品国产亚洲成人av| 通化市| 麻豆精品一区二区综合av| brazzers欧美巨大| 麻豆精品国产熟妇aⅴ一区| 91高清免费国产自产拍| 无码精品一区二区免费AV| 日韩中文字幕综合第二页| 大同市| 国产精品久久久久7777| 亚洲午夜无码久久久久小说| 熟妇人妻av中文字幕老熟妇| 久久香蕉国产线看观看猫咪av| 无码人妻精品丰满熟妇区| 国产激情第一区二区三区| 日夜啪啪一区二区三区| 亚洲最大成人网色| 亚洲自拍偷拍福利小视频| 非会员区试看120秒6次| 国产69久久精品成人看| 亚洲精品二区在线播放| 67194熟妇在线观看线路| 国产av无码国产av毛片| 国产97人人超碰CAO蜜芽PROM | 玩弄漂亮少妇高潮白浆| 长腿校花无力呻吟娇喘| 亚洲无码精品视频| 国产精品国产精品无卡区| 亚洲精品国产一二三区|