This is the 31st day of my participation in the August Text Challenge.More challenges in August

Series of articles

About ViewGroup setPersistentDrawingCache method


This is a pit mining article, inspired by a blogger’s chat with the big guy in an article


preface

I remember three years ago, when I was a student in my school, I received an outsourced Android order. There was a requirement that two animations should be executed repeatedly in one Activity according to the user’s clicks to achieve better interaction effects. There was no similar effect on the Internet at that time, but it was finally found in the official Android Demo.

And my understanding of the case setPersistentDrawingCache method has been in the optimization.

mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
Copy the code

And in the subsequent development of their own apps, even with the soft rights to prepare for the launch of the several apps in the same situation has been using this method. And bosses today in another article talking about consumption performance, then test the setPersistentDrawingCache with and without performance under consumption, found that seemingly without effect is better.


Take a look at the comments in the Demo

// Since we are caching large views, we want to keep their cacheCopy the code

Began to think about is the strength of the animation is not enough, increase the strength of the animation, the results do not add setPersistentDrawingCache or better, then go to the Android examined under the official document, just understand.

Ii. Introduction to Android official documentation

This approach was deprecated at APl level 28, and view drawing caching was largely obsolete with the introduction of hardware-accelerated rendering in APl 11. When using hardware acceleration, an intermediate cache layer is essentially unnecessary and can easily result in a net loss of performance due to the cost of creating and updating it. In rare cases, the cache layer can be useful, such as alpha animations. The setLaverTvpe (int. Android.arapics.Paint) handles this problem with hardware rendering. For a View hierarchy or a software rendered snapshot of a small portion of a single View, it is recommended to create a Canvas from a bitmap or picture and call view.draw (Android.graphics.canvas) on the View. However, the use of these software renders is discouraged and has compatibility issues with hardware rendering features such as Config. Hardware bitmap, real-time shadows, contour clipping. PixelCopy APl is recommended for Ul feedback reports or screenshots of unit tests.

Third, lose a case source code (this case is the official Demo source, according to the personal modification of the effect)

I won’t explain the code because it’s a little bit simpler

1.3 d animation classes

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 * (0.0f-interpolatedTime)); } camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); }}Copy the code

2. The Activity class

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[] {
            "Baidu Keywords"."Wechat Official Account"."Wechat Mini Program"."Personal Website"."Nuggets"."Same id: Ji Meng doesn't eat fish."
    };
    //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);

        // Prepare the list view
        final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                android.R.layout.simple_list_item_1, PHOTOS_NAMES);
        mPhotosList.setAdapter(adapter);
        mPhotosList.setOnItemClickListener(this);
        // Prepare the image
        mImageView.setClickable(true);
        mImageView.setFocusable(true);
        mImageView.setOnClickListener(this);


        Since we are caching large views, we want to keep them cached between each animation
        mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
    }

    /** * Sets a new 3D rotation on the container view. * *@paramPosition Click the item to display the picture, or -1 to display the list *@paramStart The initial Angle at which the rotation must start *@paramEnd • End Angle of rotation */
    private void applyRotation(int position, float start, float end) {
        // Find the center of the container
        final float centerX = mContainer.getWidth() / 2.0 f;
        final float centerY = mContainer.getHeight() / 2.0 f;

        // Create a new 3D rotation with the parameters provided
        // Animation listener is used to trigger network animation
        final Rotate3dAnimation rotation =
                new Rotate3dAnimation(start, end, centerX, centerY, 310.0 f.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) {
        // Preload the image and start the animation
        mImageView.setImageResource(PHOTOS_RESOURCES[position]);
        applyRotation(position, 0.90);
    }

    public void onClick(View v) {
        applyRotation(-1.180.90);
    }

    /** This class listens to the end of the first half of the animation. • When the container is rotated 90 degrees and therefore not visible, it posts a new action, effectively swapping views. * /
    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) {}}/** This class is responsible for exchanging views and initiating half of the second view animation. * /
    private final class SwapViews implements Runnable {
        private final int mPosition;

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

        public void run(a) {
            final float centerX = mContainer.getWidth() / 2.0 f;
            final float centerY = mContainer.getHeight() / 2.0 f;
            Rotate3dAnimation rotation;
            
            if (mPosition > -1) {
                mPhotosList.setVisibility(View.GONE);
                mImageView.setVisibility(View.VISIBLE);
                mImageView.requestFocus();

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

                rotation = new Rotate3dAnimation(90.0, centerX, centerY, 310.0 f.false);
            }

            rotation.setDuration(500);
            rotation.setFillAfter(true);
            rotation.setInterpolator(newDecelerateInterpolator()); mContainer.startAnimation(rotation); }}}Copy the code

3. Layout file

<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>
Copy the code

Listview loading animation

  • 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" />
Copy the code
  • 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>
Copy the code

5. Rendering