Android:ImageView旋转动画 - 保持比例类型适合中心

时间:2016-09-13 09:27:39

标签: android animation rotation

我的ImageView有android:scaleType="fitCenter"

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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="at.lukle.picturerotation.MainActivity">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:src="@drawable/android"/>

    <Button
        android:id="@+id/btn_rotate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="rotate"/>

</RelativeLayout>

看起来像这样:

Normal

单击按钮时,我应用旋转动画:

public class MainActivity extends AppCompatActivity {

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

        Button btnRotate = (Button) findViewById(R.id.btn_rotate);
        final ImageView iv = (ImageView) findViewById(R.id.iv);

        btnRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                iv.animate().rotationBy(90f).start();
            }
        });
    }
}

现在看起来像这样:Rotated

图像在侧面被切割。我希望scaleType也应用于旋转的图像,这样ImageView不仅可以旋转,还可以缩放以适应宽度。我想我也需要一个缩放动画,但我不知道该怎么做。

我也尝试使用iv.setRotation(90),但我在这里遇到同样的问题......

4 个答案:

答案 0 :(得分:0)

  

使用此

iv.setRotation(iv.getRotation() + 90);
  

而不是

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

另外两次更新android:configChanges就像那样

 <activity
        android: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"/>

答案 1 :(得分:0)

我的解决方案不优雅(我是开发中的菜鸟) 我希望有人能提供更好的解决方案......

    int h,w;
    Boolean safe=true;

在初始化活动时无法获取imageView的参数 为此,请参阅此solution 在按钮的onClick上设置尺寸

    rotateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(imageView.getRotation()/90%2==0){
                h=imageView.getHeight();
                w=imageView.getWidth();

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

当我们想要旋转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(new LinearInterpolator()).setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                      safe=false;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                      safe=true;

                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

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

这个解决方案对于上面的问题已经足够了。虽然它会缩小imageView,即使它没有必要(当高度小于宽度时)。如果它困扰你,你可以在scaleX / scaleY中添加另一个三元运算符。 / p>

答案 2 :(得分:0)

为此,请按照以下步骤操作:

  1. scaleType设置为矩阵:
 <ImageView ...
    android:scaleType="matrix"/>
  1. 在onCreate中,将图像加载到imageview并设置旋转按钮onClick侦听器:
imageView.post(new Runnable() {
            @Override
            public void run() {
                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));
            }
        }
    });

btnRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
              animateImageHeight(imageView,btnRotate);
            }
        });
  1. 在活动中添加animateImageHeight方法:

void animateImageHeight(最终ImageView imageView,最终按钮btnRotate){

    final float drawableWidth = imageView.getDrawable().getIntrinsicWidth();
    final float drawableHeight = imageView.getDrawable().getIntrinsicHeight();
    float viewWidth = imageView.getMeasuredWidth();
    final float viewHeight = imageView.getMeasuredHeight();
    final int rotation = imageRotation % 360;
    final int newRotation = (rotation + 90);

    final int newViewHeight;
    final float imageScale;
    final float newImageScale;

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


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



    animator.setInterpolator(new AccelerateDecelerateInterpolator());

    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
            btnRotate.setEnabled(false);
        }

        @Override
        public void onAnimationEnd(Animator animator) {
            imageRotation = newRotation % 360;
            btnRotate.setEnabled(true);
        }

        @Override
        public void onAnimationCancel(Animator animator) {

        }

        @Override
        public void onAnimationRepeat(Animator animator) {

        }
    });

    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float animVal = (float)animation.getAnimatedValue();
            float complementaryAnimVal = 1 - animVal;

            int animatedHeight =
                    (int)(complementaryAnimVal * viewHeight + animVal * newViewHeight);
            float animatedScale =
                    (complementaryAnimVal * imageScale + animVal * newImageScale);
            float animatedRotation =
                    (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();
}

您可以找到kotlin版本和完整的演示here

答案 3 :(得分:0)

试试:

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns: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">

        <ImageView
            android: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>
    private lateinit var binding: ActivityMainBinding
    private var scale = 1F
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        //Change to your own calculation logic to calculate the zoom factor
        val 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
    }

    fun set() {
        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
    }