Skip to content Skip to sidebar Skip to footer

Android: Imageview Rotation Animation - Keep Scale Type Fit Center

I have an ImageView that has android:scaleType='fitCenter' Copy

Instead of

 iv.animate().rotationBy(90f).start();

two more update take android:configChanges like that

<activityandroid:name=".youactivity"android:label="@string/app_name"android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        >

android:adjustViewBounds true to imageview

  <ImageView
    android:id="@+id/iv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="fitCenter"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:src="@mipmap/android"/>

Solution 2:

My Solution is not elegant (i am a noob in developing) I hope someone can provide a better solution ....

int h,w;
    Boolean safe=true;

Getting the parameters of imageView is not possible at initialisation of activity To do so please refer to this solutionOR set the dimensions at onClick of a Button Like this

    rotateButton.setOnClickListener(newView.OnClickListener() {
        @OverridepublicvoidonClick(View view) {
            if(imageView.getRotation()/90%2==0){
                h=imageView.getHeight();
                w=imageView.getWidth();

            }
        .
        .//Insert the code Snippet below here 
       }

And the code to be run when we want to rotate ImageView

if(safe)     
imageView.animate().rotationBy(90).scaleX(imageView.getRotation()/90%2==0?(w*1.0f/h):1).scaleY(imageView.getRotation()/90%2==0?(w*1.0f/h):1).setDuration(2000).setInterpolator(newLinearInterpolator()).setListener(newAnimator.AnimatorListener() {
                @OverridepublicvoidonAnimationStart(Animator animation) {
                      safe=false;
                }

                @OverridepublicvoidonAnimationEnd(Animator animation) {
                      safe=true;

                }

                @OverridepublicvoidonAnimationCancel(Animator animation) {

                }

                @OverridepublicvoidonAnimationRepeat(Animator animation) {

                }
            }).start();
        }
    });

This solution is sufficient for the Problem above.Although it will shrink the imageView even if it is not necessary(when height is smaller than Width).If it bothers you,you can add another ternary operator inside scaleX/scaleY.

Solution 3:

To do this follow these steps:

  1. set scaleType to matrix:
<ImageView...android:scaleType="matrix"/>
  1. In onCreate, load image into imageview and set rotate button onClick listener:
imageView.post(new Runnable() {
            @Override
            publicvoidrun() {
                Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.dummy);


           imageView.setImageBitmap(bitmap);

            if (bitmap.getWidth() > 0) {

                float scale = ((float)imageView.getMeasuredWidth())/((float)imageView.getDrawable().getIntrinsicWidth());

                imageView.getLayoutParams().height = (int)(scale * imageView.getDrawable().getIntrinsicHeight());
                imageView.setImageMatrix(scaleMatrix(scale, scale));
            }
        }
    });

And

btnRotate.setOnClickListener(newView.OnClickListener() {
            @OverridepublicvoidonClick(View view) {
              animateImageHeight(imageView,btnRotate);
            }
        });
  1. Add the animateImageHeight method in the activity:

void animateImageHeight(final ImageView imageView, final Button btnRotate){

finalfloatdrawableWidth= imageView.getDrawable().getIntrinsicWidth();
    finalfloatdrawableHeight= imageView.getDrawable().getIntrinsicHeight();
    floatviewWidth= imageView.getMeasuredWidth();
    finalfloatviewHeight= imageView.getMeasuredHeight();
    finalintrotation= imageRotation % 360;
    finalintnewRotation= (rotation + 90);

    finalint newViewHeight;
    finalfloat imageScale;
    finalfloat newImageScale;

    if (rotation==0 || rotation==180)
    {
        imageScale = viewWidth / drawableWidth;
        newImageScale = viewWidth / drawableHeight;
        newViewHeight = (int)(drawableWidth * newImageScale);
    }
    elseif (rotation==90 || rotation==270){
        imageScale = viewWidth / drawableHeight;
        newImageScale = viewWidth / drawableWidth;
        newViewHeight = (int)(drawableHeight * newImageScale);
    }
    else{
        thrownewUnsupportedOperationException("rotation can 0, 90, 180 or 270. ${rotation} is unsupported");
    }


    ValueAnimator animator= ValueAnimator.ofFloat(0f,1f) .setDuration(1000L);



    animator.setInterpolator(newAccelerateDecelerateInterpolator());

    animator.addListener(newAnimator.AnimatorListener() {
        @OverridepublicvoidonAnimationStart(Animator animator) {
            btnRotate.setEnabled(false);
        }

        @OverridepublicvoidonAnimationEnd(Animator animator) {
            imageRotation = newRotation % 360;
            btnRotate.setEnabled(true);
        }

        @OverridepublicvoidonAnimationCancel(Animator animator) {

        }

        @OverridepublicvoidonAnimationRepeat(Animator animator) {

        }
    });

    animator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {
        @OverridepublicvoidonAnimationUpdate(ValueAnimator animation) {
            floatanimVal= (float)animation.getAnimatedValue();
            floatcomplementaryAnimVal=1 - animVal;

            intanimatedHeight=
                    (int)(complementaryAnimVal * viewHeight + animVal * newViewHeight);
            floatanimatedScale=
                    (complementaryAnimVal * imageScale + animVal * newImageScale);
            floatanimatedRotation=
                    (complementaryAnimVal * rotation + animVal * newRotation);


            imageView.getLayoutParams().height=animatedHeight;

            Matrix matrix=
                    rotationMatrix(
                    animatedRotation,
                    drawableWidth / 2,
                    drawableHeight / 2
            );

            matrix.postScale(
                    animatedScale,
                    animatedScale,
                    drawableWidth / 2,
                    drawableHeight / 2);
            matrix.postTranslate(-(drawableWidth - imageView.getMeasuredWidth())/2, -(drawableHeight - imageView.getMeasuredHeight())/2);

            imageView.setImageMatrix(matrix);

            imageView.requestLayout();
        }
    });

    animator.start();
}

You can find the kotlin version and the complete demonstration here.

Solution 4:

try:

<?xml version="1.0" encoding="utf-8"?><layout><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid:id="@+id/image"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/pic"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout></layout>
privatelateinitvar binding: ActivityMainBinding
    privatevar scale = 1FoverridefunonCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        //Change to your own calculation logic to calculate the zoom factorval outMetrics = DisplayMetrics()
        windowManager.getDefaultDisplay().getRealMetrics(outMetrics)
        val w = outMetrics.widthPixels
        val h = outMetrics.heightPixels
        scale = if (w > h) w.toFloat() / h.toFloat() else h.toFloat() / w.toFloat()
        binding.image.scaleX = scale
        binding.image.scaleY = scale
    }

    funset() {
        sfRotation = (sfRotation + 90) % 360
        Log.d(">>>sfRotation", sfRotation.toString())
        Log.d(">>>hwrotation", hwRotation.toString())
        binding.image.rotation = sfRotation.toFloat()
        binding.image.scaleX = scale
        binding.image.scaleY = scale
    }

Post a Comment for "Android: Imageview Rotation Animation - Keep Scale Type Fit Center"