An Android Animation library which easily add itemanimator to RecyclerView items.

Overview

RecyclerView Animators

Android Arsenal License Maven Central

RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations.

Please feel free to use this.

Features

Demo

ItemAnimator

Adapters

How do I use it?

Setup

Gradle

On your module's build.gradle file add this implementation statement to the dependencies section:

dependencies {
  // Kotlin
  implementation 'jp.wasabeef:recyclerview-animators:4.0.2'
}

Also make sure that the repositories section includes not only "mavenCentral()" but also a maven section with the "google()" endpoint.

repositories {
  google()
  mavenCentral()
  jcenter()
}

ItemAnimator

Step 1

Set RecyclerView ItemAnimator.

val recyclerView = findViewById<RecyclerView>(R.id.list)
recyclerView.itemAnimator = SlideInLeftAnimator()
val recyclerView = findViewById<RecyclerView>(R.id.list)
recyclerView.itemAnimator = SlideInUpAnimator(OvershootInterpolator(1f))

Step 2

Please use the following
notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)

If you want your animations to work, do not rely on calling notifyDataSetChanged(); as it is the RecyclerView's default behavior, animations are not triggered to start inside this method.

fun remove(position: Int) {
  dataSet.removeAt(position)
  notifyItemRemoved(position)
}

fun add(text: String, position: Int) {
  dataSet.add(position, text)
  notifyItemInserted(position)
}

Advanced Step 3

You can change the durations.

recyclerView.itemAnimator?.apply {
  addDuration = 1000
  removeDuration = 100
  moveDuration = 1000
  changeDuration = 100
}

Advanced Step 4

Change the interpolator.

recyclerView.itemAnimator = SlideInLeftAnimator().apply {
  setInterpolator(OvershootInterpolator())
}

Advanced Step 5

By implementing AnimateViewHolder, you can override preset animation. So, custom animation can be set depending on view holder.

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), AnimateViewHolder {

  override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
    // do something
  }

  override fun animateRemoveImpl(holder: RecyclerView.ViewHolder, listener: ViewPropertyAnimatorListener) {
    itemView.animate().apply {
      translationY(-itemView.height * 0.3f)
      alpha(0f)
      duration = 300
      setListener(listener)
    }.start()
  }

  override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
    itemView.setTranslationY(-itemView.height * 0.3f)
    itemView.setAlpha(0f)
  }

  override fun animateAddImpl(holder: RecyclerView.ViewHolder, listener: ViewPropertyAnimatorListener) {
    itemView.animate().apply {
      translationY(0f)
      alpha(1f)
      duration = 300
      setListener(listener)
    }.start()
  }
}

Animators

Cool

LandingAnimator

Scale

ScaleInAnimator, ScaleInTopAnimator, ScaleInBottomAnimator
ScaleInLeftAnimator, ScaleInRightAnimator

Fade

FadeInAnimator, FadeInDownAnimator, FadeInUpAnimator
FadeInLeftAnimator, FadeInRightAnimator

Flip

FlipInTopXAnimator, FlipInBottomXAnimator
FlipInLeftYAnimator, FlipInRightYAnimator

Slide

SlideInLeftAnimator, SlideInRightAnimator, OvershootInLeftAnimator, OvershootInRightAnimator
SlideInUpAnimator, SlideInDownAnimator

RecyclerView.Adapter

Step 1

Set RecyclerView ItemAnimator.

val recyclerView = findViewById<RecyclerView>(R.id.list)
recyclerView.adapter = AlphaInAnimationAdapter(MyAdapter())

Java

RecyclerView recyclerView = findViewById(R.id.list);
recyclerView.setAdapter(new AlphaInAnimationAdapter(MyAdapter());

Advanced Step 2

recyclerView.adapter = AlphaInAnimationAdapter(MyAdapter()).apply {
  // Change the durations.
  setDuration(1000)
  // Change the interpolator.
  setInterpolator(vershootInterpolator())
  // Disable the first scroll mode.
  setFirstOnly(false)
}

Java

AlphaInAnimationAdapter alphaInAnimationAdapter = new AlphaInAnimationAdapter(new MyAdapter());
alphaInAnimationAdapter.setDuration(1000);
alphaInAnimationAdapter.setInterpolator(new OvershootInterpolator());
alphaInAnimationAdapter.setFirstOnly(false);

Advanced Step 3

Multiple Animations

val alphaAdapter = AlphaInAnimationAdapter(MyAdapter())
recyclerView.adapter = ScaleInAnimationAdapter(alphaAdapter)

Java

recyclerView.setAdapter(new ScaleInAnimationAdapter(alphaInAnimationAdapter));

Adapters

Alpha

AlphaInAnimationAdapter

Scale

ScaleInAnimationAdapter

Slide

SlideInBottomAnimationAdapter
SlideInRightAnimationAdapter, SlideInLeftAnimationAdapter

Applications using RecyclerView Animators

Please ping me or send a pull request if you would like to be added here.

Icon Application
Ameba Ownd
QuitNow!
AbemaTV
CL

Developed By

Daichi Furiya (Wasabeef) - [email protected]

Follow me on Twitter

Contributions

Any contributions are welcome!

Contributers

Thanks

  • Inspired by AndroidViewAnimations in daimajia.

License

Copyright 2020 Daichi Furiya / Wasabeef

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Notify changes on an item

    Notify changes on an item

    Hi, nice library! The animation on insert, delete and show item work very well but when I call "notifyItemChanged" or "notifyDatasetChanged" on the adapter, nothing happens.

    opened by folivares 20
  • java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{40e612c0 position=2 id=-1, oldPos=-1, pLpos:-1 no parent}

    java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{40e612c0 position=2 id=-1, oldPos=-1, pLpos:-1 no parent}

    crash on android 4.0.4

    after adding item and calling notifyItemMoved.
    flinging recyclerview crashes app.

    java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{40e612c0 position=2 id=-1, oldPos=-1, pLpos:-1 no parent} at android.support.v7.widget.RecyclerView$4.attachViewToParent(RecyclerView.java:377) at android.support.v7.widget.ChildHelper.attachViewToParent(ChildHelper.java:208) at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:4936) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:4913) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:4901) at android.support.v7.widget.StaggeredGridLayoutManager.fill(StaggeredGridLayoutManager.java:1340) at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:584) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1988) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.RelativeLayout.onLayout(RelativeLayout.java:925) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:890) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486) at android.widget.LinearLayout.onLayout(LinearLayout.java:1399) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11425) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1509) at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2498) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:4944) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(NativeStart.java)

    opened by mshearer123 8
  • Fixing #64 issue that we faced in special case

    Fixing #64 issue that we faced in special case

    We faced IndexOutOfBoundException because we remove animator at the end of the animation. This small change checks size before removing.

    Please review and comment!

    opened by emartynov 7
  • BREAKING CHANGES in revision 23.1.0 of Android Support Library

    BREAKING CHANGES in revision 23.1.0 of Android Support Library

    Revision 23.1.0 of the Android Support Library includes the following updates:

    Added an improved animation API to the ItemAnimator class for better customizations:

    • Change animations no longer enforce two copies of the ViewHolder object, which enables item content animations. Also, the ItemAnimator object decides whether it wants to reuse the same ViewHolder object or create a new one.
    • The new information record API gives the ItemAnimator class the flexibility to collect data at the correct point in the layout lifecycle. This information is later passed into the animate callbacks.
    • Provided an easy transition plan for this backward-incompatible API change:

    If you’ve previously extended the ItemAnimator class, you can change your base class to SimpleItemAnimator and your code should work as before. The SimpleItemAnimator class provides the old API by wrapping the new API.

    Some methods were removed from the ItemAnimator class. The following code will no longer compile:

    recyclerView.getItemAnimator().setSupportsChangeAnimations(false)
    

    You can replace it with:

    ItemAnimator animator = recyclerView.getItemAnimator();
    if (animator instanceof SimpleItemAnimator) {
       ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
    }
    

    In my project I am using Proguard, and with the new revision of the support library there are these warnings:

    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator: can't find referenced method 'void dispatchMoveFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator: can't find referenced method 'void dispatchChangeFinished(android.support.v7.widget.RecyclerView$ViewHolder,boolean)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator: can't find referenced method 'void dispatchRemoveFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator: can't find referenced method 'void dispatchAddFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$4: can't find referenced method 'void dispatchMoveStarting(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$4: can't find referenced method 'void dispatchMoveFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$5: can't find referenced method 'void dispatchChangeStarting(android.support.v7.widget.RecyclerView$ViewHolder,boolean)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$5: can't find referenced method 'void dispatchChangeFinished(android.support.v7.widget.RecyclerView$ViewHolder,boolean)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$6: can't find referenced method 'void dispatchChangeStarting(android.support.v7.widget.RecyclerView$ViewHolder,boolean)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$6: can't find referenced method 'void dispatchChangeFinished(android.support.v7.widget.RecyclerView$ViewHolder,boolean)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$DefaultAddVpaListener: can't find referenced method 'void dispatchAddStarting(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$DefaultAddVpaListener: can't find referenced method 'void dispatchAddFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$DefaultRemoveVpaListener: can't find referenced method 'void dispatchRemoveStarting(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    Warning:jp.wasabeef.recyclerview.animators.BaseItemAnimator$DefaultRemoveVpaListener: can't find referenced method 'void dispatchRemoveFinished(android.support.v7.widget.RecyclerView$ViewHolder)' in program class jp.wasabeef.recyclerview.animators.BaseItemAnimator
    

    Indeed, if I ignore these warnings, it causes a crash in my app. Please fix, thank you!

    opened by ygnessin 7
  • Getting type = 0 in my Adapter and crashing the app. Adapter with several view types.

    Getting type = 0 in my Adapter and crashing the app. Adapter with several view types.

    Hi, I'm using the SlideInBottomAnimationAdapter in my Adapter as it is in the documentation:

       vRecyclerView.setAdapter(new SlideInBottomAnimationAdapter(new AlphaInAnimationAdapter(getAdapter())));
    

    But im getting type = 0 in the method onCreateViewHolder from my own adapter:

       @Override
        public PublicationViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
            View v;
            switch (type) {
                case USER_PUBLICATION_TYPE:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_no_images, null);
                    return new UserPublicationViewHolder(v);
                case USER_PUBLICATION_TYPE_W_1_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_1_img, null);
                    return new UserPublicationSingleImageViewHolder(v);
                case USER_PUBLICATION_TYPE_W_2_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_2_img, null);
                    return new UserPublicationTwoImagesViewHolder(v);
                case USER_PUBLICATION_TYPE_W_3_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_3_img, null);
                    return new UserPublicationThreeImagesViewHolder(v);
                case USER_PUBLICATION_TYPE_W_4_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_4_img, null);
                    return new UserPublicationFourImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_no_images, null);
                    return new SocialNetworkPublicationViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_1_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_1_img, null);
                    return new SocialNetworkPublicationSingleImageViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_2_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_2_img, null);
                    return new SocialNetworkPublicationTwoImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_3_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_3_img, null);
                    return new SocialNetworkPublicationThreeImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_4_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_4_img, null);
                    return new SocialNetworkPublicationFourImagesViewHolder(v);
                case EVENT_PUBLICATION_TYPE:
                    v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_event_publication, null);
                    return new EventPublicationViewHolder(v);
                case PLACE_PUBLICATION_TYPE:
                    v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_place_publication, null);
                    return new PlacePublicationViewHolder(v);
            }
            throw new RuntimeException("No type matched! Type="+type);
        }
    

    I have several views as you can see but I didn't think that this will be a problem, is theres some work around?

    I show you the full adapter but theres nothing from another world. Maybe I need to call some super? But the onCreateViewHolder method is abstract so I know what should I do there.

       public class PublicationAdapter extends RecyclerView.Adapter<PublicationViewHolder> {
    
        public static final int USER_PUBLICATION_TYPE = 1;
        public static final int EVENT_PUBLICATION_TYPE = 2;
        public static final int PLACE_PUBLICATION_TYPE = 7;
        private static final int USER_PUBLICATION_TYPE_W_1_IMG = 3;
        private static final int USER_PUBLICATION_TYPE_W_2_IMG = 4;
        private static final int USER_PUBLICATION_TYPE_W_3_IMG = 5;
        private static final int USER_PUBLICATION_TYPE_W_4_IMG = 6;
        public static final int SOCIALNETWORK_PUBLICATION_TYPE = 8;
        private static final int SOCIALNETWORK_PUBLICATION_TYPE_W_1_IMG = 9;
        private static final int SOCIALNETWORK_PUBLICATION_TYPE_W_2_IMG = 10;
        private static final int SOCIALNETWORK_PUBLICATION_TYPE_W_3_IMG = 11;
        private static final int SOCIALNETWORK_PUBLICATION_TYPE_W_4_IMG = 12;
    
    
    
        private ArrayList<Publication> publications = new ArrayList<Publication>();
    
        public ArrayList<Publication> getPublications() {
            return publications;
        }
    
    
        public void setPublications(ArrayList<Publication> publications) {
            this.publications = publications;
        }
    
        @Override
        public int getItemViewType(int position) {
            Publication publication = publications.get(position);
            if (publication instanceof UserPublication) {
                int length = publication.getMedias().size();
                switch (length) {
                    case 1:
                        return USER_PUBLICATION_TYPE_W_1_IMG;
                    case 2:
                        return USER_PUBLICATION_TYPE_W_2_IMG;
                    case 3:
                        return USER_PUBLICATION_TYPE_W_3_IMG;
                    case 4:
                        return USER_PUBLICATION_TYPE_W_4_IMG;
                    default:
                        if (length > 4) {
                            return USER_PUBLICATION_TYPE_W_4_IMG;
                        }
                        break;
                }
                return USER_PUBLICATION_TYPE;
            }
            if (publication instanceof SocialNetworkPublication) {
                int length = publication.getMedias().size();
                switch (length) {
                    case 1:
                        return SOCIALNETWORK_PUBLICATION_TYPE_W_1_IMG;
                    case 2:
                        return SOCIALNETWORK_PUBLICATION_TYPE_W_2_IMG;
                    case 3:
                        return SOCIALNETWORK_PUBLICATION_TYPE_W_3_IMG;
                    case 4:
                        return SOCIALNETWORK_PUBLICATION_TYPE_W_4_IMG;
                    default:
                        if (length > 4) {
                            return SOCIALNETWORK_PUBLICATION_TYPE_W_4_IMG;
                        }
                        break;
                }
                return SOCIALNETWORK_PUBLICATION_TYPE;
            }
            if (publication instanceof EventPublication) {
                return EVENT_PUBLICATION_TYPE;
            }
            if(publication instanceof PlacePublication){
                return PLACE_PUBLICATION_TYPE;
            }
            throw new RuntimeException("Unknown view type in PublicationAdapter");
        }
    
        @Override
        public PublicationViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
            View v;
            switch (type) {
                case USER_PUBLICATION_TYPE:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_no_images, null);
                    return new UserPublicationViewHolder(v);
                case USER_PUBLICATION_TYPE_W_1_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_1_img, null);
                    return new UserPublicationSingleImageViewHolder(v);
                case USER_PUBLICATION_TYPE_W_2_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_2_img, null);
                    return new UserPublicationTwoImagesViewHolder(v);
                case USER_PUBLICATION_TYPE_W_3_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_3_img, null);
                    return new UserPublicationThreeImagesViewHolder(v);
                case USER_PUBLICATION_TYPE_W_4_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_4_img, null);
                    return new UserPublicationFourImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_no_images, null);
                    return new SocialNetworkPublicationViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_1_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_1_img, null);
                    return new SocialNetworkPublicationSingleImageViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_2_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_2_img, null);
                    return new SocialNetworkPublicationTwoImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_3_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_3_img, null);
                    return new SocialNetworkPublicationThreeImagesViewHolder(v);
                case SOCIALNETWORK_PUBLICATION_TYPE_W_4_IMG:
                    v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_user_publication_w_4_img, null);
                    return new SocialNetworkPublicationFourImagesViewHolder(v);
                case EVENT_PUBLICATION_TYPE:
                    v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_event_publication, null);
                    return new EventPublicationViewHolder(v);
                case PLACE_PUBLICATION_TYPE:
                    v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_place_publication, null);
                    return new PlacePublicationViewHolder(v);
            }
            throw new RuntimeException("No type matched! Type="+type);
        }
    
        private static final String INTERACTION_LIKE = "LIKE";
        private static final String INTERACTION_DISLIKE = "DISLIKE";
        private static final String INTERACTION_LOVE = "LOVE";
        private static final String INTERACTION_NONE = "";
    
        @Override
        public void onBindViewHolder(final PublicationViewHolder aPublicationHolder, int i) {
            switch (publications.get(i).getType()) {
                case Publication.TYPE_SOCIAL_NETWORK_PUBLICATION:
                    bindSocialNetworkPublicationCallbacks(aPublicationHolder, i);
                    aPublicationHolder.load(publications.get(i), FeedFragment.this);
                    break;
                case Publication.TYPE_USER_PUBLICATION:
                    bindUserPublicationCallbacks(aPublicationHolder, i);
                    aPublicationHolder.load(publications.get(i), FeedFragment.this);
                break;
                case Publication.TYPE_EVENT_PUBLICATION:
                    bindEventPublicationCallbacks(aPublicationHolder, i);
                    aPublicationHolder.load(publications.get(i), FeedFragment.this);
                break;
                case Publication.TYPE_PLACE_PUBLICATION:
                    bindPlacePublicationCallbacks(aPublicationHolder, i);
                    aPublicationHolder.load(publications.get(i), FeedFragment.this);
                break;
            }
            if (i == 0) {
                onFirstViewHolderBinded(aPublicationHolder);
            }
        }
    
        private void bindPlacePublicationCallbacks(PublicationViewHolder aPublicationHolder, int i) {
            final PlacePublication publication = (PlacePublication) publications.get(i);
            aPublicationHolder.load(publication,
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onLikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onDislikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onFavoriteClicked(publication);
                        }
                    }, FeedFragment.this);
        }
    
        private void bindEventPublicationCallbacks(PublicationViewHolder aPublicationHolder, int i) {
            final EventPublication publication = (EventPublication) publications.get(i);
            aPublicationHolder.load(publication,
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onLikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onDislikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onFavoriteClicked(publication);
                        }
                    }, FeedFragment.this);
        }
    
        private void bindUserPublicationCallbacks(PublicationViewHolder aPublicationHolder, int i) {
            final UserPublication publication = (UserPublication) publications.get(i);
            aPublicationHolder.load(publication,
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onLikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onDislikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onFavoriteClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onEditPostClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onDeletePostClicked(publication);
                        }
                    },
                    new TagCloudLocationFriends.OnTagSelectListener() {
                        @Override
                        public void onTagSelected(MinikastTag tag, int position) {
                            if(tag.getType() == 2){
                                GoTo.placeDetail(getActivity(), publication.getLocation().getId(), publication.getLocation().getName());
                            }else if (tag.getType() == 3){
                                User aUser = new User(-1);
                                aUser.setProfileId(String.valueOf(tag.getUserID()));
                                GoTo.user(getActivity(), aUser);
                            }
                        }
                    }, FeedFragment.this);
        }
    
        private void bindSocialNetworkPublicationCallbacks(PublicationViewHolder aPublicationHolder, int i) {
            final SocialNetworkPublication publication = (SocialNetworkPublication) publications.get(i);
            aPublicationHolder.load(publication,
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onLikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onDislikeClicked(publication);
                        }
                    },
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            onFavoriteClicked(publication);
                        }
                    },
                    new TagCloudLocationFriends.OnTagSelectListener() {
                        @Override
                        public void onTagSelected(MinikastTag tag, int position) {
                            if(tag.getType() == 2){
                                GoTo.placeDetail(getActivity(), publication.getLocation().getId(), publication.getLocation().getName());
                            }else if (tag.getType() == 3){
                                User aUser = new User(-1);
                                aUser.setProfileId(String.valueOf(tag.getUserID()));
                                GoTo.user(getActivity(), aUser);
                            }
                        }
                    }, FeedFragment.this);
        }
    
        private void onDeletePostClicked(UserPublication publication) {
            showDialogDeletePost(publication.getId(), mCurrentPosts.indexOf(publication));
        }
    
        private void onEditPostClicked(UserPublication publication) {
            GoTo.editPost(getActivity(), publication);
        }
    
        private void removeInteraction(Publication publication, String oldInteraction){
            RemovePostInteraction operation = new RemovePostInteraction(publication, String.valueOf(publication.getId()), StartupSharedPreferences.getUserId(), oldInteraction);
            operation.setmToken(getToken());
            sendOperationRequest(operation);
        }
    
        private void addInteraction(Publication publication, String newInteraction){
            SavePostInteractionOperation operation = new SavePostInteractionOperation(publication, String.valueOf(publication.getId()), StartupSharedPreferences.getUserId(), newInteraction);
            operation.setmToken(getToken());
            sendOperationRequest(operation);
        }
    
        private void onLikeClicked(Publication publication) {
            if(publication.getRelationship().equals(INTERACTION_LIKE)){
                publication.setRelationship(INTERACTION_NONE);
                removeInteraction(publication, INTERACTION_LIKE);
            }else{
                publication.setRelationship(INTERACTION_LIKE);
                addInteraction(publication, INTERACTION_LIKE);
            }
        }
    
        private void onFavoriteClicked(Publication publication) {
            if(publication.getRelationship().equals(INTERACTION_LOVE)){
                publication.setRelationship(INTERACTION_NONE);
                removeInteraction(publication, INTERACTION_LOVE);
            }else{
                publication.setRelationship(INTERACTION_LOVE);
                addInteraction(publication, INTERACTION_LOVE);
            }
        }
    
        private void onDislikeClicked(Publication publication) {
            if(publication.getRelationship().equals(INTERACTION_DISLIKE)){
                publication.setRelationship(INTERACTION_NONE);
                removeInteraction(publication, INTERACTION_DISLIKE);
            }else{
                publication.setRelationship(INTERACTION_DISLIKE);
                addInteraction(publication, INTERACTION_DISLIKE);
            }
        }
    
        @Override
        public long getItemId(int position) {
           return publications.get(position).getId();
        }
    
        @Override
        public int getItemCount() {
            return publications.size();
        }
    
        public void updatePublication(Publication modifP) {
            int idx = publications.indexOf(modifP);
            publications.set(idx, modifP);
        }
    }
    

    I also set the hasStableItems to true. I still can call the super.getItemViewType() but if I do so, It will still crach in the onCreateViewHolder

    opened by 4gus71n 7
  • SlideInRightAnimator Crash

    SlideInRightAnimator Crash

    i'm using API 15 on Samsung Galaxy Tab 10.1

    call AB method on UiThread

    next .. error message

    java.lang.IllegalArgumentException: Called attach on a child which is not detached: ViewHolder{4142f648 position=6 id=-1, oldPos=-1, pLpos:7undefined adapter position no parent} at android.support.v7.widget.RecyclerView$4.attachViewToParent(RecyclerView.java:422) at android.support.v7.widget.ChildHelper.attachViewToParent(ChildHelper.java:208) at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:5239) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:5216) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:5204) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1325) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1274) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:525) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2072) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2415) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1644) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1502) at android.widget.LinearLayout.onLayout(LinearLayout.java:1415) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1644) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1502) at android.widget.LinearLayout.onLayout(LinearLayout.java:1415) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1644) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1502) at android.widget.LinearLayout.onLayout(LinearLayout.java:1415) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.widget.FrameLayout.onLayout(FrameLayout.java:431) at android.view.View.layout(View.java:11477) at android.view.ViewGroup.layout(ViewGroup.java:4232) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1692) at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2649) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4507) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:978) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745) at dalvik.system.NativeStart.main(Native Method)

    opened by kronenz 4
  • Support for androidx

    Support for androidx

    Hey, is it possible to get support for androidx for this library? The current version builds just fine but it shows errors in Android Studio since the classes are basically the same but the package names are not.

    opened by KartikShankhavaram 3
  • Implement Hierarchical Timing specification for all animators in accordance with Google Material Design motion guidelines

    Implement Hierarchical Timing specification for all animators in accordance with Google Material Design motion guidelines

    Goal

    Adhere to the Google Material Design Hierarchical Timing spec, illustrated in this video.

    Motivation

    The Google Material Design spec for recycler view animations specifies:

    When building a transition, consider the order and timing of element movement. Ensure that motion supports the information hierarchy, conveying what content is most important by creating a path for the eye to follow. recyclerview-animators does not currently follow this specification - all elements animate in at once.

    Pull Request

    In this PR, I've implemented the Hierarchical Timing specification for all animators, achieving the cool effect that the spec video shows.

    Here's a video of my implementation in action, in my app: https://www.dropbox.com/s/gxiw63pn7ljv3if/recyclerview-animation.mp4?dl=0

    Implementation details

    I achieved this by adding a .setStartDelay call to each Animator's animateAddImpl and animateRemoveImpl method. They call two new methods on BaseAnimator: getAddDelay and getRemoveDelay respectively. These methods will determine the delay based on:

    1. the element's position in the adapter
    2. the current add or remove duration set by .setAddDuration or setRemoveDuration (currently, this is retrieved and then divided by 4 - I found this gives the best result and provides smooth, overlapping animations that are closest to the spec video.)

    Let me know if you need more information to merge this. Thanks for the great library!

    opened by aphexcx 3
  • Added in ability to pass in interpolators to the four ItemAnimators

    Added in ability to pass in interpolators to the four ItemAnimators

    Added in an interpolator member to BaseItem. This allowed for the 4 SlideIn itemanimators to have a secondary constructor that accepts an Interpolator as an argument. If none was passed into the constructor, then the default LinearInterpolator is used.

    enhancement 
    opened by christophereluc 3
  • No animation when using with cursor

    No animation when using with cursor

    Hello, First of all, this is a really nice project and initiative. Congrats! I tested with using an ArrayList as Dataset and worked just fine. But when I tried to implement in my project, where I use a cursor as data, no animation played (except the adapter animation, with was a little buggy). I don't know if is a problem, but I'm just notifying the adapter with: notifyDataSetChanged()

    RecyclerView Declaration and setup:

    // Cursor Adapter  
     recyclerAdapterDetail   = new DetailTaskRecyclerAdapter( getActivity(), null );
     recyclerViewDetail      = (RecyclerView)       fragmentView.findViewById(R.id.fragment_detail_recyclerview);
    
      LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
      linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    
      recyclerViewDetail.setItemAnimator(new FadeInAnimator());
      recyclerViewDetail.getItemAnimator().setAddDuration( 1000 );
      recyclerViewDetail.setLayoutManager(linearLayoutManager);
    
      recyclerViewDetail.setAdapter( recyclerAdapterDetail );
    

    Notifying part on the adapter:

    public Cursor swapCursor(Cursor cursor) {
        if (this.cursor == cursor) {
            return null;
        }
        Cursor oldCursor = this.cursor;
        this.cursor = cursor;
        if (cursor != null) {
            this.notifyDataSetChanged();
        }
        return oldCursor;
    }
    
    opened by tinmegali 3
  • Delegate hasStableIds to wrapped adapter

    Delegate hasStableIds to wrapped adapter

    What does this change?

    RecyclerView behavior can change based on hasStableIds, it's better to delegate hasStableIds to the wrapped adapter. Noticed that hasStableIds is final, so we cannot completely delegate the behavior to the wrapped adapter.

    What is the value of this and can you measure success?

    hasStableIds works properply

    Screenshots

    No

    opened by lcdsmao 2
  • Animator Crashing

    Animator Crashing

    Bug Reporting

    We recently started getting the crash below on some devices (200 / 7000). I can't even tell at which part of our code is it.

    Steps to Reproduce

    • Unknown

    OS details

    • Device: Some
    • OS: 11-13

    Stacktrace

    Fatal Exception: java.lang.IllegalStateException: Cannot find wrapper for b{d3fe4d5 position=4 id=-1, oldPos=-1, pLpos:-1 invalid update undefined adapter position no parent}, seems like it is not bound by this adapter: androidx.recyclerview.widget.e@12c523f
           at androidx.recyclerview.widget.ConcatAdapterController.onViewRecycled(ConcatAdapterController.java:51)
           at androidx.recyclerview.widget.ConcatAdapter.onViewRecycled(ConcatAdapter.java:51)
           at androidx.recyclerview.widget.RecyclerView$Recycler.dispatchViewRecycled(RecyclerView.java:76)
           at androidx.recyclerview.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:202)
           at androidx.recyclerview.widget.RecyclerView.removeAnimatingView(RecyclerView.java:62)
           at androidx.recyclerview.widget.RecyclerView$ItemAnimatorRestoreListener.onAnimationFinished(RecyclerView.java:42)
           at androidx.recyclerview.widget.RecyclerView$ItemAnimator.dispatchAnimationFinished(RecyclerView.java:42)
           at androidx.recyclerview.widget.SimpleItemAnimator.dispatchAddFinished(SimpleItemAnimator.java:22)
           at jp.wasabeef.recyclerview.animators.BaseItemAnimator$DefaultAddAnimatorListener.onAnimationEnd(BaseItemAnimator.java:22)
           at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:1116)
           at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:563)
           at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1250)
           at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1505)
           at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
           at android.animation.AnimationHandler.access$100(AnimationHandler.java:37)
           at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1221)
           at android.view.Choreographer.doCallbacks(Choreographer.java:1020)
           at android.view.ChoreographerExtImpl.checkScrollOptSceneEnable(ChoreographerExtImpl.java:319)
           at android.view.Choreographer.doFrame(Choreographer.java:909)
           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1208)
           at android.os.Handler.handleCallback(Handler.java:938)
           at android.os.Handler.dispatchMessage(Handler.java:99)
           at android.os.Looper.loopOnce(Looper.java:233)
           at android.os.Looper.loop(Looper.java:344)
           at android.app.ActivityThread.main(ActivityThread.java:8191)
           at java.lang.reflect.Method.invoke(Method.java)
           at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
    
    opened by rtsketo 0
  • Add animations work; Remove animations are clunky

    Add animations work; Remove animations are clunky

    Video: https://imgur.com/a/DoDWNvE

    Hi, I'm using an animator like so:

        views.list.layoutManager = LinearLayoutManager(context)
        views.list.itemAnimator = SlideInLeftAnimator()
    

    The add animation work nicely, there is cascading effect where the items arrives one by one. However, the remove animation is clunky: all the items are removed at the same time. I would expect the items to be removed one by one as well.

    After reading the source, I noticed that BaseItemAnimator uses ViewHolder.getOldPosition() to achieve the cascading effect for remove animations. But for me, the old position is always -1, meaning the RecyclerView is not recording ViewHolder's old position.

    Are there any special setup you have to do to make RecyclerView record ViewHolder's old position?

    opened by littledot 1
  • Default ItemAnimators don't use interpolator from constructor

    Default ItemAnimators don't use interpolator from constructor

    For example FadeInAnimator

    `  override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
        holder.itemView.animate().apply {
          alpha(0f)
          duration = removeDuration
          interpolator = interpolator
          setListener(DefaultRemoveAnimatorListener(holder))
          startDelay = getRemoveDelay(holder)
        }.start()
      }`
    

    The code interpolator = interpolator is similar to ViewPropertyAnimator.setInterpolator(ViewPropertyAnimator.getInterpolator())

    To fix, you need to use interpolator = [email protected]

    FideInAnimator

    Library version : 4.0.2

    opened by ggolyakov 0
  • Remove Animation Is Applied To All Items Strange Behaviour

    Remove Animation Is Applied To All Items Strange Behaviour

    I am trying to apply slide to right animation to only removed item but for some reason all items in recyclerview disappear first and then animated back to their position strangely. Please watch the following video. https://i.stack.imgur.com/s14Jr.gif

    Here is my code its very simple:

       friends_screen_friendlist_recyclerview.itemAnimator = SlideInRightAnimator()
                       friends_screen_friendlist_recyclerview.itemAnimator?.apply {
                            addDuration = 120;
                           removeDuration = 1000;
                            moveDuration = 500;
                            changeDuration = 500;
                       }
        friendItems.removeAt(0)
    
                   friends_screen_friendlist_recyclerview.adapter!!.notifyItemRemoved(0)
    
    
    opened by lastpeony 1
  • start delay for add/remove animation

    start delay for add/remove animation

    What does this change?

    • Resolving #176
    • Convert AnimatorSampleActivity to Kotlin
    • Set function for AddDelay and RemoveDelay for customizing delay for starting add/remove animation

    What is the value of this and can you measure success?

    • Everyone using this library can set getAddDelay and getRemoveDelay function without changing the core of the library

    Screenshots

    opened by kAvEh-- 0
Owner
Daichi Furiya
Google Developers Expert for Android
Daichi Furiya
Android ListView that mimics a GridView with asymmetric items. Supports items with row span and column span

AsymmetricGridView An Android custom ListView that implements multiple columns and variable sized elements. Please note that this is currently in a pr

Felipe Lima 1.8k Jan 7, 2023
Android library providing simple way to control divider items (ItemDecoration) of RecyclerView

RecyclerView-FlexibleDivider Android library providing simple way to control divider items of RecyclerView Release Note [Release Note] (https://github

Yoshihito Ikeda 2.4k Dec 18, 2022
Kotlin way of building RecyclerView Adapter 🧩. You do not have to write RecyclerView Adapters again and again and suffer from handling of different view types. Kiel will help you.

Kiel Kiel is a RecyclerView.Adapter with a minimalistic and convenient Kotlin DSL which provides utility on top of Android's normal RecyclerView.Adapt

ibrahim yilmaz 370 Jan 2, 2023
RecyclerView extension library which provides advanced features. (ex. Google's Inbox app like swiping, Play Music app like drag and drop sorting)

Advanced RecyclerView This RecyclerView extension library provides Google's Inbox app like swiping, Play Music app like drag-and-drop sorting and expa

Haruki Hasegawa 5.2k Dec 23, 2022
An adapter which could be used to achieve a parallax effect on RecyclerView.

android-parallax-recycleview Integration Step 1. Add the JitPack repository to your build file repositories { maven { url "https://jitpack

Pedro Oliveira 1.6k Nov 17, 2022
. Android library that integrate sticky section headers in your RecyclerView

recyclerview-stickyheaders Recyclerview-stickyheaders is an Android library that makes it easy to integrate section headers in your RecyclerView. Thes

null 968 Nov 10, 2022
Android library defining adapter classes of RecyclerView to manage multiple view types

RecyclerView-MultipleViewTypeAdapter RecyclerView adapter classes for managing multiple view types Release Note [Release Note] (https://github.com/yqr

Yoshihito Ikeda 414 Nov 21, 2022
ItemDecoration for RecyclerView using LinearLayoutManager for Android

RecyclerItemDecoration RecyclerItemDecoration allows you to draw divider between items in recyclerview with multiple ViewType without considering item

magiepooh 328 Dec 27, 2022
[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView

This project is no longer being maintained sticky-headers-recyclerview This decorator allows you to easily create section headers for RecyclerViews us

timehop 3.7k Dec 31, 2022
Pumped up RecyclerView

##Description This is an attempt to make RecyclerView easier to use. Features built in: ProgressBar while adapter hasn't been set EmptyView if adapter

Anton Malinskiy 2.6k Jan 5, 2023
A very easy-to-use and non-intrusive implement of Swipe to dismiss for RecyclerView.

RecyclerViewSwipeDismiss A very easy-to-use and non-intrusive implement of Swipe to dismiss for RecyclerView. Preview How to use Add these lines to yo

xcodebuild 431 Nov 23, 2022
A Fast Scroller for the RecyclerView world!

RecyclerViewFastScroller The RecyclerViewFastScroller is a widget that can be added to a layout and connected to a RecyclerView for fast scrolling. Th

Daniel Smith 1.1k Dec 19, 2022
An Android staggered grid view which supports multiple columns with rows of varying sizes.

AndroidStaggeredGrid ##Notice - Deprecated - 09-2015 This library has been deprecated. We will no longer be shipping any updates or approving communit

Etsy, Inc. 4.8k Dec 29, 2022
A GridView which can addHeaderView and addFooterView

Please follow me on GitHub, I need your support Github: https://github.com/liaohuqiu twitter: https://twitter.com/liaohuqiu 中文版文档 GridView with Header

Huqiu Liao 1.3k Nov 30, 2022
Android library to display a ListView whose cells are not rigid but flabby and react to ListView scroll.

FlabbyListView This library is not maintained anymore and there will be no further releases Android library to display a ListView which cells are not

JPARDOGO 762 Nov 23, 2022
An android library for section headers that stick to the top

StickyListHeaders StickyListHeaders is an Android library that makes it easy to integrate section headers in your ListView. These section headers stic

Emil Sjölander 5.5k Jan 2, 2023
Android library to achieve in an easy way, the behaviour of the home page in the Expedia app, with a pair of auto-scroll circular parallax ListViews.

ListBuddies This library is not maintained anymore and there will be no further releases Android library of a pair of auto-scroll circular parallax Li

JPARDOGO 970 Dec 29, 2022
Android library to observe scroll events on scrollable views.

Android-ObservableScrollView Android library to observe scroll events on scrollable views. It's easy to interact with the Toolbar introduced in Androi

Soichiro Kashima 9.6k Dec 29, 2022
Dividers is a simple Android library to create easy separators for your RecyclerViews

Dividers Dividers is an Android library to easily create separators for your RecyclerViews. It supports a wide range of dividers from simple ones, tha

Karumi 490 Dec 28, 2022