两行代码搞定Android视图扩散切换效果

ChlE53 8年前
   <p>用最简单的方式来实现Android视图扩散切换效果。</p>    <h3>一、概述</h3>    <p>这两天时间动手撸了个视图扩散切换效果的控制器,API兼容至 <strong>Android4.0</strong> ,更方便我们在视图切换过程中有炫酷的过渡效果。本来是想实现两个 View 之间的过渡动画,实现的过程中想到之前写的 Activity 切换动画,就试着加上了对 Activity 切换的动画支持。先来看看效果吧,代码实现只需一行,感觉还不错~</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/42e1ed66a97de843b60f6e937f27305a.gif"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/83ef2c73d55880ec6cb94138735fe1c0.gif"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b12b63c360c5f40d7ad1d510d165a45e.gif"></p>    <h3>二、实现思路简单阐述</h3>    <p>关于过渡动画的实现,我们先简单分解下这个效果,首先,当Activity发生跳转时我们要先获取共享元素控件,在跳转的界面将其添加在跳转页面之上,关于控件位置的获取,在上一篇文章 Android碎裂的粒子效果 一文中进行了介绍,主要是通过如下方法获取其位置:</p>    <pre>  <code class="language-java">protected Rect getRectInWindow(View view, boolean mIsFullWindow){              int[] location = new int[2];              view.getLocationInWindow(location);              return new Rect(location[0],location[1],location[0]+view.getMeasuredWidth(),location[1]+view.getMeasuredHeight());      }</code></pre>    <p>当跳转至目标页面,我们现在其上方盖上一层遮罩,遮罩为我们自定义的控件,在控件上方绘制上一个页面的过渡视图,将其旋转、平移、或者缩放操作:</p>    <pre>  <code class="language-java">canvas.save();              Matrix matrix = new Matrix();              matrix.postTranslate(mRect.left ,mRect.top);              matrix.postScale(mScaleXCanvas,mScaleYCanvas,mRect.centerX(),mRect.centerY());              matrix.postRotate(mRotationCanvas,mRect.centerX(),mRect.centerY());                canvas.concat(matrix);              mView.draw(canvas);              canvas.restore();</code></pre>    <p>最后就是圆形散开效果了,这里我在自定义控件上使用的是 Xfermode ,不断 drawCircle 并扩大半径,最终显示出跳转页面视图并将遮罩移除。记得关闭硬件加速。</p>    <pre>  <code class="language-java">mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));          setLayerType(LAYER_TYPE_SOFTWARE,null);</code></pre>    <p>返回动画同理,在界面返回前将遮罩盖在上一个页面之上,遮罩包括当前页面的视图影像,不断 drawCircle 并缩小其半径,同时减小当前页面视图的透明度,最终平滑的显示出上一个页面并移除遮罩。</p>    <h3>三、具体使用</h3>    <pre>  <code class="language-java">helper = new BaseViewHelper                  .Builder(SecondActivity.this)                  //.setEndView()//如果是两个切换的视图  这里设定最终显示的视图                  .setTranslationView(v)//设置过渡视图                  .isFullWindow(true)//是否全屏显示                  .isShowTransition(true)//是否显示过渡动画                  .setDimColor(Color.WHITE)//遮罩颜色                  .setDimAlpha(200)//遮罩透明度                  //.setTranslationX(0)//x轴平移                  //.setRotation(360)//旋转                  //.setScaleX(0)//x轴缩放                  //.setScaleY(0)//y轴缩放                  //.setTranslationY(0)//y轴平移                  //.setDuration(800)//过渡时长                  //.setInterpolator(new AccelerateDecelerateInterpolator())//设置插值器                  //设置监听  //                .setOnAnimationListener(new BaseViewHelper.OnAnimationListener() {  //                    @Override  //                    public void onAnimationStartIn() {  //                        Log.e("TAG","onAnimationStartIn");  //                    }  //  //                    @Override  //                    public void onAnimationEndIn() {  //                        Log.e("TAG","onAnimationEndIn");  //                    }  //  //                    @Override  //                    public void onAnimationStartOut() {  //                        Log.e("TAG","onAnimationStartOut");  //                    }  //  //                    @Override  //                    public void onAnimationEndOut() {  //                        Log.e("TAG","onAnimationEndOut");  //                    }  //                })                  .create();//开始动画</code></pre>    <p>如果从A页面跳转至B页面,也就是Activity之间的跳转时,在A页面如下代码 :</p>    <pre>  <code class="language-java">new BaseViewHelper                  .Builder(MainActivity.this, view)                  .startActivity(intent);</code></pre>    <p>B页面代码:</p>    <pre>  <code class="language-java">helper = new BaseViewHelper                  .Builder(SecondActivity.this)                  .isFullWindow(true)//是否全屏显示                  .isShowTransition(true)//是否显示过渡动画                  .setDimColor(Color.WHITE)//遮罩颜色                  .setDimAlpha(200)//遮罩透明度                  .create();//开始动画        @Override      public void onBackPressed() {          if (helper!=null && helper.isShowing()){              helper.backActivity(this);          }else {              super.onBackPressed();          }      }</code></pre>    <p>如果在一个页面两个视图之间跳转,即A视图切换到B视图:</p>    <p>在当前页面代码:</p>    <pre>  <code class="language-java">View v = View.inflate(this,R.layout.layout_second,null);              //显示在当前页面跳转              helper = new BaseViewHelper.Builder(this,view)                      .setEndView(v)                      .create();          @Override      public void onBackPressed() {          if (helper!=null && helper.isShowing()){              helper.back();          }else {              super.onBackPressed();          }      }</code></pre>    <h3> </h3>    <p> </p>    <p> </p>