-
Notifications
You must be signed in to change notification settings - Fork 753
Support for a Gridview layout #8
Comments
+1 |
Do you have any comments or thoughts on the issues I brought up in the OP? |
I am looking at implementing something similar at the moment. Definitely worth looking at I think! In our case we want to be able to switch between list and grid view. The only implementation I have come across is this one: https://github.com/antoniolg/RecyclerViewExtensions/blob/master/library/src/main/java/com/antonioleiva/recyclerviewextensions/GridLayoutManager.java not sure if it is any good, the repo states it is still in development. In the case of a mixed row, it should be treated as a break, so you will have partial rows - I can't think of a reason to do it any other way! |
Too bad, it looks like that project hasn't been touched for months. I think you're definitely right about the mixed row behavior. Recently I've been thinking that a more robust way doing sticky headers would be in the layout manager itself rather than a decorator. The biggest problem with the decorator approach is we don't get the benefits of item animators or view recycling for free. |
Ahh, after bringing in those classes, I went to import and there's a gridlayoutmanager already in the support libs! I have it working but it's not spitting the rows. Will have to look into it further. |
Wow, nice. There's also a staggered grid layout manager. That's really fantastic. |
Splitting the rows will work if you add a header view and set it's span to the gridviews span size. For example, let your items (which include the header items) implement an interface like
Actually, this does only help if the headers are part of the adapter's data itself... No stickyness, but that's how I use headers in GridViews currently... |
So I do have a basic implementation for grid headers, I don't really have the time at the moment to test this works for anything other than my own use-cases though. import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import com.timehop.stickyheadersrecyclerview.HeaderPositionCalculator;
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter;
import com.timehop.stickyheadersrecyclerview.caching.HeaderProvider;
import com.timehop.stickyheadersrecyclerview.caching.HeaderViewCache;
import com.timehop.stickyheadersrecyclerview.calculation.DimensionCalculator;
import com.timehop.stickyheadersrecyclerview.rendering.HeaderRenderer;
import com.timehop.stickyheadersrecyclerview.util.LinearLayoutOrientationProvider;
import com.timehop.stickyheadersrecyclerview.util.OrientationProvider;
/**
* @author Ben Neill
* @since 22/06/15.
*/
public class StickyRecyclerGridHeadersDecoration extends RecyclerView.ItemDecoration {
private final StickyRecyclerHeadersAdapter mAdapter;
private final SparseArray<Rect> mHeaderRects;
private final HeaderProvider mHeaderProvider;
private final OrientationProvider mOrientationProvider;
private final HeaderPositionCalculator mHeaderPositionCalculator;
private final HeaderRenderer mRenderer;
private final DimensionCalculator mDimensionCalculator;
private final int colCount;
public StickyRecyclerGridHeadersDecoration(StickyRecyclerHeadersAdapter adapter, int colCount) {
this(adapter, new LinearLayoutOrientationProvider(), new DimensionCalculator(), colCount);
}
private StickyRecyclerGridHeadersDecoration(StickyRecyclerHeadersAdapter adapter, OrientationProvider orientationProvider, DimensionCalculator dimensionCalculator, int colCount) {
this(adapter, orientationProvider, dimensionCalculator, new HeaderRenderer(orientationProvider), new HeaderViewCache(adapter, orientationProvider), colCount);
}
private StickyRecyclerGridHeadersDecoration(StickyRecyclerHeadersAdapter adapter, OrientationProvider orientationProvider, DimensionCalculator dimensionCalculator, HeaderRenderer headerRenderer, HeaderProvider headerProvider, int colCount) {
this(adapter, headerRenderer, orientationProvider, dimensionCalculator, headerProvider, new HeaderPositionCalculator(adapter, headerProvider, orientationProvider, dimensionCalculator), colCount);
}
private StickyRecyclerGridHeadersDecoration(StickyRecyclerHeadersAdapter adapter, HeaderRenderer headerRenderer, OrientationProvider orientationProvider, DimensionCalculator dimensionCalculator, HeaderProvider headerProvider, HeaderPositionCalculator headerPositionCalculator, int colCount) {
this.colCount = colCount;
this.mHeaderRects = new SparseArray<>();
this.mAdapter = adapter;
this.mHeaderProvider = headerProvider;
this.mOrientationProvider = orientationProvider;
this.mRenderer = headerRenderer;
this.mDimensionCalculator = dimensionCalculator;
this.mHeaderPositionCalculator = headerPositionCalculator;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int itemPosition = parent.getChildAdapterPosition(view);
for (int i = 0; i <= colCount - 1; i++) {
if (mHeaderPositionCalculator.hasNewHeader(itemPosition - i, false)) {
View header = getHeaderView(parent, itemPosition - i);
setItemOffsetsForHeader(outRect, header, mOrientationProvider.getOrientation(parent));
}
}
}
private void setItemOffsetsForHeader(Rect itemOffsets, View header, int orientation) {
final Rect headerMargins = this.mDimensionCalculator.getMargins(header);
if (orientation == LinearLayoutManager.VERTICAL) {
itemOffsets.top = header.getHeight() + headerMargins.top + headerMargins.bottom;
} else {
itemOffsets.left = header.getWidth() + headerMargins.left + headerMargins.right;
}
}
@Override
public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(canvas, parent, state);
this.mHeaderRects.clear();
if (parent.getChildCount() > 0 && this.mAdapter.getItemCount() > 0) {
for (int i = 0; i < parent.getChildCount(); ++i) {
View itemView = parent.getChildAt(i);
int position = parent.getChildPosition(itemView);
if (this.hasStickyHeader(i, position) || this.mHeaderPositionCalculator.hasNewHeader(position, false)) {
View header = this.mHeaderProvider.getHeader(parent, position);
Rect headerOffset = this.mHeaderPositionCalculator.getHeaderBounds(parent, header, itemView, this.hasStickyHeader(i, position));
this.mRenderer.drawHeader(parent, canvas, header, headerOffset);
this.mHeaderRects.put(position, headerOffset);
}
}
}
}
private boolean hasStickyHeader(int listChildPosition, int indexInList) {
return listChildPosition <= 0 && this.mAdapter.getHeaderId(indexInList) >= 0;
}
public View getHeaderView(RecyclerView parent, int position) {
return this.mHeaderProvider.getHeader(parent, position);
}
} |
@asgarddesigns Does the above implementation work with GridLayoutManager? |
@jotish Yep, it works fine with the support lib version of layoutManager. You may have to override the span size in order to split lines across headers though, something like this:-
|
@asgarddesigns Does not exist the method ?? |
You can use the init methods for that:
|
@TobiasBuchholz Thanks.
@asgarddesigns this solution but did not correctly |
@xiaolongyuan Looks like I am still on 0.4.2 when those methods still existed! |
I have done a fix, that works for me. Take a look to this PR #106 |
Does your StickyRecyclerGridHeadersDecoration also work with StaggeredGridLayoutManager ? |
@asgarddesigns where to declare columnCount in fragment/activity? Please help |
@xiaolongyuan what is columnCount and where to declare it, please help out |
I have added columncount=2 but the following output it showing when using the demo. |
Is there a good implementation of a grid layout manager for RecyclerView?
If so, is it worthwhile to implement sticky headers for it?
How do we deal with the case where the beginning of a row has a different header than the middle of a row or the end of a row?
The text was updated successfully, but these errors were encountered: