Анимация удаления элемента ListView
Я пытаюсь анимировать удаление элемента ListView, используя это:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, final View view, final int i, long l) {
view.animate().setDuration(500).x(-view.getWidth()).alpha(0f);
adapter.remove(tasks.get(i));
adapter.notifyDataSetChanged();
}
});
Это не работает. Я в основном следовал совету 4-го ответа сверху этого поста:
Как анимировать добавление или удаление строк Android ListView
Тем не менее, есть некоторые забавные вещи рисования происходит, или переработка, или что-то, потому что в то время как анимация происходит, элемент ниже того, который соскальзывает с экрана также удаляется по какой-то причине. Ответ что вопрос asker в конечном итоге помечен как правильный, К сожалению, RTFM по отношению ко всему источнику Android. Я посмотрел там, и я не могу найти уведомления выпадающие в JellyBean, который я пытаюсь эмулировать.
ТИА.
Джон
4 ответов:
Я только что нашел прекрасное решение: https://github.com/paraches/ListViewCellDeleteAnimation
Вот видео: http://www.youtube.com/watch?v=bOl5MIti7n0
Большое спасибо 'paraches';)
Edit
Начиная с версии Android 22.0.0 новый
android.support.v7.widget.RecyclerViewдоступен в качестве преемникаListView. Стандартные анимации добавления/удаления/обновления доступны из коробки. Анимация виджета также легко настраивается (несколько пользовательских анимация ).Я настоятельно рекомендую переключиться с
ListViewнаRecyclerView, Если вам нужна анимация пользовательских элементов.
Идея: я запускаю анимацию, когда пользователь выбирает строку. Когда анимация завершена, я удаляю строку из адаптера.Следующий код анимирует выбранную строку:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listView = (ListView) findViewById(R.id.listView1); final ArrayList<String> values = new ArrayList<String>(); values.add("Android"); values.add("iPhone"); values.add("WindowsMobile"); values.add("Blackberry"); values.add("Windows7"); final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); listView.setAdapter(adapter); final Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_out); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { adapter.remove(adapter.getItem(selectedRow)); adapter.notifyDataSetChanged(); } }); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(getApplicationContext(), " " + values.get(position), Toast.LENGTH_LONG).show(); view.startAnimation(animation); selectedRow = position; } }); }Slide_out.xml-файл:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:fromYDelta="0%" android:toYDelta="100%" android:duration="@android:integer/config_mediumAnimTime"/> </set>
Как указывает чет Хаазе в DevBytes, https://www.youtube.com/watch?v=8MIfSxgsHIs , все это будет работать, но не забудьте добавить флаги transientState.
Из его кода:
// Here's where the problem starts - this animation will animate a View object. // But that View may get recycled if it is animated out of the container, // and the animation will continue to fade a view that now contains unrelated // content. ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, 0); anim.setDuration(1000); if (setTransientStateCB.isChecked()) { // Here's the correct way to do this: if you tell a view that it has // transientState, then ListView ill avoid recycling it until the // transientState flag is reset. // A different approach is to use ViewPropertyAnimator, which sets the // transientState flag internally. view.setHasTransientState(true); } anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { cheeseList.remove(item); adapter.notifyDataSetChanged(); view.setAlpha(1); if (setTransientStateCB.isChecked()) { view.setHasTransientState(false); } } }); anim.start();
Я использовал анимацию слайдов сверху вниз для обновления ListView. Вот код, который я использовал:
adapter.notifyDataSetChanged(); Animation animation = AnimationUtils.loadAnimation( getApplication(), R.anim.slide_top_to_bottom); getListView().startAnimation(animation); getListView().setSelection(0);И slide_top_to_bottom.xml (сохраните его в папке
res/anim)<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator"> <translate android:fromYDelta="-100%" android:toXDelta="0" android:duration="100" /> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="50" /> </set>Редактировать: Попробуйте это:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, final View view, final int i, long l) { ValueAnimator fader = ObjectAnimator.ofFloat(view, "alpha", 1, 0); AnimatorSet animation = new AnimatorSet(); animation.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } }); ((AnimatorSet) animation).play(fader); animation.setDuration(500); animation.start(); adapter.remove(tasks.get(i)); adapter.notifyDataSetChanged(); } });
Comments