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);
}
});
Итак, в основном, я раздуваю представление под ним. Затем я анимирую вид сверху слева. Как только он выходит из экрана и анимация завершена, он возвращается обратно.
Ответы
Ответ 1
Анимация работает как ожидалось. Просто потому, что вы анимировали что-то, это не значит, что вы действительно переместили его. Анимация влияет только на рисованные пиксели во время самой анимации, а не на конфигурацию виджетов.
Вам нужно добавить AnimationListener
и в методе onAnimationEnd()
сделать что-то, что делает ваш перенос постоянным (например, удаляет верхний вид из его родительского элемента, помечает вид сверху как имеющий видимость GONE
).
Ответ 2
Наконец-то появился способ работать, правильный способ сделать это: 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-axis, top - 0, потому что мы не анимировали ось y, теперь мы в праве сделали someView.getWidth() + 150
, в основном, мы получили ширину нашего представления и добавили 150, потому что мы слева теперь переходим к 150 x-axis, чтобы сделать ширину просмотра исходной, а нижняя равна высоте нашего представления.
Надеюсь, вы поняли концепцию перевода, и все еще у вас есть вопросы, которые вы можете задать сразу в разделе комментариев, я с удовольствием помогу:)
РЕДАКТИРОВАТЬ Не используйте метод layout()
, поскольку он может быть вызван инфраструктурой, когда когда-либо вид недействителен и ваши изменения не будут выдаваться, используйте LayoutParams
, чтобы установить параметры макета в соответствии с к вашему требованию
Ответ 3
Я могу немного опоздать с ответом, но у меня есть решение для этого:
Просто добавьте android:fillAfter="true"
в ваш xml
Ответ 4
Вы можете использовать
fillAfter=true
fillEnabled=true
ваше представление будет не в reset в исходное положение, но если у вас есть какие-то кнопки или что-то еще в вашем представлении, их позиция не изменится.
Вы должны использовать 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;
С уважением Айк
Ответ 5
Вам нужно добавить эту команду:
final Animation animSlideLeft = new TranslateAnimation(0, -80, 0,-350, 0, 0, 0, 0);
animSlideLeft.setFillAfter(true);
Ответ 6
Я пошел на тот же вопрос и решил его с установкой marginLeft на OnAnimationEnd()..
MarginLayoutParams params = (MarginLayoutParams) this.getLayoutParams();
params.setMargins(this.getWidth()*position, 0,0,0);
this.setLayoutParams(params);
Ответ 7
Эта проблема беспокоит более недели.
И Мухаммад ответил мне на первый план, чтобы решить его.
Я использовал разметку для реализации боковых меню с анимацией.
"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();
}
}
Ответ 8
Используйте вспомогательные методы ниже, чтобы легко оживить ваш вид. Затем вы можете анимировать и сбросить после завершения, как это:
// 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();
}
}
}
});
}