Android之开门动画的实现

实现原理

  • 如何将一个View视图一分为二?(效果图:)
OpenAnim.gif

实现步骤

  1. 其实就是将整个View视图缓存成一张图片,需要开启一下功能

     //缓存图像
            mMainContainer.setDrawingCacheEnabled(true);  //开启缓存
            mMainContainer.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); //设置缓存的质量
             Bitmap bitmap = mMainContainer.getDrawingCache();
    
  • 注意事项:

    1. 如果以上方法放在Activity的onCreate(),onStart(),onResume()方法调用.那么getDrawingCache()方法会返回一个Null,那么就会空指针异常,原因:

      1. 因为在onCreate(),onStart(),onResume方法中,View还没有测量完成,布局完成,所以拿不到宽高,只有0,所以这个时候getDrawingCache()方法就会返回Null.我画了个图:如图所示:
View框架视图.png
  1. 解决方法:(解决方法很多)

    • 可以在onResume()方法中开辟线程,并延时300ms执行以上方法.这个时候子View就被添加到了DectorView中了

    • 我是在onWindowFocusChanged方法中调用.在这个方法中子View已经添加到DectorView中了,所以已经有宽高属性了

       @Override
          public void onWindowFocusChanged(boolean hasFocus) {
              super.onWindowFocusChanged(hasFocus);
              initData();
          }
      

      initData()方法:

        //缓存图像
              mMainContainer.setDrawingCacheEnabled(true);  //开启缓存
              mMainContainer.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); //设置缓存的质量
               Bitmap bitmap = mMainContainer.getDrawingCache();
      
    • 或者手动进行测量,布局.添加如下代码:

       mMainContainer.setDrawingCacheEnabled(true);  //开启缓存
              mMainContainer.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); //设置缓存的质量
              mMainContainer.buildDrawingCache();
              mMainContainer.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                      View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
              mMainContainer.layout(0, 0, mMainContainer.getMeasuredWidth(), mMainContainer.getMeasuredHeight());
              Bitmap bitmap = mMainContainer.getDrawingCache();
      

  2. 缓存好View视图为图片之后,就需要将这张图片一份为2了,那么就需要两个容器装着左半部分图片和右半部分图片了.现在贴一下布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.kira.opendooranimdemo.MainActivity">
    <!-- 被分裂的视图-->
    <RelativeLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <ImageView

            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:background="@mipmap/ahri_2"
            />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="测试测试"/>

    </RelativeLayout>

    <!-- 图片容器-->
    <LinearLayout
        android:visibility="invisible"
        android:id="@+id/anim_container"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="match_parent">
        <ImageView
            android:id="@+id/iv_left"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            />
        <ImageView
            android:id="@+id/iv_right"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            />
    </LinearLayout>

</RelativeLayout>

  1. 开始将缓存出来的图片一分为2:

     Bitmap leftBitmap = getLeftBitmap(bitmap);
            mLeft.setImageBitmap(leftBitmap);
    
            Bitmap rightBitmap = getRightBitmap(bitmap);
            mRight.setImageBitmap(rightBitmap);
    startOpenAnim();
    
    • getLeftBitmap()方法,代码如下:

       private Bitmap getLeftBitmap(Bitmap bitmap) {
              int width=(int) (bitmap.getWidth() / 2f + 0.5f);
              //画画需要白纸,Bitmap就是那张白纸
              Bitmap leftCopyBitmap = Bitmap.createBitmap(width, bitmap.getHeight(), bitmap.getConfig());
              //创建画布
              Canvas canvas=new Canvas(leftCopyBitmap);
              Matrix matrix = new Matrix();
              //画画需要画笔,创建画笔
              Paint paint=new Paint();
              canvas.drawBitmap(bitmap,matrix,paint);
              return leftCopyBitmap;
          }
      
    • getRightBitmap()方法,代码如下:

       private Bitmap getRightBitmap(Bitmap bitmap) {
              int width=(int) (bitmap.getWidth() / 2f + 0.5f);
              //画画需要白纸,Bitmap就是那张白纸
              Bitmap rightCopyBitmap = Bitmap.createBitmap(width, bitmap.getHeight(), bitmap.getConfig());
              //创建画布
               Canvas canvas=new Canvas(rightCopyBitmap);
              Matrix matrix=new Matrix();
              //要获取右半部分的图片则需要图片向左平移一半
              matrix.setTranslate(-width,0);
              //画画需要画笔,创建画笔
              Paint paint=new Paint();
              canvas.drawBitmap(bitmap,matrix,paint);
              return rightCopyBitmap;
          }
      
  2. 最后开启动画:代码如下

       private void startOpenAnim() {
            mMainContainer.setVisibility(View.GONE);
            mAnimContainer.setVisibility(View.VISIBLE);
            int leftWidth = mLeft.getWidth();
            int rightWidth = mRight.getWidth();
            ObjectAnimator leftAnim = ObjectAnimator.ofFloat(mLeft, "translationX", 0, -leftWidth);
            ObjectAnimator rightAnim = ObjectAnimator.ofFloat(mRight, "translationX",0, rightWidth);
            ObjectAnimator mainAnim = ObjectAnimator.ofFloat(mAnimContainer, "alpha", 1, 0);
            AnimatorSet set=new AnimatorSet();
            set.setDuration(3*1000);
            set.playTogether(leftAnim,rightAnim,mainAnim);
            set.start();
        }
    

    到这里就大功告成了.

    ​ 所有代码如下:

 package com.kira.opendooranimdemo;
   import android.animation.AnimatorSet;
   import android.animation.ObjectAnimator;
   import android.graphics.Bitmap;
   import android.graphics.Canvas;
   import android.graphics.Matrix;
   import android.graphics.Paint;
   import android.os.Bundle;
   import android.support.v7.app.AppCompatActivity;
   import android.util.Log;
   import android.view.View;
   import android.widget.ImageView;
   import android.widget.LinearLayout;
   import android.widget.RelativeLayout;
   public class MainActivity extends AppCompatActivity {
       private ImageView mLeft;
       private ImageView mRight;
       private LinearLayout mAnimContainer;
       private RelativeLayout mMainContainer;
       private static final String TAG = "MainActivity";

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           initView();

          // initNewData();
       }

       @Override
       public void onWindowFocusChanged(boolean hasFocus) {
           super.onWindowFocusChanged(hasFocus);
           initData();
       }

       private void initNewData() {
           int height=0;
           for (int i = 0; i < mMainContainer.getChildCount(); i++) {
               height+=mMainContainer.getChildAt(i).getHeight();
           }
           //创建对应大小的Bitmap
           Log.e(TAG, "initNewData: "+mMainContainer.getWidth()+"....."+height);
           Bitmap bitmap = Bitmap.createBitmap(300, 500, Bitmap.Config.ARGB_8888);
           Bitmap leftBitmap = getLeftBitmap(bitmap);
           mLeft.setImageBitmap(leftBitmap);

           Bitmap rightBitmap = getRightBitmap(bitmap);
           mRight.setImageBitmap(rightBitmap);
           startOpenAnim();
       }

       private void initData() {
           //缓存图像
           mMainContainer.setDrawingCacheEnabled(true);  //开启缓存
           mMainContainer.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); //设置缓存的质量
   //        mMainContainer.buildDrawingCache();
   //        mMainContainer.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
   //                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
   //        mMainContainer.layout(0, 0, mMainContainer.getMeasuredWidth(), mMainContainer.getMeasuredHeight());
           Bitmap bitmap = mMainContainer.getDrawingCache();


           Bitmap leftBitmap = getLeftBitmap(bitmap);
           mLeft.setImageBitmap(leftBitmap);

           Bitmap rightBitmap = getRightBitmap(bitmap);
           mRight.setImageBitmap(rightBitmap);

           startOpenAnim();
       }

       private void startOpenAnim() {
           mMainContainer.setVisibility(View.GONE);
           mAnimContainer.setVisibility(View.VISIBLE);
           int leftWidth = mLeft.getWidth();
           int rightWidth = mRight.getWidth();
           ObjectAnimator leftAnim = ObjectAnimator.ofFloat(mLeft, "translationX", 0, -leftWidth);
           ObjectAnimator rightAnim = ObjectAnimator.ofFloat(mRight, "translationX",0, rightWidth);
           ObjectAnimator mainAnim = ObjectAnimator.ofFloat(mAnimContainer, "alpha", 1, 0);
           AnimatorSet set=new AnimatorSet();
           set.setDuration(3*1000);
           set.playTogether(leftAnim,rightAnim,mainAnim);
           set.start();
       }

       private Bitmap getRightBitmap(Bitmap bitmap) {
           int width=(int) (bitmap.getWidth() / 2f + 0.5f);
           //画画需要白纸,Bitmap就是那张白纸
           Bitmap rightCopyBitmap = Bitmap.createBitmap(width, bitmap.getHeight(), bitmap.getConfig());
           //创建画布
            Canvas canvas=new Canvas(rightCopyBitmap);
           Matrix matrix=new Matrix();
           //要获取右半部分的图片则需要图片向左平移一半
           matrix.setTranslate(-width,0);
           //画画需要画笔,创建画笔
           Paint paint=new Paint();
           canvas.drawBitmap(bitmap,matrix,paint);
           return rightCopyBitmap;
       }

       private Bitmap getLeftBitmap(Bitmap bitmap) {
           int width=(int) (bitmap.getWidth() / 2f + 0.5f);
           //画画需要白纸,Bitmap就是那张白纸
           Bitmap leftCopyBitmap = Bitmap.createBitmap(width, bitmap.getHeight(), bitmap.getConfig());
           //创建画布
           Canvas canvas=new Canvas(leftCopyBitmap);
           Matrix matrix = new Matrix();
           //画画需要画笔,创建画笔
           Paint paint=new Paint();
           canvas.drawBitmap(bitmap,matrix,paint);
           return leftCopyBitmap;


       }

       private void initView() {
           mLeft = (ImageView) findViewById(R.id.iv_left);
           mRight = (ImageView) findViewById(R.id.iv_right);
           mAnimContainer = (LinearLayout) findViewById(R.id.anim_container);
           mMainContainer = (RelativeLayout) findViewById(R.id.main_container);
       }
   }

布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.kira.opendooranimdemo.MainActivity">
    <!-- 被分裂的视图-->
    <RelativeLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <ImageView

            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:background="@mipmap/ahri_2"
            />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="测试测试"/>

    </RelativeLayout>

    <!-- 图片容器-->
    <LinearLayout
        android:visibility="invisible"
        android:id="@+id/anim_container"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="match_parent">
        <ImageView
            android:id="@+id/iv_left"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            />
        <ImageView
            android:id="@+id/iv_right"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"

            />
    </LinearLayout>

</RelativeLayout>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容