Search code examples
androidandroid-animationobjectanimator

Scale view to parent layout size


I am trying to scale a view to layout size by using object animator. The view is a LinearLayout. The view does stretch, but not till the screen size in both the directions (i.e X and Y).

Here is the code.

I feel that either the problem is with this:

  1. The formula to calculate how much zoom must be done.

    zoomTillX = screen_width/zoomView_width;
    zoomTillY = screen_height/zoomView_height;
    
  2. Or with the Animation property code that is done in a wrong way.

Please let me know how can I achieve a zoom in.

public class MainActivity extends AppCompatActivity {

    TextView tv;
    double screen_height;
    LinearLayout zoomView;
    double screen_width;
    double zoomTillX;
    double zoomTillY;
    double zoomView_width;
    double zoomView_height;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        tv = (TextView) findViewById(R.id.tv);
        zoomView = (LinearLayout) findViewById(R.id.zoomView);
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        screen_height = (double)dm.heightPixels;
        screen_width = (double)dm.widthPixels;
        zoomView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                zoomView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                zoomView_width = (double)zoomView.getMeasuredWidth();
                zoomView_height =  (double)zoomView.getMeasuredHeight();


            }
        });
        zoomView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


            final  Handler handler =  new Handler(Looper.getMainLooper());

                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        if(zoomView_width > 0 && zoomView_height > 0)
                        {
                            zoomTillX = screen_width/zoomView_width;
                            zoomTillY = screen_height/zoomView_height;

                            Log.d("VIEW GET X IS ",String.valueOf(zoomView.getX()));
                            Log.d("VIEW GET Y IS ",String.valueOf(zoomView.getY()));

                            ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(zoomView, "scaleX", (float)(zoomTillX));
                            ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(zoomView, "scaleY",(float)(zoomTillY));

                            List<Animator> oaList = new ArrayList<Animator>();
                            oaList.add(scaleDownX);
                            oaList.add(scaleDownY);

                            AnimatorSet ani = new AnimatorSet();
                            ani.playTogether(oaList);
                            ani.setDuration(500);
                           ani.start();

                        }else{

                            handler.postDelayed(this,300);
                        }

                    }
                },500);

            }
        });

    }
}

This is how it looks finally.

enter image description here


Solution

  • That can be done via ValueAnimator.

    Having this layout as the content of activity:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
      <View
          android:id="@+id/view"
          android:layout_width="170dp"
          android:layout_height="170dp"
          android:background="#3143ff"/>
    
    </FrameLayout>
    

    And in activity's onCreate():

    
    
        final View view = findViewById(R.id.view);
        final View contentView = findViewById(R.id.content_frame);
    
        contentView.setOnClickListener(v -> {
    
          final int screenWidth = contentView.getWidth();
          final int screenHeight = contentView.getHeight();
    
          ValueAnimator widthAnimator = ValueAnimator.ofInt(view.getWidth(), screenWidth);
          ValueAnimator heightAnimator = ValueAnimator.ofInt(view.getHeight(), screenHeight);
    
          widthAnimator.setDuration(1500);
          heightAnimator.setDuration(1500);
    
          widthAnimator.addUpdateListener(animation -> {
            view.getLayoutParams().width = (int) animation.getAnimatedValue();
            view.requestLayout();
          });
    
          heightAnimator.addUpdateListener(animation -> {
            view.getLayoutParams().height = (int) animation.getAnimatedValue();
            view.requestLayout();
          });
    
          widthAnimator.start();
          heightAnimator.start();
        });
    
    
    

    This will be the result:

    enter image description here


    Transitions API

    We've implemented this animation ourselves. But why won't we let the system take care of building all this animators?

    There's a Transitions API, which will take the heavy lifting for us. All we have to do, is to ask the framework to detect layout changes, create appropriate animators and run the animations.

    So, all the code above can be changed to following, which will result in exactly same output:

    
    
        contentView.setOnClickListener(v -> {
          final int screenWidth = contentView.getWidth();
          final int screenHeight = contentView.getHeight();
    
          // Uncomment this, if you want Transitions API to run default animation
          // TransitionManager.beginDelayedTransition(contentView);
    
          Transition autoTransition = new AutoTransition();
          autoTransition.setDuration(1500);
    
          // With this overload you can control actual transition animation
          TransitionManager.beginDelayedTransition(contentView, autoTransition);
          // After `beginDelayedTransition()` function perform changes to the layout
          // Transitions framework will detect those changes and perform appropriate animations
          view.getLayoutParams().width = screenWidth;
          view.getLayoutParams().height = screenHeight;
          view.requestLayout();
          view.invalidate();
        });