Android: Анимация Положение Сбрасывается После Завершения
Я использую 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 ответов:
анимация работает, как ожидалось. Просто потому, что вы анимировали что-то, не означает, что вы на самом деле переместили его. Анимация влияет только на нарисованные пиксели во время самой анимации, а не на конфигурацию виджетов.
вам нужно добавить
AnimationListener
и вonAnimationEnd()
метод, сделать что-то, что делает ваш ход постоянным (например, удаляет вид сверху от своего родителя, отмечает вид сверху как имеющий видимостьGONE
).
наконец-то есть способ обойти,правильный способ сделать это
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-axis до 150 x-axis
Итак, что мы делаем, это установить
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-axis,top - 0 потому что мы не анимировали ось y, Теперь в правом мы сделали
someView.getWidth() + 150
в основном мы получаем ширину нашего взгляда и добавил 150 потому что мы наши левые теперь перейти к 150 x-axis чтобы ширина вида была равна его исходной единице, а дно равно высоте нашего вида.я надеюсь, что вы теперь поняли концепцию перевода, и все же у вас есть какие-либо вопросы, которые вы можете задать сразу в разделе комментариев,я с удовольствием помогу :)
EDIT не используйте
layout()
метод как он может быть вызван фреймворком, когда когда-либо просмотр будет признан недействительным, и ваши изменения не будут присутствовать, используйтеLayoutParams
для того чтобы установить ваши параметры плана согласно вашему требованию
Я может быть немного поздно с ответом, но у меня есть решение для этого:
просто добавить
android:fillAfter=true
в XML
можно использовать
fillAfter=true fillEnabled=true
ваш вид не будет сброшен в исходное положение , но если у вас есть некоторые кнопки или что-то еще в вашем представлении, их положение не изменится.
вы должны использовать
ObjectAnimator
, он работает от уровня API 11 . Он меняет положение просмотра автоматически,вот пример
ObjectAnimator objectAnimator= ObjectAnimator.ofFloat(mContent_container, "translationX", startX, endX); objectAnimator.setDuration(1000); objectAnimator.start();
спасибо Джул за его ответ
если ваше приложение не найдено
object animator
, измените уровень API сProject -> properties -> Android
, чемimport android.animation.ObjectAnimator;
С Уважением Гайк
вам нужно добавить команду:
final Animation animSlideLeft = new TranslateAnimation(0, -80, 0,-350, 0, 0, 0, 0); animSlideLeft.setFillAfter(true);
Я пошел к тому же вопросу и решил его с установкой marginLeft в OnAnimationEnd()..
MarginLayoutParams params = (MarginLayoutParams) this.getLayoutParams(); params.setMargins(this.getWidth()*position, 0,0,0); this.setLayoutParams(params);
эта проблема беспокоит уже больше недели. И ответ Мухаммеда указал мне прямой путь к его решению.
я использовал sever 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(); } }
использовать вспомогательные методы ниже чтобы легко анимировать Ваше мнение. Тогда вы можете анимация и сброс после завершения такой:
// 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(); } } } }); }