Skip to content

Commit b609006

Browse files
author
Rafael Dominiquini
committed
Bug fixes
1 parent 9b80a3c commit b609006

File tree

4 files changed

+82
-67
lines changed

4 files changed

+82
-67
lines changed

library/src/main/java/com/timehop/stickyheadersrecyclerview/HeaderPositionCalculator.java

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ public boolean hasStickyHeader(View itemView, int orientation, int position) {
5151

5252
mDimensionCalculator.initMargins(mTempRect1, itemView);
5353

54-
if (orientation == LinearLayout.VERTICAL) {
55-
offset = itemView.getTop();
56-
margin = mTempRect1.top;
54+
if (itemView != null) {
55+
if (orientation == LinearLayout.VERTICAL) {
56+
offset = itemView.getTop();
57+
margin = mTempRect1.top;
58+
} else {
59+
offset = itemView.getLeft();
60+
margin = mTempRect1.left;
61+
}
5762
} else {
58-
offset = itemView.getLeft();
59-
margin = mTempRect1.left;
63+
offset = -1;
64+
margin = 0;
6065
}
6166

6267
return offset <= margin && mAdapter.getHeaderId(position) >= 0;
@@ -113,10 +118,12 @@ private boolean indexOutOfBounds(int position) {
113118
public boolean headerObscuringSomeItem(RecyclerView parent, View firstHeader) {
114119
for (int i = 0; i < parent.getChildCount(); i++) {
115120
View child = parent.getChildAt(i);
121+
116122
if (itemIsObscuredByHeader(parent, child, firstHeader, mOrientationProvider.getOrientation(parent))) {
117123
return true;
118124
}
119125
}
126+
120127
return false;
121128
}
122129

@@ -128,8 +135,7 @@ public void initHeaderBounds(Rect bounds, RecyclerView recyclerView, View header
128135
View viewAfterNextHeader = getFirstViewUnobscuredByHeader(recyclerView, header);
129136
int firstViewUnderHeaderPosition = recyclerView.getChildAdapterPosition(viewAfterNextHeader);
130137
View secondHeader = mHeaderProvider.getHeader(recyclerView, firstViewUnderHeaderPosition);
131-
translateHeaderWithNextHeader(recyclerView, mOrientationProvider.getOrientation(recyclerView), bounds,
132-
header, viewAfterNextHeader, secondHeader);
138+
translateHeaderWithNextHeader(recyclerView, mOrientationProvider.getOrientation(recyclerView), bounds, header, viewAfterNextHeader, secondHeader);
133139
}
134140
}
135141

@@ -143,56 +149,61 @@ public Rect getHeaderBounds(RecyclerView recyclerView, View header, View firstVi
143149

144150
private void initDefaultHeaderOffset(Rect headerMargins, RecyclerView recyclerView, View header, View firstView, int orientation, boolean enableStickyHeader) {
145151
int translationX, translationY;
152+
146153
mDimensionCalculator.initMargins(mTempRect1, header);
147154

148-
ViewGroup.LayoutParams layoutParams = firstView.getLayoutParams();
149-
int leftMargin = 0;
150-
int topMargin = 0;
151-
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
152-
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) layoutParams;
153-
leftMargin = marginLayoutParams.leftMargin;
154-
topMargin = marginLayoutParams.topMargin;
155-
}
155+
if (header != null && firstView != null) {
156+
ViewGroup.LayoutParams layoutParams = firstView.getLayoutParams();
157+
int leftMargin = 0;
158+
int topMargin = 0;
159+
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
160+
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) layoutParams;
161+
leftMargin = marginLayoutParams.leftMargin;
162+
topMargin = marginLayoutParams.topMargin;
163+
}
156164

157-
if (orientation == LinearLayoutManager.VERTICAL) {
158-
translationX = firstView.getLeft() - leftMargin + mTempRect1.left;
159-
translationY = enableStickyHeader ?
160-
Math.max(firstView.getTop() - topMargin - header.getHeight() - mTempRect1.bottom, getListTop(recyclerView) + mTempRect1.top) :
161-
firstView.getTop() - topMargin - header.getHeight() - mTempRect1.bottom;
162-
} else {
163-
translationY = firstView.getTop() - topMargin + mTempRect1.top;
164-
translationX = enableStickyHeader ?
165-
Math.max(firstView.getLeft() - leftMargin - header.getWidth() - mTempRect1.right, getListLeft(recyclerView) + mTempRect1.left) :
166-
firstView.getLeft() - leftMargin - header.getWidth() - mTempRect1.right;
167-
}
165+
if (orientation == LinearLayoutManager.VERTICAL) {
166+
translationX = firstView.getLeft() - leftMargin + mTempRect1.left;
167+
translationY = enableStickyHeader ?
168+
Math.max(firstView.getTop() - topMargin - header.getHeight() - mTempRect1.bottom, getListTop(recyclerView) + mTempRect1.top) :
169+
firstView.getTop() - topMargin - header.getHeight() - mTempRect1.bottom;
170+
} else {
171+
translationY = firstView.getTop() - topMargin + mTempRect1.top;
172+
translationX = enableStickyHeader ?
173+
Math.max(firstView.getLeft() - leftMargin - header.getWidth() - mTempRect1.right, getListLeft(recyclerView) + mTempRect1.left) :
174+
firstView.getLeft() - leftMargin - header.getWidth() - mTempRect1.right;
175+
}
168176

169-
headerMargins.set(translationX, translationY, translationX + header.getWidth(), translationY + header.getHeight());
177+
headerMargins.set(translationX, translationY, translationX + header.getWidth(), translationY + header.getHeight());
178+
}
170179
}
171180

172181
private boolean isStickyHeaderBeingPushedOffscreen(RecyclerView recyclerView, View stickyHeader) {
173-
View viewAfterHeader = getFirstViewUnobscuredByHeader(recyclerView, stickyHeader);
174-
int firstViewUnderHeaderPosition = recyclerView.getChildAdapterPosition(viewAfterHeader);
175-
if (firstViewUnderHeaderPosition == RecyclerView.NO_POSITION) {
182+
if (stickyHeader != null) {
183+
View viewAfterHeader = getFirstViewUnobscuredByHeader(recyclerView, stickyHeader);
184+
int firstViewUnderHeaderPosition = recyclerView.getChildAdapterPosition(viewAfterHeader);
185+
if (firstViewUnderHeaderPosition == RecyclerView.NO_POSITION) {
176186
return false;
177-
}
178-
179-
boolean isReverseLayout = mOrientationProvider.isReverseLayout(recyclerView);
180-
if (firstViewUnderHeaderPosition > 0 && hasNewHeader(firstViewUnderHeaderPosition, isReverseLayout)) {
181-
View nextHeader = mHeaderProvider.getHeader(recyclerView, firstViewUnderHeaderPosition);
182-
mDimensionCalculator.initMargins(mTempRect1, nextHeader);
183-
mDimensionCalculator.initMargins(mTempRect2, stickyHeader);
187+
}
184188

185-
if (mOrientationProvider.getOrientation(recyclerView) == LinearLayoutManager.VERTICAL) {
186-
int topOfNextHeader = viewAfterHeader.getTop() - mTempRect1.bottom - nextHeader.getHeight() - mTempRect1.top;
187-
int bottomOfThisHeader = recyclerView.getPaddingTop() + stickyHeader.getBottom() + mTempRect2.top + mTempRect2.bottom;
188-
if (topOfNextHeader < bottomOfThisHeader) {
189-
return true;
190-
}
191-
} else {
192-
int leftOfNextHeader = viewAfterHeader.getLeft() - mTempRect1.right - nextHeader.getWidth() - mTempRect1.left;
193-
int rightOfThisHeader = recyclerView.getPaddingLeft() + stickyHeader.getRight() + mTempRect2.left + mTempRect2.right;
194-
if (leftOfNextHeader < rightOfThisHeader) {
195-
return true;
189+
boolean isReverseLayout = mOrientationProvider.isReverseLayout(recyclerView);
190+
if (firstViewUnderHeaderPosition > 0 && hasNewHeader(firstViewUnderHeaderPosition, isReverseLayout)) {
191+
View nextHeader = mHeaderProvider.getHeader(recyclerView, firstViewUnderHeaderPosition);
192+
mDimensionCalculator.initMargins(mTempRect1, nextHeader);
193+
mDimensionCalculator.initMargins(mTempRect2, stickyHeader);
194+
195+
if (mOrientationProvider.getOrientation(recyclerView) == LinearLayoutManager.VERTICAL) {
196+
int topOfNextHeader = viewAfterHeader.getTop() - mTempRect1.bottom - nextHeader.getHeight() - mTempRect1.top;
197+
int bottomOfThisHeader = recyclerView.getPaddingTop() + stickyHeader.getBottom() + mTempRect2.top + mTempRect2.bottom;
198+
if (topOfNextHeader < bottomOfThisHeader) {
199+
return true;
200+
}
201+
} else {
202+
int leftOfNextHeader = viewAfterHeader.getLeft() - mTempRect1.right - nextHeader.getWidth() - mTempRect1.left;
203+
int rightOfThisHeader = recyclerView.getPaddingLeft() + stickyHeader.getRight() + mTempRect2.left + mTempRect2.right;
204+
if (leftOfNextHeader < rightOfThisHeader) {
205+
return true;
206+
}
196207
}
197208
}
198209
}
@@ -202,8 +213,10 @@ private boolean isStickyHeaderBeingPushedOffscreen(RecyclerView recyclerView, Vi
202213

203214
private void translateHeaderWithNextHeader(RecyclerView recyclerView, int orientation, Rect translation,
204215
View currentHeader, View viewAfterNextHeader, View nextHeader) {
216+
205217
mDimensionCalculator.initMargins(mTempRect1, nextHeader);
206218
mDimensionCalculator.initMargins(mTempRect2, currentHeader);
219+
207220
if (orientation == LinearLayoutManager.VERTICAL) {
208221
int topOfStickyHeader = getListTop(recyclerView) + mTempRect2.top + mTempRect2.bottom;
209222
int shiftFromNextHeader = viewAfterNextHeader.getTop() - nextHeader.getHeight() - mTempRect1.bottom - mTempRect1.top - currentHeader.getHeight() - topOfStickyHeader;

library/src/main/java/com/timehop/stickyheadersrecyclerview/caching/HeaderViewCache.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ public class HeaderViewCache implements HeaderProvider {
1818
private final LongSparseArray<View> mHeaderViews = new LongSparseArray<>();
1919
private final OrientationProvider mOrientationProvider;
2020

21-
public HeaderViewCache(StickyRecyclerHeadersAdapter adapter,
22-
OrientationProvider orientationProvider) {
21+
public HeaderViewCache(StickyRecyclerHeadersAdapter adapter, OrientationProvider orientationProvider) {
2322
mAdapter = adapter;
2423
mOrientationProvider = orientationProvider;
2524
}
@@ -29,8 +28,8 @@ public View getHeader(RecyclerView parent, int position) {
2928
long headerId = mAdapter.getHeaderId(position);
3029

3130
View header = mHeaderViews.get(headerId);
31+
3232
if (header == null) {
33-
//TODO - recycle views
3433
RecyclerView.ViewHolder viewHolder = mAdapter.onCreateHeaderViewHolder(parent, position);
3534
mAdapter.onBindHeaderViewHolder(viewHolder, position);
3635
header = viewHolder.itemView;
@@ -49,14 +48,15 @@ public View getHeader(RecyclerView parent, int position) {
4948
heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.EXACTLY);
5049
}
5150

52-
int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
53-
parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width);
54-
int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
55-
parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height);
51+
int childWidth = ViewGroup.getChildMeasureSpec(widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width);
52+
int childHeight = ViewGroup.getChildMeasureSpec(heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height);
53+
5654
header.measure(childWidth, childHeight);
5755
header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
56+
5857
mHeaderViews.put(headerId, header);
5958
}
59+
6060
return header;
6161
}
6262

library/src/main/java/com/timehop/stickyheadersrecyclerview/calculation/DimensionCalculator.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class DimensionCalculator {
1919
* @param view for which to get margins
2020
*/
2121
public void initMargins(Rect margins, View view) {
22-
LayoutParams layoutParams = view.getLayoutParams();
22+
LayoutParams layoutParams = view != null ? view.getLayoutParams() : null;
2323

24-
if (layoutParams instanceof MarginLayoutParams) {
24+
if (layoutParams != null && layoutParams instanceof MarginLayoutParams) {
2525
initMarginRect(margins, (MarginLayoutParams) layoutParams);
2626
} else {
2727
margins.set(0, 0, 0, 0);
@@ -36,18 +36,20 @@ public void initMargins(Rect margins, View view) {
3636
* @param marginLayoutParams margins to populate the Rect with
3737
*/
3838
private void initMarginRect(Rect marginRect, MarginLayoutParams marginLayoutParams) {
39+
if (marginLayoutParams != null) {
3940
marginRect.set(
40-
marginLayoutParams.leftMargin,
41-
marginLayoutParams.topMargin,
42-
marginLayoutParams.rightMargin,
43-
marginLayoutParams.bottomMargin
44-
);
41+
marginLayoutParams.leftMargin,
42+
marginLayoutParams.topMargin,
43+
marginLayoutParams.rightMargin,
44+
marginLayoutParams.bottomMargin
45+
);
46+
}
4547
}
4648

4749
public Rect getMarginRect(View header) {
4850
Rect rect = new Rect();
4951

50-
if (header.getLayoutParams() instanceof MarginLayoutParams) {
52+
if (header != null && header.getLayoutParams() instanceof MarginLayoutParams) {
5153
initMarginRect(rect, (MarginLayoutParams) header.getLayoutParams());
5254
} else {
5355
rect.set(0, 0, 0, 0);

sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/MainActivity.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,15 @@ private void reorderItems() {
225225
if (getFirstChar(item) != firstCharOnLastItem) { // new header found for item
226226
int numColumnOfItem = i % getNumColumns();
227227
if (numColumnOfItem > 0 && !EMPTY_NAME.equals(item)) { // fill row with empty items
228-
int emptyVideos = getNumColumns() - numColumnOfItem;
229-
for (int j = 0; j < emptyVideos; j++) {
228+
int emptyRows = getNumColumns() - numColumnOfItem;
229+
for (int j = 0; j < emptyRows; j++) {
230230
items.add(i, EMPTY_NAME);
231-
if (j != emptyVideos - 1) {
231+
if (j != emptyRows - 1) {
232232
i++;
233233
}
234234
}
235235
continue;
236-
} else if (numColumnOfItem == 0 && EMPTY_NAME.equals(item)){
236+
} else if (numColumnOfItem == 0 && EMPTY_NAME.equals(item)) {
237237
// remove empty items to avoid empty rows when removing items
238238
while (items.get(i).equals(EMPTY_NAME)) {
239239
items.remove(i);

0 commit comments

Comments
 (0)