Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Binding adapter for https://github.com/evant/binding-collection-adapter which assigns common parameters to a List/Grid RecyclerView. Automatically restores the state of the old LayoutManager into the new one.
public class LMBindingAdapter {
// TODO the creation and modification of a layout manager must be done in one class. The creation is in a factory, but the modification is here.
@BindingAdapter(value = {"viewMode", "orientation", "reverseLayout", "spanCount", "spanSizeLookup"}, requireAll = false)
public static void setLayoutManager(RecyclerView recyclerView,
RecyclerViewMode viewMode,
@LayoutManagers.Orientation int orientation,
boolean reverseLayout,
int spanCount,
final SpanSizeLookup spanSizeLookup) {
if (viewMode == null) {
throw new IllegalArgumentException("viewMode must not be null");
}
LayoutManagers.LayoutManagerFactory layoutManagerFactory;
RecyclerView.LayoutManager oldLayoutManager = recyclerView.getLayoutManager();
Parcelable oldLayoutManagerState = null;
if (oldLayoutManager != null) {
oldLayoutManagerState = oldLayoutManager.onSaveInstanceState();
}
switch (viewMode) {
case LIST:
if (oldLayoutManager instanceof LinearLayoutManager
&& !(oldLayoutManager instanceof GridLayoutManager)) {
((LinearLayoutManager) oldLayoutManager).setOrientation(orientation);
((LinearLayoutManager) oldLayoutManager).setReverseLayout(reverseLayout);
} else {
if (orientation != LinearLayoutManager.VERTICAL) {
layoutManagerFactory = LayoutManagers.linear(orientation, reverseLayout);
} else {
layoutManagerFactory = LayoutManagers.linear();
}
RecyclerView.LayoutManager newLayoutManager = layoutManagerFactory.create(recyclerView);
recyclerView.setLayoutManager(newLayoutManager);
// Attempt to transfer the saved state of the old LM into the new one
if (oldLayoutManagerState != null && oldLayoutManager instanceof LinearLayoutManager) {
newLayoutManager.onRestoreInstanceState(oldLayoutManagerState);
}
}
break;
case GRID:
if (spanCount < 1) {
throw new IllegalArgumentException("spanCount must be defined");
}
final GridLayoutManager gridLayoutManager;
if (oldLayoutManager instanceof GridLayoutManager) {
gridLayoutManager = (GridLayoutManager) oldLayoutManager;
gridLayoutManager.setSpanCount(spanCount);
} else {
if (orientation != GridLayoutManager.VERTICAL) {
layoutManagerFactory = LayoutManagers.grid(spanCount, orientation, reverseLayout);
} else {
layoutManagerFactory = LayoutManagers.grid(spanCount);
}
gridLayoutManager = (GridLayoutManager) layoutManagerFactory.create(recyclerView);
recyclerView.setLayoutManager(gridLayoutManager);
// Attempt to transfer the saved state of the old LM into the new one
if (oldLayoutManagerState != null && oldLayoutManager instanceof LinearLayoutManager) {
gridLayoutManager.onRestoreInstanceState(oldLayoutManagerState);
}
}
final GridLayoutManager.SpanSizeLookup lookup;
if (spanSizeLookup == null) {
lookup = new GridLayoutManager.DefaultSpanSizeLookup();
} else {
lookup = new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
int spanSize = spanSizeLookup.getSpanSize(position);
return spanSize > 0 ? spanSize : gridLayoutManager.getSpanCount();
}
};
}
gridLayoutManager.setSpanSizeLookup(lookup);
break;
/*case STAGGERED_GRID:
if (spanCount < 1) {
throw new IllegalArgumentException("spanCount must be defined");
}
layoutManagerFactory = LayoutManagers.staggeredGrid(spanCount, orientation);
recyclerView.setLayoutManager(layoutManagerFactory.create(recyclerView));
break;*/
default:
throw new IllegalArgumentException("Unsupported view mode");
}
}
}
public enum RecyclerViewMode {
LIST(R.string.compact_list, R.drawable.ic_view_list_white_24dp),
GRID(R.string.grid, R.drawable.ic_view_module_white_24dp),
STAGGERED_GRID(R.string.staggered_grid, R.drawable.ic_dashboard_white_24dp);
private final int title;
private final int icon;
RecyclerViewMode(@StringRes int title, @DrawableRes int icon) {
this.title = title;
this.icon = icon;
}
public int getTitle() {
return title;
}
public int getIcon() {
return icon;
}
}
public interface SpanSizeLookup {
/**
* Gets the number of span positions occupied by the item
* @param itemPosition the adapter position of the item
* @return The span count or -1 to occupy all available spans.
*/
int getSpanSize(int itemPosition);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment