Android: позиция анимации сбрасывается после завершения - PullRequest
61 голосов
/ 07 октября 2010

Я использую определенную в xml анимацию, чтобы сдвинуть вид с экрана. Проблема в том, что, как только анимация завершается, она сбрасывается в исходное положение. Мне нужно знать, как это исправить. Вот XML:

<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
   <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="500"/></set>

Вот Java, которую я использую для его вызова:

    homeScrn = (View)findViewById(R.id.homescreen);
    slideLeftOut = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);

    //Set Click Listeners For Menu
    btnHelp.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            LayoutInflater.from(getApplicationContext()).inflate(R.layout.help, (ViewGroup)findViewById(R.id.subpage), true);
            homeScrn.startAnimation(slideLeftOut);
        }
    });

Итак, в основном, я раздуваю взгляд под ним. Затем я оживляю вид сверху слева. Как только он выходит за пределы экрана и анимация заканчивается, он сбрасывает свою позицию назад.

Ответы [ 8 ]

105 голосов
/ 04 апреля 2013

Наконец-то есть способ обойти это, правильный способ сделать это - setFillAfter(true),

, если вы хотите определить свою анимацию в xml, вам следует сделать что-то вродеэто

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/decelerate_interpolator"
     android:fillAfter="true">

    <translate 
        android:fromXDelta="0%"
        android:toXDelta="-100%"
        android:duration="1000"/>

</set>

вы можете видеть, что я определил filterAfter="true" в теге set, если вы попытаетесь определить его в теге translate, он не будет работать,может быть ошибка в структуре !!

, а затем в коде

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_out);
someView.startAnimation(anim);

ИЛИ

TranslateAnimation animation = new TranslateAnimation(-90, 150, 0, 0);

animation.setFillAfter(true);

animation.setDuration(1800);

someView.startAnimation(animation);

тогда это, безусловно, будет работать !!

Теперь это немного сложно, кажется, что представление фактически перемещается в новую позицию, но фактически пиксели представления перемещаются, т.е. ваш вид фактически находится в своем начальном положении.положение, но не видимое, вы можете проверить его, если у вас есть какая-то кнопка или кликабельный вид (в моем случае в макете), чтобы исправить то, что вам придется вручную переместить ваш вид / макет в новое положение

public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)

new TranslateAnimation(-90, 150, 0, 0);

Теперь, когда мы видим, что наша анимация будет начинаться с -90 по оси X до 150 по оси X

, то, что мы делаем, установлено

someView.setAnimationListener(this);

и в

public void onAnimationEnd(Animation animation)
{
   someView.layout(150, 0, someView.getWidth() + 150, someView.getHeight());
}

теперь позвольте мне объяснить, public void layout (int left, int top, int right, int botton)

он перемещает ваш макет в новую позицию, первый аргумент определяет левый, который у нас равен 150 , потому что анимация перевода оживила наш вид на 150 по оси x , top равен 0 , потому что у нас нет анимированной оси y, теперь справа мы сделали someView.getWidth() + 150в основном мы получаем ширину нашего вида и добавляем 150 , потому что теперь мы слева направо перемещаемся к 150 по оси x , чтобы сделать ширину вида исходной, а дно равновысота нашего взгляда.

Я надеюсь, что вы, люди, теперь поняли концепцию перевода, и, тем не менее, у вас есть какие-либо вопросы, которые вы можете задать сразу в разделе комментариев, я рад помочь:)

РЕДАКТИРОВАТЬ Не используйте метод layout(), так как он может вызываться платформой, когда просмотр недействителен и ваши изменения не будут сохраняться, используйте LayoutParams, чтобы установить параметры макета в соответствии с вашими требованиями

81 голосов
/ 07 октября 2010

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

Вам нужно добавить AnimationListener, а в методе onAnimationEnd() сделать что-то, что сделает ваш ход постоянным (например, удаляет вид сверху из его родителя, помечает вид сверху как видимость GONE ).

24 голосов
/ 26 июля 2011

Возможно, я немного опоздал с ответом, но у меня есть решение для этого:

Просто добавьте android:fillAfter="true" в свой xml

9 голосов
/ 05 декабря 2012

Вы можете использовать

fillAfter=true
fillEnabled=true

ваш вид не будет сброшен в исходное положение, но если у вас есть какие-то кнопки или что-то еще, ваше положение не изменится.

Вы должны использовать ObjectAnimator, он работает с уровня API 11.Это меняет позицию просмотра автоматически,

вот пример

ObjectAnimator objectAnimator= ObjectAnimator.ofFloat(mContent_container, "translationX", startX, endX);
objectAnimator.setDuration(1000);
objectAnimator.start();

Спасибо JUL за его ответ

Если ваше приложение не найдено object animatorизменить уровень API с Project -> properties -> Android, чем import android.animation.ObjectAnimator;

С уважением Айк

7 голосов
/ 27 марта 2016

Вам необходимо добавить эту команду:

final Animation animSlideLeft = new TranslateAnimation(0, -80, 0,-350, 0, 0, 0, 0);
animSlideLeft.setFillAfter(true);
1 голос
/ 18 июля 2013

Эта проблема беспокоила больше недели.И ответ Мухаммеда указал мне простой способ решить эту проблему.

Я использовал разметку для реализации боковых меню с анимацией."view.layout не будет постоянным. Вы должны использовать LayoutParams, который будет постоянным."

Вот мое решение: (Используйте тип LayoutParameter, который зависит от макета вашего родителя):

@Override
public void onAnimationEnd(Animation animation) {
FrameLayout.LayoutParams layoutParams=new FrameLayout.LayoutParams(screenWidth, screenHeight);
layoutParams.setMargins((int) -(screenWidth * RATE), 0,
            (int) (screenWidth - screenWidth * RATE), screenHeight);
    for(View v:views) {

        v.setLayoutParams(layoutParams);
        //v.layout((int) -(screenWidth * RATE), 0, (int) (screenWidth - screenWidth * RATE), screenHeight);
        v.clearAnimation();
    }
}
1 голос
/ 01 июня 2012

Я пошел на тот же вопрос и решил его, установив marginLeft в OnAnimationEnd () ..

MarginLayoutParams params = (MarginLayoutParams) this.getLayoutParams(); params.setMargins(this.getWidth()*position, 0,0,0); this.setLayoutParams(params);

0 голосов
/ 10 июля 2018

Используйте вспомогательные методы ниже, чтобы легко анимировать ваш вид. Затем вы можете оживить и сбросить после завершения следующим образом:

// Animate the view:

fly(
  view1,
  (float) 0,
  (float) 0,
  (float) 0,
  (float) 1000,
  250,
  null,
  null,
  () -> {

    // Return the view to initial position on animation end:  

    fly(
      view1,
      (float) 0,
      (float) 0,
      (float) 0,
      (float) 0,
      0);

    return null;
  });

Вспомогательные методы:

/**
 * Translation of a view.
 */
public static void fly(
  View view,
  float fromXDelta,
  float toXDelta,
  float fromYDelta,
  float toYDelta,
  int duration) {

  fly(
    view,
    fromXDelta,
    toXDelta,
    fromYDelta,
    toYDelta,
    duration,
    null,
    null,
    null);
}

/**
 * Translation of a view with handlers.
 *
 * @param view       A view to animate.
 * @param fromXDelta Amount to shift by X axis for start position.
 * @param toXDelta   Amount to shift by X axis for end position.
 * @param fromYDelta Amount to shift by Y axis for start position.
 * @param toYDelta   Amount to shift by Y axis for end position.
 * @param duration   Animation duration.
 * @param start      On animation start. Otherwise NULL.
 * @param repeat     On animation repeat. Otherwise NULL.
 * @param end        On animation end. Otherwise NULL.
 */
public static void fly(
  View view,
  float fromXDelta,
  float toXDelta,
  float fromYDelta,
  float toYDelta,
  int duration,
  Callable start,
  Callable repeat,
  Callable end) {

  Animation animation;

  animation =
    new TranslateAnimation(
      fromXDelta,
      toXDelta,
      fromYDelta,
      toYDelta);

  animation.setDuration(
    duration);

  animation.setInterpolator(
    new DecelerateInterpolator());

  animation.setFillAfter(true);

  view.startAnimation(
    animation);

  animation.setAnimationListener(new AnimationListener() {

    @Override
    public void onAnimationStart(Animation animation) {

      if (start != null) {
        try {

          start.call();

        } catch (Exception e) {
          e.printStackTrace();
        }
      }

    }

    @Override
    public void onAnimationEnd(Animation animation) {

      if (end != null) {
        try {

          end.call();

        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    @Override
    public void onAnimationRepeat(
      Animation animation) {

      if (repeat != null) {
        try {

          repeat.call();

        } catch (Exception e) {
          e.printStackTrace();
        }
      }  
    }
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...