Based on the deprecated infinum MjolnirRecyclerView library, updated by using AndroidX and added more options: Parallax header and more is coming.
Add this in your root build.gradle
file (not your module build.gradle
file):
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
Add this to your module's build.gradle
file (make sure the version matches the JitPack badge above):
dependencies {
...
implementation 'com.github.invissvenska:ImprovedRecyclerView:VERSION'
}
ImprovedRecyclerView provides methods to add header, footers, empty view and more in a simple way by extending the default RecyclerView behaviour.
You can add optional header and footer to your list. These are optional so you don't have to set a header and/or footer.
adapter.setHeader(View view);
adapter.setFooter(View view);
Empty view is supported. It will be shown automatically when the adapter is empty, and automatically hides when the adapter is populated.
recyclerView.setEmptyView(View view);
It is also possible to show the empty view while the adapter is not set. This is a handy when the adapter is initialized at a later point in time.
// show empty view when adapter is not set
recyclerView.setEmptyView(View view, true);
The onClick methods are already implemented for you by the library.
Implement the OnClickListener<E>
interface in your Activity or Fragment and override the onClick
method.
public class SimpleFragment extends Fragment implements SimpleAdapter.OnClickListener<String> {
// some other code
@Override
public void onClick(int index, String item) {
Toast.makeText(this.getContext(), item, Toast.LENGTH_SHORT).show();
}
}
Paging can be used if you want to use less data in your app. Just add the initial set of items, and when you scroll down the next set of items will be added to the list.
Implement the OnNextPageListener
interface in your Activity or Fragment and override the onScrolledToNextPage
method.
public class NextPageFragment extends Fragment implements SimpleAdapter.OnNextPageListener {
// some other code
@Override
public void onScrolledToNextPage() {
// Fetch data and add it to the list, show some loading widget in UI to indicate loading
adapter.addAll(ITEMS);
}
}
Just use a GridLayoutManager instead of a LinearLayoutManager. Size of header and footer will be automatically spanned across the grid spansize.
...
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
adapter = new SimpleAdapter(getContext());
recyclerView.setAdapter(adapter);
adapter.setHeader(R.layout.item_header);
adapter.setFooter(R.layout.item_footer);
...
Only updates the different values in the RecyclerView and let the same values intact when giving a new list of items.
Extend the DiffUtil.Callback
class and update the getChangePayload
method according your needs. In this example only a string value is added to the Bundle.
public class ItemsDiffUtil extends DiffUtil.Callback {
public static final String EXTRA_ITEM_DESCRIPTION = "EXTRA_ITEM_DESCRIPTION";
private List<Item> oldList;
private List<Item> newList;
public ItemsDiffUtil(List<E> oldList, List<E> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
Bundle bundle = new Bundle();
bundle.putString(EXTRA_ITEM_DESCRIPTION, newList.get(newItemPosition).getName());
return bundle;
}
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getName().equals(newList.get(newItemPosition).getName());
}
}
In your Adapter add the following lines to in the onBind
method to update only fill the updated items.
@Override
protected void bind(final Item item, final int position, List<Object> payloads) {
if (payloads.isEmpty()) {
tvPosition.setText(String.valueOf(item.getId()));
tvText.setText(item.getName());
} else {
Bundle bundle = (Bundle) payloads.get(0);
tvText.setText(bundle.getString(ItemsDiffUtil.EXTRA_ITEM_DESCRIPTION));
}
...
}
In your Fragment or Activity call the update
method in you Adapter to update only the different items:
adapter.update(newList, new ItemsDiffUtil(items, newList));
When you want to feel more depth in you app you can use the parallax option for the header.
Add the height of your header layout to your adapter, and add the ImprovedHeaderScrollListener
to your RecyclerView.
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setEmptyView(emptyView);
adapter = new SimpleAdapter(getContext(), (int) getResources().getDimension(R.dimen.parallax_height));
adapter.setHeader(R.layout.item_header);
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new ResizeScrollListener<>(adapter, layoutManager));
adapter.addAll(ITEMS);
Please click the image below to enlarge.