Повернуть изображение с анимацией
Что я имею
У меня есть изображение стрелки (как на левом). Когда пользователь нажимает на него, он должен поворачиваться на 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) {
}
});
}
Эта проблема
Я вижу, что анимация работает нормально, но при настройке изображения наблюдается небольшое мерцание. Может быть из-за разницы во времени, когда анимация заканчивается и изображение установлено.
Как я могу удалить эту проблему мерцания? Есть ли у вас лучший подход для этого?
9 ответов
Прежде всего, какое минимальное требование к SDK? В случае, если это хотя бы Android 3.0, вы можете использовать более новую инфраструктуру анимации и анимировать свое изображение примерно так:
imageView.animate().rotation(180).start();
О мерцании: я бы не стал сбрасывать исходное изображение ImageView после поворота, я бы просто оставил в оригинале и убедился, что анимация поворота заполняется после анимации, оставляя изображение повернутым. Мерцание, скорее всего, вызвано ретрансляцией / перерисовкой View при смене исходного изображения.
Дополнительные визуальные артефакты (мерцание?) Могут быть вызваны тем, что исходное повернутое изображение и повернутое статическое изображение могут отличаться на несколько пикселей.
На вашем месте я бы использовал ViewPropertyAnimator
(доступно из API 12). Его синтаксис более понятен IMO.
Использование будет:
toggle.animate().rotation(0.5f);
Проверенный код: (Вы можете следовать моему решению)
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"
Ты можешь использовать setFillAfter
если вы хотите сохранить состояние вашей анимации.
Почему вы не используете RotateAnimation?
создайте папку с именем anim в res и файл с именем rotator.xml внутри res/anim.
<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 в макет. Установите свойство src ImageView в качестве имени файла добавляемого изображения, например, 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);
}
});
}
}
КОТЛИН
очень эффективная и плавная анимация вращения ImageView в Kotlin.
После анимации вращения ImageView сохраняется без прослушивателя анимации.
imageView.animate().rotation(angle).setDuration(700).setInterpolator(AccelerateDecelerateInterpolator()).start()
Если вы хотите повернуть изображение на 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()
КОТЛИН:
Плавный способ сделать анимацию расширения и свертывания с помощью только одного
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}
}
}
}
}