实现原理
- 如何将一个View视图一分为二?(效果图:)
实现步骤
-
其实就是将整个View视图缓存成一张图片,需要开启一下功能
//缓存图像 mMainContainer.setDrawingCacheEnabled(true); //开启缓存 mMainContainer.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); //设置缓存的质量 Bitmap bitmap = mMainContainer.getDrawingCache();
-
注意事项:
-
如果以上方法放在Activity的onCreate(),onStart(),onResume()方法调用.那么getDrawingCache()方法会返回一个Null,那么就会空指针异常,原因:
- 因为在onCreate(),onStart(),onResume方法中,View还没有测量完成,布局完成,所以拿不到宽高,只有0,所以这个时候getDrawingCache()方法就会返回Null.我画了个图:如图所示:
-
-
解决方法:(解决方法很多)
可以在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();
缓存好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>
-
开始将缓存出来的图片一分为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; }
-
-
最后开启动画:代码如下
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>