I'm building a shopping cart RecyclerView that displays all the items in the cart in a RecyclerView, as well as it has an additional view at the bottom that summarizes the cart (total owing, coupon discount if applicable, etc).
If there's > 3 items in the cart, it looks fine as the user will have to scroll to the bottom to view the "summary view". However, if there's 1 or 2 items, the first items appear, than the summary view, then whitespace. I'd rather the first items, then whitespace, then the summary view.
I've tried adding empty items, however, depending on the device's resolution, it looks inconsistent.
Current appearance if less than 3 items (ie if no scrolling required):
-----------
| Item1 |
| ------- |
| Item2 |
| ------- |
| Summary |
| ------- |
| |
| |
| |
| |
----------
Desired appearance:
-----------
| Item1 |
| ------- |
| Item2 |
| ------- |
| |
| |
| |
| |
| ------- |
| Summary |
----------
I was thinking about your task and eventually put together some code that you may find useful. There's a problem on this stage though.
What I did is added an item decorator to a recycler view:
recyclerView.addItemDecoration(new StickySummaryDecoration());
And here's my implementation of the basic decorator (frankly, it's my first experience with item decorators, so it may not be optimal or totally correct but I did my best):
public class StickySummaryDecoration extends RecyclerView.ItemDecoration {
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getAdapter().getItemCount();
int lastVisibleItemPosition =
((LinearLayoutManager) parent.getLayoutManager()).findLastVisibleItemPosition();
int firstVisiblePosition =
((LinearLayoutManager) parent.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
if ((firstVisiblePosition == 0) && (lastVisibleItemPosition == (childCount - 1))) {
View summaryView = parent.getChildAt(parent.getChildCount() - 1);
int topOffset = parent.getHeight() - summaryView.getHeight();
int leftOffset =
((RecyclerView.LayoutParams) summaryView.getLayoutParams()).leftMargin;
c.save();
c.translate(leftOffset, topOffset);
summaryView.draw(c);
c.restore();
summaryView.setVisibility(View.GONE);
}
}
}
So what I get with this.
Bottom-docked summary in the short list:
You need to scroll down to see the summary in the long list:
Now about a problem. This side-effect when scrolling back up in the long list is what I haven't solved yet.
My experiments are uploaded to a github repo just in case :)
EDIT
Just now I came to me that the missing row element in the recycler view is my recycled summary view holder that has GONE
visibility. There should be a way to bring it back...
EDIT 2
I reconsidered my first solution and changed the code a little bit to account for the long list case (in which case the item decoration is disabled (I think it's closer to what you wanted to achieve)), this automatically resolves the missing row problem.
Based on the answer by yigit I created a working implementation. Extend ItemDecoration
and override getItemOffsets()
:
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getAdapter().getItemCount();
if (parent.getChildLayoutPosition(view) != childCount - 1) return;
int lastViewBottom = calculateViewBottom(parent.getLayoutManager().findViewByPosition(childCount - 2));
view.measure(parent.getWidth(), parent.getHeight());
int height = view.getMeasuredHeight();
int topOffset = parent.getHeight() - lastViewBottom - height;
if (topOffset < 0) topOffset = itemOffset;
outRect.set(itemOffset, topOffset, itemOffset, itemOffset);
}
private int calculateViewBottom(View view) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
return (int) view.getY() + view.getHeight() + params.topMargin + params.bottomMargin;
}
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