【问题标题】:Rotate an Imagewith Animation使用动画旋转图像
【发布时间】:2015-07-24 10:07:04
【问题描述】:

我有什么

我有一个箭头图像(如左图)。当用户点击它时,它应该会随着动画旋转 180 度,并且应该看起来像正确的。

我做了什么

private void rotate(float degree, final int toggleV) {

        final RotateAnimation rotateAnim = new RotateAnimation(0.0f, degree,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);

        rotateAnim.setDuration(500);
        toggle.startAnimation(rotateAnim);
        rotateAnim.setAnimationListener(new Animation.AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {


                if (toggleV == 1)
                    toggle.setImageResource(R.drawable.toggle_up);
                else
                    toggle.setImageResource(R.drawable.toggle_down);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

问题

我看到动画效果很好,但是在设置图像时有一点闪烁。可能是因为动画结束和图片设置的时间差。

如何消除此闪烁问题?您有更好的方法来做到这一点吗?

【问题讨论】:

标签: android android-animation android-imageview image-rotation


【解决方案1】:

首先,您对 SDK 的最低要求是多少?如果它至少是 Android 3.0,您可以使用更新的动画框架,并使用以下内容为您的 Image 设置动画:

imageView.animate().rotation(180).start();

关于闪烁:我不会在旋转后重置 ImageView 的源图像,我只是留在原始图像中并确保在动画之后填充旋转动画,使图像旋转。闪烁很可能是由视图在更改源图像时重新布局/重绘引起的。

可能会导致更多的视觉伪影(闪烁?),因为原始旋转图像和旋转后的静态图像可能在几个像素上有所不同。

【讨论】:

  • 当我按下 ImageView 时它只会旋转一次。但是在我再次按下它之后它应该再次旋转等等。但这不会发生。有什么想法吗?
  • 好吧,如果您使用我提供的代码示例,此代码专门告诉查看“旋转到 180 度”。因此,如果它已经旋转到 180 度,那么它将什么也不做。在点击监听器中,您可以例如检查视图的当前旋转(.getRotation),如果它不是 0,则以类似的方式将其旋转回 0。
  • 是的,我就是这样做的,它也有效。现在,有没有办法在旋转到 0 时控制动画方向。我的意思是,它正在向特定方向旋转,但我想以相反的方式进行。
  • 我猜你想继续以相同的方向旋转视图,而不是将 CW 旋转到 180 并将 CCW 旋转回 0。你可以例如设置并不断增加旋转目标,即 X * 180 度,基于用户交互时视图的旋转(可能发生在动画中间)。例如。如果我们需要旋转以点击视图:单击 -> 旋转到 180 -> 单击 -> 旋转到 2 x 180 -> ...你明白了。
  • 转到:imageView.animate().rotation(0).rotation(180).start(); 返回:imageView.animate().rotation(180).rotation(0).start();
【解决方案2】:

如果我是你,我会使用 ViewPropertyAnimator(可从 API 12 获得)。它的语法更直接 IMO。
用法是:

toggle.animate().rotation(0.5f);

【讨论】:

  • 同上一个答案。但是如何确保每次按下图像时都会发生旋转?目前它只发生一次。
  • 使用“rotateBy”。咨询 API,它将成为你最喜欢的动画工具
  • 谢谢。有什么办法可以控制旋转方向吗?
  • 我会尝试一个负值。但我不确定
【解决方案3】:

如果你想保持动画的状态,你可以使用setFillAfter

【讨论】:

  • 没有解释,也没有任何上下文。
【解决方案4】:

你为什么不使用RotateAnimation?

在 res 中创建一个名为 anim 的文件夹,并在 res/anim 中创建一个名为 rotator.xml 的文件。

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="400"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360"/>

这里将在 4000 毫秒(4 秒)内完成一个完整的旋转。现在将要旋转的 PNG 图像添加到可绘制文件夹中。然后打开res/main.xml,去掉布局中默认的textView后,在布局中添加一个ImageView和Button。将 ImageView 的 src 属性设置为添加图像的文件名,例如 android:src=”@drawable/myimg” 好的,让我们编辑主类。在按钮的 onClick() 中,添加运行动画所需的代码。检查以下代码。

public class AnimationActivity extends Activity {

    public ImageView  myImage ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        myImage = (ImageView)findViewById(R.id.imageView1);
        final Animation myRotation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotator);
        ((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener()    {
            @Override
            public void onClick(View arg0) {
                myImage.startAnimation(myRotation);
            }
        });
    }
}

【讨论】:

    【解决方案5】:

    验证码:(你可以按照我的解决方案)

    imageView.setImageResource(R.drawable.ic_arrow_up);
    
    boolean up = true;
    
    if (!up) { 
        up = true; 
        imageView.startAnimation(animate(up)); 
    } else { 
        up = false; 
        imageView.startAnimation(animate(up)); 
    }
    
    private Animation animate(boolean up) {
        Animation anim = AnimationUtils.loadAnimation(this, up ? R.anim.rotate_up : R.anim.rotate_down);
        anim.setInterpolator(new LinearInterpolator()); // for smooth animation
        return anim;
    }
    

    可绘制/ic_arrow_up.xml

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:fillColor="#3d3d3d"
            android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
    </vector>
    

    动画/rotate_up.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        android:fillEnabled="true">
        <rotate
            android:duration="200"
            android:fromDegrees="-180"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="0" />
    </set>
    

    动画/rotate_down.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        android:fillEnabled="true">
        <rotate
            android:duration="200"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="180" />
    </set>
    

    我使用了那个代码。因为这样会保存动画状态:

    android:fillAfter="true"
    android:fillEnabled="true"
    

    【讨论】:

      【解决方案6】:

      如果要将图像顺时针旋转 180 度。

      private var isExpanded = true
      
      private fun rotateImage(view: View) {
          val startAngle = if (isExpanded) 0f else 180f
          ObjectAnimator.ofFloat(view, View.ROTATION, startAngle, startAngle + 180f).apply {
              duration = 300
              interpolator = LinearInterpolator()
              start()
          }
          isExpanded = !isExpanded
      }
      

      或更简单地说(如@Alex.F 所写):

      view.animate().setDuration(300).rotationBy(180f).start()
      

      请注意,如果您过于频繁地多次旋转图像,它不会停止在 0 - 180 - 360 位置。因为如果你在前一个动画完成之前开始一个新的动画,它会改变一个角度。

      因此,在接受的答案中写入了更好的方法。它不依赖于当前的动画状态。

      private var angle = 0f
      
      angle += 180f
      view.animate().setDuration(300).rotation(angle).start()
      

      【讨论】:

        【解决方案7】:
        img_view.animate().rotation(360.0f).setDuration(1000);
        

        【讨论】:

          【解决方案8】:

          科特林:

          仅使用一个ImageView 即可制作展开和折叠动画的流畅方式:

          class MainActivity : AppCompatActivity() {
          
              var isExpanded = true
          
              override fun onCreate(savedInstanceState: Bundle?) {
                  super.onCreate(savedInstanceState)
                  setContentView(R.layout.activity_main)
          
          
                  val imageView = findViewById<ImageView>(R.id.image_header_toggle)
          
                  imageView.setOnClickListener {
                      if (!isExpanded) {
                          imageView.animate().apply {
                          duration = 500
                          rotation(180f)
                          isExpanded = true}
                      }else{
                          imageView.animate().apply {
                          duration = 500
                          rotation(0f)
                          isExpanded = false}
                      }
                  }
              }
          }
          

          【讨论】:

            【解决方案9】:

            科特林

            Kotlin 中非常高效流畅的 ImageView 旋转动画。

            旋转动画后,ImageView 被保留,不需要动画监听器。

            imageView.animate().rotation(angle).setDuration(700).setInterpolator(AccelerateDecelerateInterpolator()).start()
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-04-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多