I want to change my ListView I currently have over to use RecyclerView
so I can make use of StaggeredGridLayoutManager
but RecyclerView does not have the ability to add a header like ListView.
Usually with a ListView I set an empty view in the header and put the image below the listview and translate the bottom image with the scrolling of the list to create the Parallax
effect.
So with out a header how can I create the same parallax effect with RecyclerView
?
the easiest way to do it, is using below onScrollListener
without relying on any library.
View view = recyclerView.getChildAt(0);
if(view != null && recyclerView.getChildAdapterPosition(view) == 0) {
view.setTranslationY(-view.getTop() / 2);// or use view.animate().translateY();
}
make sure your second viewHolder
item has a background color to match the drawer/activity background. so the scrolling looks parallax.
So today I tried to archive that effect on a RecyclerView
. I was able to do it but since the code is too much I will paste here my github project and I will explain some of the key points of the project.
https://github.com/kanytu/android-parallax-recyclerview
First we need to look at getItemViewType
on the RecyclerView.Adapter
class. This methods defines what type of view we're dealing with. That type will be passed on to onCreateViewHolder
and there we can inflate different views. So what I did was: check if the position is the first one. If so then inflate the header, if not inflate a normal row.
I've added also a CustomRelativeLayout
that clips the view so we don't have any trouble with the dividers and with the rows getting on top of the header.
From this point you seem to know the rest of the logic behind it.
The final result was:
EDIT:
If you need to insert something in adapter make sure you notify the correct position by adding 1 in the notifyItemChanged/Inserted
method. For example:
public void addItem(String item, int position) {
mData.add(position, item);
notifyItemInserted(position + 1); //we have to add 1 to the notification position since we don't want to mess with the header
}
Another important edit I've done is the scroll logic. The mCurrentOffset
system I was using didn't work with the item insertion since the offset will change if you add an item. So what I did was:
ViewHolder holder = findViewHolderForPosition(0);
if (holder != null)
((ParallaxRecyclerAdapter) getAdapter()).translateHeader(-holder.itemView.getTop() * 0.5f);
To test this I added a postDelayed
Runnable, started the app, scrolled to the end, add the item in position 0, and scroll up again. The result was:
If anyone is looking for other parallax effects they can check my other repo:
https://github.com/kanytu/android-parallax-listview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With