How to make Rotate3dAnimation more smoother?

前端 未结 4 846
北荒
北荒 2020-12-30 06:47

In my app I am using Rotate3dAnimation to show a Google map. The code is working fine, but the animation is not smooth, some lines are also visible while rotating the view.

相关标签:
4条回答
  • 2020-12-30 07:01

    I have made the animation like this. I had the same problems. So, suggestions:

    • make xml layout as simple as possible, you can test it using Hierarchy View tool in android. It tool shows the time of building and drawing the laoyuts;

    • images on layout should have so low weight as possible;

    • use hardware acceleration if your device supports it (in manifest):

    • I have noticed one more interesing behavior. If I call some code in onAnimationEnd(Animation animation) method, the animation freezes for a short time. This problem I was solved using next construction:

      private static final int DELAY_AFTER_ANIMATION = 10;

      public void onAnimationEnd(Animation animation) { new Handler().postDelayed(new Runnable() { @Override public void run() { setData(); // do the heavy code here } }, DELAY_AFTER_ANIMATION); }

    To construct animation I used the same code (Rotate3dAnimation). For calling animation(main difference is using the isReverse parameter):

    public void apply3dRotation(float start, float end, AnimationListener listener, boolean isReverse) {
        View view = getRotateView();
        if(view == null){
            return;
        }
    
        if (isHardwareAcceleartionNotSupported()){
            AndroidHelper.disableHardwareAccelerationOnView(view, this.getClass());
        }
    
        final float centerX = view.getWidth() / 2.0f;
        final float centerY = view.getHeight() / 2.0f;
    
        Flip3dAnimation rotation;
    
        rotation = new Flip3dAnimation(start, end, centerX, centerY, 310.0f, isReverse);
        rotation.setDuration(ANIMATION_DURATION);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
    
        if(listener != null){
            rotation.setAnimationListener(listener);
        }
    
        view.startAnimation(rotation);
    }
    

    isHardwareAcceleartionNotSupported() method checks the OS version. In my project I disabled acceleration for smartphones. In AndroidHelper class:

    public static void disableHardwareAccelerationOnView(View view, Class c){
        try {
            view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        } catch (Error e) {
            Log.i(c.getSimpleName(), e.getMessage());
        }
    }
    

    And one problem yet. If the animation hides when screen rotates to 90 degrees, it's a problem of a camera. In this case we should to place image farther from the spectator.

    • And one more trick - sometimes I set the pause before animation start:

        animation.setStartOffset(100);
      
    0 讨论(0)
  • 2020-12-30 07:10

    One option for (non-OpenGL) 3d animation effects on Android is to implement the animations in a ViewGroup's getChildStaticTransform method using the graphics.Camera and Matrix classes.

    In broad terms it's done like this:

    • Extend ViewGroup or a subclass thereof.

    • In the constructors, set staticTransformationEnabled to true:

       setStaticTransformationsEnabled(true);
      
    • Override the protected method getChildStaticTransformation(View view, Transformation t).

    • In getChildStaticTransformation, use graphics.Camera to rotate the View as per your picture.

    • Get the camera's matrix and adjust it to center the camera position on the view.

    For example, this is how a 3d translation effect is done in the 3d carousel by Igor Kushnarev:

    protected boolean getChildStaticTransformation(View child, Transformation transformation) {
       //...
        // Center of the item
        float centerX = (float)child.getWidth()/2, centerY = (float)child.getHeight()/2;
    
        // Save camera
        mCamera.save();
    
        // Translate the item to it's coordinates
        final Matrix matrix = transformation.getMatrix();
        mCamera.translate(((CarouselImageView)child).getX(), 
                ((CarouselImageView)child).getY(), 
                ((CarouselImageView)child).getZ());
    
        // Get the camera's matric and position the item
        mCamera.getMatrix(matrix);
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    
        // Restore camera
        mCamera.restore();      
    
        return true;
     }    
    

    Here are some more code examples on how to use graphics.Camera and Matrixin getChildStaticTransformation:

    • ViewPager3d by Inovex. This project is interesting because if you run it as is, the 3d animation is not smooth (on a Galaxy S2). Hoverever, if you strip it of the non-camera/matrix overscroll animations but keep the getChildStaticTransformation 3d effects done with camera and matrix, the 3d effects are smooth.

    • CoverFlow by Neil Davies.

    0 讨论(0)
  • 2020-12-30 07:16

    I will just give a small hint; however right now I am so busy at work I can not implement this.

    The steps are

    • get your drawing cache Bitmap
    • set your content to an imageview only with this Bitmap
    • apply the animation to this imageview
    • at the end of the animation re set your content

    This I believe will maximize the performance.

    I will try to write some code later.

    CODE

    View longLivingReference; //keep a reference
    private void applyRotation(int position, float start, float end) {
        longLivingReference = findViewById(R.id.event_container);
        longLivingReference .setDrawingCacheEnabled(true);
        Bitmap bitmapForAnimation = Bitmap.createBitmap(longLivingReference.getDrawingCache());
        ImageView iv = new ImageView(mContext);
        iv = new ImageView(mContext);
        iv.setImageBitmap(bitmapForAnimation);
        setContentView(iv);
    
        final float centerX = mContainer.getWidth() / 2.0f;
        final float centerY = mContainer.getHeight() / 2.0f;
        final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
        rotation.setDuration(500);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        rotation.setAnimationListener(yourAnimationListener {
            //whatever your AnimationListener is, you can call super.onAnimationEnd if needed
            @Override
            public void onAnimationEnd(Animation animation) {
                setContentView(longLivingReference);
            }
        });
        iv.startAnimation(rotation);
    }
    
    0 讨论(0)
  • 2020-12-30 07:19

    I cannot understand ur question completely but according to me,

    The key to a smoothly scrolling Rotate3dAnimation is to keep the application’s main thread (the UI thread) free from heavy processing. Ensure you do any disk access, network access, or SQL access in a separate thread.

    This link isfor listview Rotate3dAnimation...

    0 讨论(0)
提交回复
热议问题