Android - Zoom animation using AnimatorSet

后端 未结 2 1818
我在风中等你
我在风中等你 2020-12-31 06:07

The official Zooming a View tutorial uses an AnimatorSet to zoom into a View. It creates the illusion of downward movement as the view expands. Later, the

相关标签:
2条回答
  • 2020-12-31 06:16

    Ok, I think you want a zoom out with upward movement from your images and description. I cant understand your code, it seems too much complex to me (I am a noob). Now I have done what you want using the following code. At first I declare a relative layout with an image view, this relative layout will be the container. I set initial width height, but we will change it later from code.

    <RelativeLayout
        android:id="@+id/container"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity">
    
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="400dp"
            android:layout_height="200dp"
            android:layout_centerHorizontal="true"
            android:scaleType="fitXY"
            android:src="@drawable/my_image"/>
    </RelativeLayout>
    

    Now In Activity I set a listener for layout change so that I can get the actual size of the container. Then set the the layout for ImageView.

    public class MainActivity extends Activity {
        ImageView im;
        RelativeLayout container;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Logger.init().hideThreadInfo().setMethodCount(0);
    
            setContentView(R.layout.activity_main);
            im = (ImageView) findViewById(R.id.imageView);
            container = (RelativeLayout) findViewById(R.id.container);
            container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    setInitialPos();
                    container.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            });
    
        }
    
        int width;
        int height;
        int topMargin;
    
        private void setInitialPos() {
            Logger.e("container: " + container.getWidth() + " x " + container.getHeight());
            width = container.getWidth();
            height = 400;
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) im.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = height;
            topMargin = (container.getHeight() - height) / 2;
            layoutParams.topMargin = topMargin;
            im.setLayoutParams(layoutParams);
    
            startAnimation();
        }
    

    We have to animate three things here, width, height and topMargin (for positioning). So, I declare three variable for initial position of animator and I calculate them on initial layoutsetup. Now we need to animate these three variables simultaneously which is easy.

        private void startAnimation() {
            AnimatorSet animator = new AnimatorSet();
    
            Animator widthAnimator = ObjectAnimator.ofInt(this, "width", width, 200);
            widthAnimator.setInterpolator(new LinearInterpolator());
    
            Animator heightAnimator = ObjectAnimator.ofInt(this, "height", height, 100);
            heightAnimator.setInterpolator(new LinearInterpolator());
    
            Animator marginAnimator = ObjectAnimator.ofInt(this, "topMargin", topMargin, 0);
            marginAnimator.setInterpolator(new LinearInterpolator());
    
            animator.playTogether(widthAnimator, heightAnimator, marginAnimator);
            animator.setDuration(3000);
            animator.start();
        }
    
        public void setWidth(int w) {
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) im.getLayoutParams();
            layoutParams.width = w;
            im.setLayoutParams(layoutParams);
        }
    
        public void setHeight(int h) {
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) im.getLayoutParams();
            layoutParams.height = h;
            im.setLayoutParams(layoutParams);
        }
    
        public void setTopMargin(int m) {
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) im.getLayoutParams();
            layoutParams.topMargin = m;
            im.setLayoutParams(layoutParams);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 06:28

    This is the solution I have ultimately used:

    private void applyAnimation(final View startView, final View finishView, long duration) {
        float scalingFactor = ((float)finishView.getHeight())/((float)startView.getHeight());
    
        ScaleAnimation scaleAnimation =  new ScaleAnimation(1f, scalingFactor,
                                                            1f, scalingFactor,
                                                            Animation.RELATIVE_TO_SELF, 0.5f,
                                                            Animation.RELATIVE_TO_SELF, 0.5f);
    
        scaleAnimation.setDuration(duration);
        scaleAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
    
        Display display = getWindowManager().getDefaultDisplay();
    
        int H;
    
        if(Build.VERSION.SDK_INT >= 13){
            Point size = new Point();
            display.getSize(size);
            H = size.y;
        }
        else{
            H = display.getHeight();
        }
    
        float h = ((float)finishView.getHeight());
    
        float verticalDisplacement = (-(H/2)+(3*h/4));
    
        TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0,
                                                                       Animation.ABSOLUTE, 0,
                                                                       Animation.ABSOLUTE, 0,
                                                                       Animation.ABSOLUTE, verticalDisplacement);
    
        translateAnimation.setDuration(duration);
        translateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
    
        AnimationSet animationSet = new AnimationSet(false);
        animationSet.addAnimation(scaleAnimation);
        animationSet.addAnimation(translateAnimation);
        animationSet.setFillAfter(false);
    
        startView.startAnimation(animationSet);
    }
    

    The key factor here is the value of toYDelta in the TranslateAnimation parameter:

    toYDelta = (-(H/2)+(3*h/4));
    

    Understanding why this works is the main thing. The rest is mostly simple.

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