I have RecyclerView and I need next behavior:
Improvising on Dmitriy Korobeynikov and solving the problem of calling notify dataset changed
public class StickyFooterItemDecoration extends RecyclerView.ItemDecoration {
@Override
public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent,
RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int adapterItemCount = parent.getAdapter().getItemCount();
if (adapterItemCount == RecyclerView.NO_POSITION || (adapterItemCount - 1) != position) {
return;
}
outRect.top = calculateTopOffset(parent, view, adapterItemCount);
}
private int calculateTopOffset(RecyclerView parent, View footerView, int itemCount) {
int topOffset =
parent.getHeight() - parent.getPaddingTop() - parent.getPaddingBottom()
- visibleChildHeightWithFooter(parent, footerView, itemCount);
return topOffset < 0 ? 0 : topOffset;
}
private int visibleChildHeightWithFooter(RecyclerView parent, View footerView, int itemCount) {
int totalHeight = 0;
int onScreenItemCount = Math.min(parent.getChildCount(), itemCount);
for (int i = 0; i < onScreenItemCount - 1; i++) {
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) parent.getChildAt(i)
.getLayoutParams();
int height =
parent.getChildAt(i).getHeight() + layoutParams.topMargin
+ layoutParams.bottomMargin;
totalHeight += height;
}
int footerHeight = footerView.getHeight();
if (footerHeight == 0) {
fixLayoutSize(footerView, parent);
footerHeight = footerView.getHeight();
}
footerHeight = footerHeight + footerView.getPaddingBottom() + footerView.getPaddingTop();
return totalHeight + footerHeight;
}
private void fixLayoutSize(View view, ViewGroup parent) {
// Check if the view has a layout parameter and if it does not create one for it
if (view.getLayoutParams() == null) {
view.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
// Create a width and height spec using the parent as an example:
// For width we make sure that the item matches exactly what it measures from the parent.
// IE if layout says to match_parent it will be exactly parent.getWidth()
int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY);
// For the height we are going to create a spec that says it doesn't really care what is calculated,
// even if its larger than the screen
int heightSpec = View.MeasureSpec
.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED);
// Get the child specs using the parent spec and the padding the parent has
int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
parent.getPaddingLeft() + parent.getPaddingRight(), view.getLayoutParams().width);
int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
parent.getPaddingTop() + parent.getPaddingBottom(), view.getLayoutParams().height);
// Finally we measure the sizes with the actual view which does margin and padding changes to the sizes calculated
view.measure(childWidth, childHeight);
// And now we setup the layout for the view to ensure it has the correct sizes.
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}
}