InstalMaterial學習筆記之Reveal效果

jopen 9年前發布 | 17K 次閱讀 Android開發 移動開發 InstalMaterial

本文記錄開源項目 InstalMaterial學習到的Reveal效果
國內有對應博客的翻譯


先看一下效果圖:


最后效果圖
</div>

慣例,不過這次是我學到了什么

  1. 對自定義屬性使用屬性動畫
  2. 屬性動畫,get方法不一定需要
  3. 最重要的是ViewTreeObserver.OnPreDrawListener()的使用,另一種過渡動畫的實現方式
  4. </ol>

    OK,開始吧

    首先

    仔細看動畫效果,其實就是一個半徑不斷變大的圓

    那么來實現這個效果吧

    1. 先定義個類RevealView,重載構造方法
    2. 增加一個成員變量 radius 表示圓的半徑
    3. 增加一個Paint變量 mPaint 用來畫
    4. </ol>

      如此后代碼如下:

      public RevealView(Context context) {
          super(context);
          init();
      }

      public RevealView(Context context, AttributeSet attrs) { super(context, attrs); init(); }

      public RevealView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); }

      private void init() { mPaint=new Paint(); mPaint.setColor(getResources().getColor(R.color.primary_dark)); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } private Paint mPaint; private int radius;</pre>

      接下來,我們重寫onDraw,畫個圓

      @Override
      protected void onDraw(Canvas canvas) {    
      super.onDraw(canvas);    
      //原點是中心    
      canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
      }

      接下去就是讓radius得值不斷發生變化了

      到這里,可能有同學會想著起個thread不停去賦值,再invalidate.
      其實不必這么麻煩,我們使用屬性動畫即可:

      //這里我計算了斜對角線的長度,這樣可以保證畫的圓能夠保證覆蓋整個view
      int maxRadius = (int) (Math.sqrt(Math.pow(getHeight(), 2)+ Math.pow(getWidth(), 2)));
      ObjectAnimator revealAnimator = ObjectAnimator.ofInt(this, "radius", 0,maxRadius).setDuration(300);
      revealAnimator.setInterpolator(new AccelerateInterpolator());
      revealAnimator.start();

      到這里熟悉屬性動畫的同學可能就知道,還差了getter setter方法
      Tip:其實事實上getter方法不是必須的,少了setter方法也不會崩潰,只是動畫沒有效果而已
      注意:

      //Notice 這里傳入了兩個值 如果只傳了一個,則會在動畫開始時候去調用gettter方法
      ObjectAnimator.ofInt(this, "radius", 0,maxRadius).setDuration(300);

      OK,讓我們加入setter方法:

      public void setRadius(int radius) {
          this.radius = radius;
          Log.d(TAG, "setRadius "+radius);
      }

      恩,OK,問自己一下,這樣,就好了嗎?
      答案是,沒有!
      我們還需要對setter方法加工一下

      public void setRadius(int radius) {
          this.radius = radius;
          Log.d(TAG, "setRadius "+radius);
          //Notice 調用invalidate 之后 onDraw才會被調用
          invalidate();
      }

      至此,我們運行一下:



      reveal_效果1階段.gif
      </div>

      初始效果已經出來了,但是你會發現,動畫結束后,我們的revealview把其他View都擋住了.

      呵呵,這個還不簡單嗎?動畫結束后給gone了不得了嘛?

      //新增一個callback 回調動畫結束
      public void setCallback(Callback callback) {
          this.callback = callback;
      }
      private Callback callback;
      public interface Callback{
          void onRevealEnd();
      }

      //在activity里設置 mVReveal.setCallback(new RevealView.Callback() { @Override public void onRevealEnd() { //隱藏 mVReveal.setVisibility(View.GONE); // todo 其他事情 } });</pre>

      然后跑起來試試:


      第一階段效果.gif
      </div>

      還不錯吧?

      接下來我們運用到Activity跳轉

      這個時候我們需要用到ViewTreeObserver.OnPreDrawListener()

      //在跳轉的activity里
      mVReveal.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
          @Override
          public boolean onPreDraw() {
             //必須remove掉 不然會重復調用
              mVReveal.getViewTreeObserver().removeOnPreDrawListener(this);
              mVReveal.startReveal();
              return false;
          }});

      //按鈕點擊事件

      Intent intent = new Intent(this, RevealActivity.class);intent.putExtra("location", location);startActivity(intent);overridePendingTransition(0, 0);//Notice 這個絕對不能省..不然沒有效果

      好了,差不多介紹到這里..
      不過其實還有其他的優化擴展,
      1.比如傳坐標,指定圓心開始reveal
      2.reveal結束后繼續其他的動畫
      大家自己試試吧:Github.

      最后總結下

      1. InstalMaterial 是一個值得你認真去學習的開源項目.
      2. 時間允許的話一定要動手實踐,不要覺得看著簡單就以為自己會了,其實沒你想的那么簡單.就像我,看著這個效果很簡單,原本覺得不用這么麻煩就可以實現,結果,最后還是一步一步照著frogermcs的代碼寫了下去,這樣才能真正學到東西.
      3. 自學不易,請堅持!
      4. </ol>

        另外,最近在閱讀HeadFirst設計模式,尋找朋友一起學習交流~
        下次見!~

        與我聯系,交個朋友

        我的新浪微博

        我的Github

        </blockquote> 來自:

       本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!