Wie kann ich die RecyclerView-Elemente beim Erscheinen animieren?
Der Standardelementanimator wird nur animiert, wenn Daten hinzugefügt oder entfernt werden, nachdem die Recyclingdaten festgelegt wurden. Ich entwickle neue Anwendungen und habe keine Ahnung, wo ich anfangen soll.
Irgendwelche Ideen, wie man das erreichen kann?
EDIT:
Gemäß der ItemAnimator-Dokumentation :
Diese Klasse definiert die Animationen, die für Elemente ausgeführt werden, wenn Änderungen am Adapter vorgenommen werden.
Wenn Sie also Ihre Elemente nicht einzeln zu Ihrer RecyclerView
hinzufügen und die Ansicht bei jeder Iteration aktualisieren, glaube ich nicht, dass ItemAnimator
die Lösung für Ihre Bedürfnisse ist.
So können Sie die RecyclerView
-Elemente animieren, wenn sie mit einem CustomAdapter angezeigt werden:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
private Context context;
// The items to display in your RecyclerView
private ArrayList<String> items;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
public static class ViewHolder extends RecyclerView.ViewHolder
{
TextView text;
// You need to retrieve the container (ie the root ViewGroup from your custom_item_layout)
// It's the view that will be animated
FrameLayout container;
public ViewHolder(View itemView)
{
super(itemView);
container = (FrameLayout) itemView.findViewById(R.id.item_layout_container);
text = (TextView) itemView.findViewById(R.id.item_layout_text);
}
}
public CustomAdapter(ArrayList<String> items, Context context)
{
this.items = items;
this.context = context;
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_item_layout, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.text.setText(items.get(position));
// Here you apply the animation when the view is bound
setAnimation(holder.itemView, position);
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(context, Android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
}
Und Ihr custom_item_layout würde so aussehen:
<FrameLayout
Android:id="@+id/item_layout_container"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<TextView
Android:id="@+id/item_layout_text"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:textAppearance="?android:attr/textAppearanceListItemSmall"
Android:gravity="center_vertical"
Android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
</FrameLayout>
Weitere Informationen zu CustomAdapters und RecyclerView
finden Sie in diesem training in der offiziellen Dokumentation .
Probleme beim schnellen Blättern
Die Verwendung dieser Methode kann zu Problemen beim schnellen Scrollen führen. Die Ansicht kann während der Animation erneut verwendet werden. Um dies zu vermeiden, empfiehlt es sich, die Animation zu löschen, wenn sie getrennt wird.
@Override
public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
{
((CustomViewHolder)holder).clearAnimation();
}
Auf CustomViewHolder:
public void clearAnimation()
{
mRootLayout.clearAnimation();
}
Alte Antwort:
Werfen Sie einen Blick auf Gabrielo Mariottis Repo , ich bin mir ziemlich sicher, dass Sie finden, was Sie brauchen. Er stellt einfache ItemAnimators für die RecyclerView bereit, beispielsweise SlideInItemAnimator oder SlideScaleItemAnimator.
Ich habe das Einblenden von Recyclerview
-Objekten animiert, wenn sie wie im folgenden Code gezeigt angezeigt werden. Vielleicht hilft das jemandem.
private final static int FADE_DURATION = 1000; //FADE_DURATION in milliseconds
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// Set the view to fade in
setFadeAnimation(holder.itemView);
}
private void setFadeAnimation(View view) {
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
Sie können setFadeAnimation()
auch durch die folgende setScaleAnimation()
ersetzen, um das Erscheinungsbild von Elementen zu animieren, indem Sie sie von einem Punkt aus skalieren:
private void setScaleAnimation(View view) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
Der obige Code weist einige Warzen auf, sofern beim Scrollen die RecyclerView
-Elemente immer verblassen oder skalieren. Wenn Sie möchten, können Sie Code hinzufügen, um die Animation nur dann zuzulassen, wenn das Fragment oder die Aktivität mit der Variablen RecyclerView
zum ersten Mal erstellt wird (z. B. Systemzeit bei der Erstellung abrufen und Animation nur für die ersten FADE_DURATION-Millisekunden zulassen).
Ich habe eine Animation aus pbms Antwort mit wenig modification
erstellt, damit die Animation nur einmal ausgeführt wird
im anderen Wort der Animation appear with you scroll down only
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
lastPosition = position;
}
}
und in onBindViewHolder
rufen Sie die Funktion auf
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// call Animation function
setAnimation(holder.itemView, position);
}
Sie können ein RecyclerView-Attribut wie folgt hinzufügen: layoutAnimation = "@ anim/rv_item_animation":
<Android.support.v7.widget.RecyclerView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layoutAnimation="@anim/layout_animation_fall_down"
/>
danke für den ausgezeichneten Artikel hier: https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213
Ein guter Anfang ist folgender: https://github.com/wasabeef/recyclerview-animators/blob/master/animators/src/main/Java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.Java
Sie benötigen nicht einmal die gesamte Bibliothek, diese Klasse reicht aus ... __ Wenn Sie Ihre Adapter-Klasse einfach implementieren, geben Sie einen Animator wie folgt:
@Override
protected Animator[] getAnimators(View view) {
return new Animator[]{
ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
};
}
@Override
public long getItemId(final int position) {
return getWrappedAdapter().getItemId(position);
}
sie sehen Elemente, die beim Scrollen von unten erscheinen, und vermeiden auch das Problem mit dem schnellen Scrollen.
Das Animieren von Elementen in der Recyclingübersicht, wenn sie im Adapter gebunden sind, ist möglicherweise nicht die beste Idee, da dies dazu führen kann, dass die Elemente in der Recyclingübersicht mit unterschiedlichen Geschwindigkeiten animiert werden. In meinem Fall animieren die Gegenstände am Ende des Recyclingberichts schneller zu ihrer Position, als diejenigen, die oben sind, da die Gegenstände weiter oben reisen müssen, so dass es unordentlich aussieht.
Den ursprünglichen Code, mit dem ich jeden Artikel in das Recycling-Fenster animiert habe, finden Sie hier:
http://frogermcs.github.io/Instagram-with-Material-Design-concept-is-getting-real/
Aber ich werde den Code kopieren und einfügen, falls der Link bricht.
SCHRITT 1: Legen Sie dies in Ihrer onCreate-Methode fest, damit die Animation nur einmal ausgeführt wird:
if (savedInstanceState == null) {
pendingIntroAnimation = true;
}
SCHRITT 2: Sie müssen diesen Code in die Methode einfügen, in der Sie die Animation starten möchten:
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
In dem Link animiert der Schreiber die Symbolleistensymbole, sodass er sie in diese Methode einfügt:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
inboxMenuItem = menu.findItem(R.id.action_inbox);
inboxMenuItem.setActionView(R.layout.menu_item_view);
if (pendingIntroAnimation) {
pendingIntroAnimation = false;
startIntroAnimation();
}
return true;
}
SCHRITT 3: Schreibe jetzt die Logik für startIntroAnimation ():
private static final int ANIM_DURATION_TOOLBAR = 300;
private void startIntroAnimation() {
btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));
int actionbarSize = Utils.dpToPx(56);
toolbar.setTranslationY(-actionbarSize);
ivLogo.setTranslationY(-actionbarSize);
inboxMenuItem.getActionView().setTranslationY(-actionbarSize);
toolbar.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(300);
ivLogo.animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(400);
inboxMenuItem.getActionView().animate()
.translationY(0)
.setDuration(ANIM_DURATION_TOOLBAR)
.setStartDelay(500)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startContentAnimation();
}
})
.start();
}
Meine bevorzugte Alternative:
Ich möchte lieber das gesamte Recyclingblatt animieren, anstatt die Elemente im Recyclingblatt.
SCHRITT 1 und 2 bleiben gleich.
In Schritt 3 würde ich die Animation starten, sobald Ihr API-Aufruf mit Ihren Daten zurückkehrt.
private void startIntroAnimation() {
recyclerview.setTranslationY(latestPostRecyclerview.getHeight());
recyclerview.setAlpha(0f);
recyclerview.animate()
.translationY(0)
.setDuration(400)
.alpha(1f)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
}
Dies würde Ihr gesamtes Recycling-Fenster so animieren, dass es vom unteren Bildschirmrand eingeblendet wird.
Erstellen Sie diese Methode in Ihrem recyclerview Adapter
private void setZoomInAnimation(View view) {
Animation zoomIn = AnimationUtils.loadAnimation(context, R.anim.zoomin);// animation file
view.startAnimation(zoomIn);
}
Und schließlich fügen Sie diese Codezeile in onBindViewHolder hinzu
setZoomInAnimation(holder.itemView);
Fügen Sie diese Zeile zu RecyclerView.xml hinzu
Android:animateLayoutChanges="true"
Erweitert einfach deinen Adapter wie unten
public class RankingAdapter extends AnimatedRecyclerView<RankingAdapter.ViewHolder>
Fügen Sie eine Supermethode zu onBindViewHolder hinzu
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
Es ist ein automatischer Weg, animierte Adapter wie "Basheer AL-MOMANI" zu erstellen.
import Android.support.v7.widget.RecyclerView;
import Android.view.View;
import Android.view.ViewGroup;
import Android.view.animation.Animation;
import Android.view.animation.ScaleAnimation;
import Java.util.Random;
/**
* Created by eliaszkubala on 24.02.2017.
*/
public class AnimatedRecyclerView<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {
@Override
public T onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(T holder, int position) {
setAnimation(holder.itemView, position);
}
@Override
public int getItemCount() {
return 0;
}
protected int mLastPosition = -1;
protected void setAnimation(View viewToAnimate, int position) {
if (position > mLastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
mLastPosition = position;
}
}
}
Ohne Codierung.
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:animation="@anim/item_animation_fall_down"
Android:animationOrder="normal"
Android:delay="15%" />
<translate
Android:fromYDelta="-20%"
Android:toYDelta="0"
Android:interpolator="@Android:anim/decelerate_interpolator"
/>
<alpha
Android:fromAlpha="0"
Android:toAlpha="1"
Android:interpolator="@Android:anim/decelerate_interpolator"
/>
<scale
Android:fromXScale="105%"
Android:fromYScale="105%"
Android:toXScale="100%"
Android:toYScale="100%"
Android:pivotX="50%"
Android:pivotY="50%"
Android:interpolator="@Android:anim/decelerate_interpolator"
/>
Verwendung in Layouts und Wiederholungsübersicht wie:
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recycler_view"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layoutAnimation="@anim/layout_animation"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />