Как анимировать добавление или удаление строк Android ListView - PullRequest
209 голосов
/ 14 октября 2010

В iOS есть очень простое и мощное средство для анимации добавления и удаления строк UITableView, вот клип из видео на YouTube , показывающий анимацию по умолчанию. Обратите внимание, как окружающие строки сворачиваются в удаленную строку. Эта анимация помогает пользователям отслеживать, что изменилось в списке и где они находились в списке при изменении данных.

Поскольку я разрабатывал для Android, я не нашел эквивалентного средства для анимации отдельных строк в TableView . Вызов notifyDataSetChanged() на моем адаптере приводит к тому, что ListView немедленно обновляет свое содержимое новой информацией. Я хотел бы показать простую анимацию новой строки, которая сдвигается или сдвигается при изменении данных, но я не могу найти никакого документированного способа сделать это. Похоже, что LayoutAnimationController может содержать ключ к тому, чтобы заставить это работать, но когда я устанавливаю LayoutAnimationController в моем ListView (аналогично LayoutAnimation2 в ApiDemo) и удаляю элементы из моего адаптера после списка элементы исчезают сразу, вместо того, чтобы их оживить.

Я также пробовал что-то вроде следующего, чтобы оживить отдельный элемент при его удалении:

@Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
    Animation animation = new ScaleAnimation(1, 1, 1, 0);
    animation.setDuration(100);
    getListView().getChildAt(position).startAnimation(animation);
    l.postDelayed(new Runnable() {
        public void run() {
            mStringList.remove(position);
            mAdapter.notifyDataSetChanged();
        }
    }, 100);
}

Однако строки, окружающие анимированный ряд, не перемещаются, пока не перейдут на свои новые позиции при вызове notifyDataSetChanged(). Похоже, ListView не обновляет свой макет после размещения его элементов.

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

Спасибо!

Ответы [ 14 ]

124 голосов
/ 28 июля 2011
Animation anim = AnimationUtils.loadAnimation(
                     GoTransitApp.this, android.R.anim.slide_out_right
                 );
anim.setDuration(500);
listView.getChildAt(index).startAnimation(anim );

new Handler().postDelayed(new Runnable() {

    public void run() {

        FavouritesManager.getInstance().remove(
            FavouritesManager.getInstance().getTripManagerAtIndex(index)
        );
        populateList();
        adapter.notifyDataSetChanged();

    }

}, anim.getDuration());

для анимации сверху вниз:

<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromYDelta="20%p" android:toYDelta="-20"
            android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
9 голосов
/ 31 июля 2014

Взгляните на решение Google.Вот только метод удаления.

ListViewRemovalAnimation код проекта и Видео демонстрация

Требуется Android 4.1+ (API 16).Но у нас 2014 снаружи.

2 голосов
/ 21 января 2015

После вставки новой строки в ListView, я просто прокручиваю ListView в новую позицию.

ListView.smoothScrollToPosition(position);
2 голосов
/ 13 декабря 2012

звонок listView.scheduleLayoutAnimation (); перед изменением списка

2 голосов
/ 17 марта 2011

Я взломал еще один способ сделать это без необходимости манипулировать списком. К сожалению, обычные Android-анимации, похоже, манипулируют содержимым строки, но на самом деле они не эффективны для сокращения представления. Итак, сначала рассмотрим этот обработчик:

private Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
    Bundle bundle = message.getData();

    View view = listView.getChildAt(bundle.getInt("viewPosition") - 
        listView.getFirstVisiblePosition());

    int heightToSet;
    if(!bundle.containsKey("viewHeight")) {
        Rect rect = new Rect();
        view.getDrawingRect(rect);
        heightToSet = rect.height() - 1;
    } else {
        heightToSet = bundle.getInt("viewHeight");
    }

    setViewHeight(view, heightToSet);

    if(heightToSet == 1)
        return;

    Message nextMessage = obtainMessage();
    bundle.putInt("viewHeight", (heightToSet - 5 > 0) ? heightToSet - 5 : 1);
    nextMessage.setData(bundle);
    sendMessage(nextMessage);
}

Добавить эту коллекцию в список адаптеров:

private Collection<Integer> disabledViews = new ArrayList<Integer>();

и добавьте

public boolean isEnabled(int position) {
   return !disabledViews.contains(position);
}

Далее, где бы вы ни хотели скрыть строку, добавьте:

Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt("viewPosition", listView.getPositionForView(view));
message.setData(bundle);
handler.sendMessage(message);    
disabledViews.add(listView.getPositionForView(view));

Вот и все! Вы можете изменить скорость анимации, изменив количество пикселей, на которое она сжимается по высоте сразу. Не очень сложно, но это работает!

2 голосов
/ 18 октября 2010

Рассматривали ли вы анимацию развертки вправо?Вы можете сделать что-то вроде рисования постепенно увеличивающейся белой полосы в верхней части элемента списка, а затем удалить ее из списка.Другие ячейки все равно встали бы на свои места, но лучше, чем ничего.

2 голосов
/ 17 октября 2010

Поскольку ListViews высоко оптимизированы, я думаю, что это невозможно получить. Вы пытались создать свой «ListView» по коду (то есть, надувая строки из xml и добавляя их в LinearLayout) и анимируя их?

1 голос
/ 10 июля 2015

Вот исходный код , позволяющий удалять строки и переупорядочивать их.

Также доступен демонстрационный APK-файл.Удаление строк выполняется больше по аналогии с приложением Google Gmail, которое показывает вид снизу после прокрутки вида сверху.Вид снизу может иметь кнопку «Отменить» или что угодно.

1 голос
/ 04 ноября 2012

Как я уже объяснил свой подход на своем сайте, я поделился ссылкой. В любом случае идея состоит в том, чтобы создавать растровые изображения с помощью getdrawingcache. У вас есть два растровых изображения и анимируйте нижнее растровое изображение для создания эффекта перемещения

Пожалуйста, см. Следующий код:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        public void onItemClick(AdapterView<?> parent, View rowView, int positon, long id)
        {
            listView.setDrawingCacheEnabled(true);
            //listView.buildDrawingCache(true);
            bitmap = listView.getDrawingCache();
            myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), rowView.getBottom());
            myBitmap2 = Bitmap.createBitmap(bitmap, 0, rowView.getBottom(), bitmap.getWidth(), bitmap.getHeight() - myBitmap1.getHeight());
            listView.setDrawingCacheEnabled(false);
            imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1));
            imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
            imgView1.setVisibility(View.VISIBLE);
            imgView2.setVisibility(View.VISIBLE);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(0, rowView.getBottom(), 0, 0);
            imgView2.setLayoutParams(lp);
            TranslateAnimation transanim = new TranslateAnimation(0, 0, 0, -rowView.getHeight());
            transanim.setDuration(400);
            transanim.setAnimationListener(new Animation.AnimationListener()
            {
                public void onAnimationStart(Animation animation)
                {
                }

                public void onAnimationRepeat(Animation animation)
                {
                }

                public void onAnimationEnd(Animation animation)
                {
                    imgView1.setVisibility(View.GONE);
                    imgView2.setVisibility(View.GONE);
                }
            });
            array.remove(positon);
            adapter.notifyDataSetChanged();
            imgView2.startAnimation(transanim);
        }
    });

Для понимания с изображениями посмотрите это

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...