wake-up-neo.com

So animieren Sie das Hinzufügen oder Entfernen von Android ListView-Zeilen

In iOS gibt es eine sehr einfache und leistungsstarke Möglichkeit, das Hinzufügen und Entfernen von UITableView-Zeilen zu animieren. Hier ist ein Clip aus einem Youtube-Video , der die Standardanimation zeigt. Beachten Sie, wie die umgebenden Zeilen auf die gelöschte Zeile reduziert werden. Mithilfe dieser Animation können Benutzer nachverfolgen, was sich in einer Liste geändert hat und wo in der Liste sie sich befanden, als die Daten geändert wurden.

Seit ich auf Android entwickelt habe, habe ich keine gleichwertige Möglichkeit gefunden, einzelne Zeilen in einer TableView zu animieren. Durch den Aufruf von notifyDataSetChanged() auf meinem Adapter wird ListView sofort mit neuen Informationen aktualisiert. Ich würde gerne eine einfache Animation einer neuen Zeile zeigen, die einschiebt oder herausschiebt, wenn sich die Daten ändern, aber ich kann keinen dokumentierten Weg finden, dies zu tun. Es sieht aus wie LayoutAnimationController könnte einen Schlüssel enthalten, damit dies funktioniert, aber wenn ich einen LayoutAnimationController in meiner ListView (ähnlich wie ApiDemo's LayoutAnimation2 ) setze und Elemente aus meinem Adapter entferne, nachdem die Liste angezeigt wurde, wird das angezeigt Elemente verschwinden sofort, anstatt animiert zu werden.

Ich habe auch folgende Dinge ausprobiert, um ein einzelnes Objekt zu animieren, wenn es entfernt wird:

@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);
}

Die Zeilen, die die animierte Zeile umgeben, bewegen sich jedoch erst, wenn sie beim Aufruf von notifyDataSetChanged() zu ihren neuen Positionen springen. Es scheint, dass ListView sein Layout nicht aktualisiert, sobald seine Elemente platziert wurden.

Beim Schreiben meiner eigenen Implementierung/Gabelung von ListView ist mir etwas in den Sinn gekommen, das scheint etwas zu sein, das nicht so schwierig sein sollte.

Vielen Dank!

206
Alex Pretzlav
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());

für die Animation von oben nach unten:

<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>
122
OAK
14
Eric

Schauen Sie sich die Google-Lösung an. Hier ist nur eine Löschmethode.

ListViewRemovalAnimation Projektcode und Video Demonstration

Es benötigt Android 4.1+ (API 16). Aber wir haben 2014 draußen.

9
dimetil

aufruf listView.scheduleLayoutAnimation (); bevor Sie die Liste ändern

2
karabara

Haben Sie in Erwägung gezogen, einen Sweep nach rechts zu animieren? Sie können beispielsweise einen zunehmend größeren weißen Balken über dem Listenelement zeichnen und ihn dann aus der Liste entfernen. Die anderen Zellen würden immer noch einrasten, aber es wäre besser als nichts.

2
Sam Dufel

Nachdem ich eine neue Zeile in ListView eingefügt habe, scrolle ich die ListView einfach an die neue Position. 

ListView.smoothScrollToPosition(position);
2
Rafael

Ich habe zusammen eine andere Möglichkeit gehackt, um dies zu tun, ohne die Listenansicht bearbeiten zu müssen. Leider scheinen normale Android-Animationen den Inhalt der Zeile zu manipulieren, sind jedoch wirkungslos, wenn sie die Ansicht tatsächlich verkleinern. Betrachten Sie zuerst diesen Handler:

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);
}

Fügen Sie diese Sammlung Ihrem Listenadapter hinzu:

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

und hinzufügen 

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

Wo immer Sie eine Zeile ausblenden möchten, fügen Sie Folgendes hinzu:

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));

Das ist es! Sie können die Geschwindigkeit der Animation ändern, indem Sie die Anzahl der Pixel ändern, um die die Höhe gleichzeitig verkleinert wird. Nicht wirklich anspruchsvoll, aber es funktioniert!

2
jkschneider

Da ListViews hochoptimiert sind, denke ich, dass dies nicht möglich ist. Haben Sie versucht, Ihre "ListView" per Code zu erstellen (dh, indem Sie Ihre Zeilen aus XML heraus aufblasen und an eine LinearLayout anhängen) und sie animieren?

2
whlk

Da Android Open Source ist, müssen Sie die Optimierungen von ListView nicht erneut implementieren. Sie können den Code von ListView abrufen und versuchen, einen Weg zu finden, die Animation zu hacken. Sie können auch eine Funktionsanforderung öffnen in Android Bug Tracker (und wenn Sie sich entschieden haben, diese zu implementieren, Vergiss nicht einen Patch beisteuern ).

Zu Ihrer Information, der ListView-Quellcode ist hier .

1
Lie Ryan

Ich habe es nicht ausprobiert, aber anscheinend sollte animateLayoutChanges tun, was Sie suchen. Ich sehe es in der ImageSwitcher-Klasse. Ich gehe davon aus, dass es auch in der ViewSwitcher-Klasse ist.

1
Genia S.

Nachdem ich meine Vorgehensweise auf meiner Website erklärt hatte, teilte ich den Link. Die Idee ist, Bitmaps zu erstellen. __

Bitte sehen Sie den folgenden Code:

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);
        }
    });

Zum Verständnis von Bildern siehe dies

Vielen Dank.

1
Ram

Hier ist der Quellcode , mit dem Sie Zeilen löschen und neu anordnen können.

Eine Demo-APK-Datei ist ebenfalls verfügbar. Das Löschen von Zeilen erfolgt mehr wie bei Google Gmail App, die eine Ansicht von unten zeigt, nachdem eine Ansicht von oben gezogen wurde. Die untere Ansicht kann eine Rückgängig-Schaltfläche haben oder was auch immer Sie möchten.

1
AndroidDev

Ich habe etwas Ähnliches gemacht. Ein Ansatz besteht darin, über die Animationszeit die Höhe der Ansicht über die Zeit in den Zeilen onMeasure zu interpolieren, während requestLayout() für die listView ausgegeben wird. Ja, es ist möglicherweise besser, den ListView-Code direkt auszuführen, aber es war eine schnelle Lösung (die gut aussah!). 

0
Dori

Einfach einen anderen Ansatz teilen:

Setzen Sie zunächst die Listenansicht Android: animateLayoutChanges auf true :

<ListView
        Android:id="@+id/items_list"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:animateLayoutChanges="true"/>

Dann füge ich ein handler hinzu, um Elemente hinzuzufügen und die Listenansicht verzögert zu aktualisieren:

Handler mHandler = new Handler();
    //delay in milliseconds
    private int mInitialDelay = 1000;
    private final int DELAY_OFFSET = 1000;


public void addItem(final Integer item) {
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mDataSet.add(item);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                        }
                    });
                }
            }).start();

        }
    }, mInitialDelay);
    mInitialDelay += DELAY_OFFSET;
}
0
Mina Samy