旋转带动画的图像
Rotate an Imagewith Animation
我有什么
我有一个箭头图像(如左图)。当用户点击它时,它应该旋转 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) {
}
});
}
问题
我看到动画效果很好,但在设置图像时有一点闪烁。可能是因为动画结束和图片设置的时间差
如何解决这个闪烁问题?你有更好的方法吗?
如果您想保留动画状态,可以使用 setFillAfter
。
你为什么不用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"/>
这里一个完整的旋转将在4000ms(4秒)内完成。现在将要旋转的 PNG 图像添加到可绘制文件夹中。然后打开res/main.xml,去掉布局中默认的textView后,在布局中添加一个ImageView和Button。将 ImageView 的 src 属性 设置为添加图像的文件名,例如 android:src=”@drawable/myimg” 好的,让我们编辑主 class。在按钮的 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);
}
});
}
}
如果我是你,我会使用 ViewPropertyAnimator
(可从 API 12 获得)。 IMO 的语法更直接。
用法为:
toggle.animate().rotation(0.5f);
首先,您对 SDK 的最低要求是什么?如果它至少是 Android 3.0,您可以使用较新的动画框架,并使用如下内容为您的图像制作动画:
imageView.animate().rotation(180).start();
关于闪烁:我不会在旋转后重置 ImageView 的源图像,我只是保留原始图像并确保旋转动画在动画之后填充,使图像旋转。闪烁很可能是由更改源图像时视图的 relayout/redraw 引起的。
可能会导致进一步的视觉伪影(闪烁?),因为原始旋转图像和旋转后的静态图像可能存在几个像素的差异。
验证码:(您可以按照我的解决方案)
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;
}
drawable/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>
anim/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>
anim/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"
如果要将图片顺时针旋转 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()
KOTLIN:
一种仅用一个即可制作展开和折叠动画的流畅方法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}
}
}
}
}
img_view.animate().rotation(360.0f).setDuration(1000);
KOTLIN
ImageView 在 Kotlin.
中非常高效和流畅的旋转动画
旋转动画后,ImageView被保留,不需要动画监听器。
imageView.animate().rotation(angle).setDuration(700).setInterpolator(AccelerateDecelerateInterpolator()).start()
我有什么
我有一个箭头图像(如左图)。当用户点击它时,它应该旋转 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) {
}
});
}
问题
我看到动画效果很好,但在设置图像时有一点闪烁。可能是因为动画结束和图片设置的时间差
如何解决这个闪烁问题?你有更好的方法吗?
如果您想保留动画状态,可以使用 setFillAfter
。
你为什么不用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"/>
这里一个完整的旋转将在4000ms(4秒)内完成。现在将要旋转的 PNG 图像添加到可绘制文件夹中。然后打开res/main.xml,去掉布局中默认的textView后,在布局中添加一个ImageView和Button。将 ImageView 的 src 属性 设置为添加图像的文件名,例如 android:src=”@drawable/myimg” 好的,让我们编辑主 class。在按钮的 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);
}
});
}
}
如果我是你,我会使用 ViewPropertyAnimator
(可从 API 12 获得)。 IMO 的语法更直接。
用法为:
toggle.animate().rotation(0.5f);
首先,您对 SDK 的最低要求是什么?如果它至少是 Android 3.0,您可以使用较新的动画框架,并使用如下内容为您的图像制作动画:
imageView.animate().rotation(180).start();
关于闪烁:我不会在旋转后重置 ImageView 的源图像,我只是保留原始图像并确保旋转动画在动画之后填充,使图像旋转。闪烁很可能是由更改源图像时视图的 relayout/redraw 引起的。
可能会导致进一步的视觉伪影(闪烁?),因为原始旋转图像和旋转后的静态图像可能存在几个像素的差异。
验证码:(您可以按照我的解决方案)
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;
}
drawable/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>
anim/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>
anim/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"
如果要将图片顺时针旋转 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()
KOTLIN:
一种仅用一个即可制作展开和折叠动画的流畅方法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}
}
}
}
}
img_view.animate().rotation(360.0f).setDuration(1000);
KOTLIN
ImageView 在 Kotlin.
中非常高效和流畅的旋转动画旋转动画后,ImageView被保留,不需要动画监听器。
imageView.animate().rotation(angle).setDuration(700).setInterpolator(AccelerateDecelerateInterpolator()).start()