注册

讲讲ViewGroup的setPersistentDrawingCache方法

这是一篇采坑文章,灵感来源于博主某篇文章中与大佬的聊天


前言

记得在三年前,还在上一个学校,学生时代的时候,接过一个外包的Android单,里面有个需求是在一个Activity中根据用户的点击反复的执行两个动画以达到比较好的交互效果。当时在网上没有找到类似的效果,最后还是在Android官方Demo里找到的。

而本人对其案例中setPersistentDrawingCache方法的理解一直是在对其进行优化。

mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);

并且在后续的自己开发APP中,甚至是拿了软著权准备上架的那几款APP相同情景下一直使用此方法。今天和大佬在另一篇文章中聊到性能消耗,于是测试了下setPersistentDrawingCache加与不加的性能消耗,结果发现貌似不加效果还好一点。


一、看看Demo中给出的注释

// Since we are caching large views, we want to keep their cache
//由于我们缓存的是大视图,我们希望保留它们的缓存

开始想着是动画的强度不够,加大了动画的强度,结果不加setPersistentDrawingCache还是好一点,于是去Android官方文档查看了下,才明白。

二、Android官方文档给出的介绍

此方法在APl级别28中已弃用,随着APl 11中硬件加速渲染的引入,视图绘图缓存在很大程度上已经过时了。在使用硬件加速时,中间缓存层基本上是不必要的,并且由于创建和更新该层的成本,很容易导致性能的净损失。在极少数情况下,缓存层是有用的,比如alpha动画。View.setLaverTvpe (int。android.araphics.Paint)通过硬件渲染处理这个问题。对于视图层次结构或单个视图的一小部分的软件渲染快照,建议从位图或图片创建一个Canvas,并在视图上调用View. draw(android.graphics.Canvas)。然而,这些软件渲染的用法是不鼓励的,并且与硬件渲染特性(如Config)存在兼容性问题。硬件位图,实时阴影,轮廓剪辑。对于Ul反馈报告或单元测试的屏幕截图,建议使用PixelCopy APl。

三、丢一个案例源码(此案例为官方Demo源码,根据个人修改了点效果)

代码比较简单就不解释了

1.3d动画类

public class Rotate3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mCenterX;
private final float mCenterY;
private final float mDepthZ;
private final boolean mReverse;
private Camera mCamera;


public Rotate3dAnimation(float fromDegrees, float toDegrees,
float centerX, float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}

@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;

final Matrix matrix = t.getMatrix();

camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();

matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}

2.Activity类

public class Transition3d extends Activity implements
AdapterView.OnItemClickListener, View.OnClickListener {
private ListView mPhotosList;
private ViewGroup mContainer;
private ImageView mImageView;

//item-name
private static final String[] PHOTOS_NAMES = new String[] {
"百度关键词",
"微信公众号",
"微信小程序",
"个人网站",
"掘金",
"同id:计蒙不吃鱼"
};
//item-img
private static final int[] PHOTOS_RESOURCES = new int[] {
R.drawable.aaaa,
R.drawable.aaaa1,
R.drawable.aaaa1,
R.drawable.aaaa,
R.drawable.aaaa,
R.drawable.aaaa

};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.animations_main_screen);

mPhotosList = (ListView) findViewById(android.R.id.list);
mImageView = (ImageView) findViewById(R.id.picture);
mContainer = (ViewGroup) findViewById(R.id.container);

// 准备列表视图
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, PHOTOS_NAMES);
mPhotosList.setAdapter(adapter);
mPhotosList.setOnItemClickListener(this);
// 准备图片
mImageView.setClickable(true);
mImageView.setFocusable(true);
mImageView.setOnClickListener(this);


//由于我们缓存的是大视图,我们希望在每个动画之间保持它们的缓存
mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
}

/**
* 在容器视图上设置一个新的3D旋转。
*
* @param position 单击该项以显示图片,或单击-1以显示列表
* @param start 旋转必须开始的起始角度
* @param end •旋转的结束角度
*/

private void applyRotation(int position, float start, float end) {
//找到容器的中心
final float centerX = mContainer.getWidth() / 2.0f;
final float centerY = mContainer.getHeight() / 2.0f;

//使用提供的参数创建一个新的3D旋转
// 动画监听器用于触发网络动画
final Rotate3dAnimation rotation =
new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
rotation.setDuration(500);
rotation.setFillAfter(true);
rotation.setInterpolator(new AccelerateInterpolator());
rotation.setAnimationListener(new DisplayNextView(position));

mContainer.startAnimation(rotation);
}

public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
//预加载图像然后开始动画
mImageView.setImageResource(PHOTOS_RESOURCES[position]);
applyRotation(position, 0, 90);
}

public void onClick(View v) {
applyRotation(-1, 180, 90);
}

/**
这class收听动画前半部分的结尾部分。•当容器旋转90度,因此不可见时,它会发布一个新的动作,有效地交换视图。
*/

private final class DisplayNextView implements Animation.AnimationListener {
private final int mPosition;

private DisplayNextView(int position) {
mPosition = position;
}

public void onAnimationStart(Animation animation) {
}

public void onAnimationEnd(Animation animation) {
mContainer.post(new SwapViews(mPosition));
}

public void onAnimationRepeat(Animation animation) {
}
}

/**
这个类负责交换视图并启动第二个视图
动画的一半。
*/

private final class SwapViews implements Runnable {
private final int mPosition;

public SwapViews(int position) {
mPosition = position;
}

public void run() {
final float centerX = mContainer.getWidth() / 2.0f;
final float centerY = mContainer.getHeight() / 2.0f;
Rotate3dAnimation rotation;

if (mPosition > -1) {
mPhotosList.setVisibility(View.GONE);
mImageView.setVisibility(View.VISIBLE);
mImageView.requestFocus();

rotation = new Rotate3dAnimation(90, 180, centerX, centerY, 310.0f, false);
} else {
mImageView.setVisibility(View.GONE);
mPhotosList.setVisibility(View.VISIBLE);
mPhotosList.requestFocus();

rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false);
}

rotation.setDuration(500);
rotation.setFillAfter(true);
rotation.setInterpolator(new DecelerateInterpolator());

mContainer.startAnimation(rotation);
}
}

}

3.布局文件

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">


<ListView
android:id="@android:id/list"
android:persistentDrawingCache="animation|scrolling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_bottom_to_top_slide" />


<ImageView
android:id="@+id/picture"
android:scaleType="fitCenter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />


</FrameLayout>

4.Listview的载入动画

  • layout_bottom_to_top_slide.xml
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="30%"
android:animationOrder="reverse"
android:animation="@anim/slide_right" />

  • slide_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
<translate android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="@android:integer/config_shortAnimTime" />

</set>

5.效果图

Video_20210831_035149_726.gif

0 个评论

要回复文章请先登录注册