讲讲ViewGroup的setPersistentDrawingCache方法

Posted 计蒙不吃鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了讲讲ViewGroup的setPersistentDrawingCache方法相关的知识,希望对你有一定的参考价值。

系列文章目录

讲讲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.效果图

以上是关于讲讲ViewGroup的setPersistentDrawingCache方法的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义ViewGroup

Firebase auth setPersistance(type: 'SESSION') throws INTERNAL ASSERTION FAILED: Expected a class def

无法通过 Helm 安装 Grafana

Android-浅谈ViewGroup

自定义控件自定义ViewGroup 在ViewGroup中显示TextView

android--------自定义控件 之 ViewGroup