diff --git a/example/src/main/java/com/tonicartos/superslimexample/CountryNamesAdapter.java b/example/src/main/java/com/tonicartos/superslimexample/CountryNamesAdapter.java index 7e35972..a7d90b9 100644 --- a/example/src/main/java/com/tonicartos/superslimexample/CountryNamesAdapter.java +++ b/example/src/main/java/com/tonicartos/superslimexample/CountryNamesAdapter.java @@ -86,8 +86,7 @@ public void onBindViewHolder(CountryViewHolder holder, int position) { holder.bindItem(item.text); - final GridSLM.LayoutParams lp = new GridSLM.LayoutParams( - itemView.getLayoutParams()); + final GridSLM.LayoutParams lp = GridSLM.LayoutParams.from(itemView.getLayoutParams()); // Overrides xml attrs, could use different layouts too. if (item.isHeader) { lp.headerDisplay = mHeaderDisplay; diff --git a/gradle.properties b/gradle.properties index cb3fd6e..f2647b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,8 +17,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME=0.4.9.1 -VERSION_CODE=22 +VERSION_NAME=0.4.10 +VERSION_CODE=24 GROUP=com.tonicartos POM_GENERATE_UNIQUE_SNAPSHOTS=false diff --git a/library/src/main/java/com/tonicartos/superslim/GridSLM.java b/library/src/main/java/com/tonicartos/superslim/GridSLM.java index 9120cca..77f3aa4 100644 --- a/library/src/main/java/com/tonicartos/superslim/GridSLM.java +++ b/library/src/main/java/com/tonicartos/superslim/GridSLM.java @@ -2,6 +2,7 @@ import android.content.Context; import android.content.res.TypedArray; +import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; @@ -39,6 +40,8 @@ public GridSLM(LayoutManager layoutManager, Context context) { @Override public int computeHeaderOffset(int firstVisiblePosition, SectionData sd, LayoutState state) { + final int itemCount = state.recyclerState.getItemCount(); + /* * Work from an assumed overlap and add heights from the start until the overlap is zero or * less, or the current position (or max items) is reached. @@ -49,7 +52,7 @@ public int computeHeaderOffset(int firstVisiblePosition, SectionData sd, LayoutS position += mNumColumns) { // Look to see if the header overlaps with the displayed area of the mSection. int rowHeight = 0; - for (int col = 0; col < mNumColumns; col++) { + for (int col = 0; col < mNumColumns && position + col < itemCount; col++) { LayoutState.View child = state.getView(position + col); measureChild(child, sd); rowHeight = @@ -260,7 +263,7 @@ public int finishFillToStart(int leadingEdge, View anchor, SectionData sd, Layou @Override public LayoutManager.LayoutParams generateLayoutParams(LayoutManager.LayoutParams params) { - return new LayoutParams(params); + return LayoutParams.from(params); } @Override @@ -475,16 +478,49 @@ public LayoutParams(Context c, AttributeSet attrs) { a.recycle(); } + /** + * This constructor will be protected in version 0.5. + *
+ * Use {@link #from} instead. + *
+ * + * @param other Source layout params. + */ + @Deprecated public LayoutParams(ViewGroup.MarginLayoutParams other) { super(other); init(other); } + /** + * This constructor will be protected in version 0.5. + *+ * Use {@link #from} instead as this constructor will not copy the margin params from the + * source layout. + *
+ * + * @param other Source layout params. + */ + @Deprecated public LayoutParams(ViewGroup.LayoutParams other) { super(other); init(other); } + /** + * Creates a new instance of {@link LayoutParams}. + * + * @param other Source layout params. + * @return New grid layout params. + */ + public static LayoutParams from(@NonNull ViewGroup.LayoutParams other) { + if (other instanceof ViewGroup.MarginLayoutParams) { + return new LayoutParams((ViewGroup.MarginLayoutParams) other); + } else { + return new LayoutParams(other); + } + } + public int getColumnWidth() { return mColumnWidth; } diff --git a/library/src/main/java/com/tonicartos/superslim/LayoutManager.java b/library/src/main/java/com/tonicartos/superslim/LayoutManager.java index 128f26a..f97d3e3 100644 --- a/library/src/main/java/com/tonicartos/superslim/LayoutManager.java +++ b/library/src/main/java/com/tonicartos/superslim/LayoutManager.java @@ -8,6 +8,7 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.NonNull; import android.support.v7.widget.LinearSmoothScroller; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; @@ -265,6 +266,19 @@ public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State fixOverscroll(bottomLine, layoutState); } + + @Override + public void onItemsChanged(RecyclerView recyclerView) { + View view = getAnchorChild(); + if (view == null) { + mRequestPosition = NO_POSITION_REQUEST; + mRequestPositionOffset = 0; + } else { + mRequestPosition = getPosition(view); + mRequestPositionOffset = getDecoratedTop(view); + } + } + @Override public RecyclerView.LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); @@ -272,7 +286,7 @@ public RecyclerView.LayoutParams generateDefaultLayoutParams() { @Override public LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - LayoutParams params = new LayoutParams(lp); + LayoutParams params = LayoutParams.from(lp); params.width = LayoutParams.MATCH_PARENT; params.height = LayoutParams.MATCH_PARENT; @@ -1273,14 +1287,9 @@ private boolean isOverscrolled(LayoutState state) { return false; } - View lastVisibleView = findLastCompletelyVisibleItem(); - if (lastVisibleView == null) { - lastVisibleView = getChildAt(getChildCount() - 1); - } - - boolean reachedBottom = getPosition(lastVisibleView) == itemCount - 1; - if (!reachedBottom || - getDecoratedBottom(lastVisibleView) >= getHeight() - getPaddingBottom()) { + View lastVisibleView = findLastVisibleItem(); + if (getPosition(lastVisibleView) == itemCount - 1 + && getDecoratedBottom(lastVisibleView) >= getHeight() - getPaddingBottom()) { return false; } @@ -1544,7 +1553,8 @@ private void trimStart(LayoutState state) { } /** - * Trim all content wholly beyond the direction edge. If the direction is START, then update the + * Trim all content wholly beyond the direction edge. If the direction is START, then update + * the * header of the section intersecting the top edge. * * @param direction Direction of edge to trim against. @@ -1781,16 +1791,49 @@ public LayoutParams(Context c, AttributeSet attrs) { int sectionManagerKind = SECTION_MANAGER_LINEAR; + /** + * This constructor will be removed in version 0.5. + *+ * Use {@link #from} instead. + *
+ * + * @param other Source layout params. + */ + @Deprecated public LayoutParams(ViewGroup.MarginLayoutParams other) { super(other); init(other); } + /** + * This constructor will be removed in version 0.5. + *+ * Use {@link #from} instead as this constructor will not copy the margin params from the + * source layout. + *
+ * + * @param other Source layout params. + */ + @Deprecated public LayoutParams(ViewGroup.LayoutParams other) { super(other); init(other); } + /** + * Creates a new instance of {@link LayoutParams}. + * + * @param other Source layout params. + * @return New layout params. + */ + public static LayoutParams from(@NonNull ViewGroup.LayoutParams other) { + if (other instanceof ViewGroup.MarginLayoutParams) { + return new LayoutParams((ViewGroup.MarginLayoutParams) other); + } else { + return new LayoutParams(other); + } + } + public boolean areHeaderFlagsSet(int flags) { return (headerDisplay & flags) == flags; }