Подтвердить что ты не робот

Поворот анимации с анимацией

The two states of the image

Что у меня

У меня есть изображение стрелки (например, левое). Когда пользователь нажимает на него, он должен вращаться на 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) {

            }
        });
    }

Проблема

Я вижу, что анимация работает нормально, но при настройке изображения немного мерцает. Может быть, из-за разницы во времени, когда анимация заканчивается и изображение установлено.

Как я могу удалить эту проблему мерцания? У вас есть лучший подход к этому?

4b9b3361

Ответ 1

Во-первых, какова минимальная потребность в SDK? В случае, если он, по крайней мере, Android 3.0, вы можете использовать новую структуру анимации и анимировать свое изображение примерно так:

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

О мерцании: я не стал бы reset исходным изображением ImageView после поворота, я бы просто оставил в оригинале и удостоверился, что анимация вращения заполняется после анимации, оставив изображение вращением. Мерцание, скорее всего, вызвано просмотром ретрансляции/перерисовкой при изменении исходного изображения.

Другие визуальные артефакты (мерцание?) могут быть вызваны тем, что изображение с оригинальным вращением и повернутое статическое изображение могут отличаться в нескольких пикселях.

Ответ 2

Если бы я был вами, я бы использовал ViewPropertyAnimator (доступный из API 12). Его синтаксис более прямой ИМО.
Использование:

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

Ответ 3

Почему вы не используете 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);
            }
        });
    }
}

Ответ 4

Вы можете использовать setFillAfter, если хотите сохранить состояние своей анимации.

Ответ 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
}

Или проще:

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