【问题标题】:Android: ImageView rotation animation - keep scale type fit centerAndroid:ImageView 旋转动画 - 保持比例类型适合中心
【发布时间】:2017-01-20 20:23:48
【问题描述】:

我有一个具有android:scaleType="fitCenter" 的 ImageView

<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>

看起来像这样:

当按钮被点击时,我会应用一个旋转动画:

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();
            }
        });
    }
}

现在看起来像这样:

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

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

【问题讨论】:

  • 第一次在imageview上设置图片时,根据设备宽度进行缩放,这样旋转图片时图片不会被裁剪。
  • 我需要图像在每次旋转/方向时填充整个宽度。
  • 好的。然后在旋转图像之前对其进行缩放。
  • 我认为你需要使用 graphics.Matrix;。例子。第一次设置 ImageView 后,从该 ImageView 获取矩阵,旋转它然后再次设置。
  • @lukle 你有没有找到任何解决方案我在旋转ImageView 时遇到同样的问题,它的图像正在裁剪我正在使用fitXY

标签: android animation rotation


【解决方案1】:

用过这个

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"/>

【讨论】:

  • 遇到同样的问题
【解决方案2】:

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

    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中添加另一个三元运算符。

【讨论】:

    【解决方案3】:

    要做到这一点,请按以下步骤操作:

    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. 在activity中添加animateImageHeight方法:

    void animateImageHeight(final ImageView imageView, final Button 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

    【讨论】:

      【解决方案4】:

      尝试:

      <?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
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多