Skip to content

Commit f190b9d

Browse files
committed
Merge pull request timehop#90 from johngray1965/master
Added a check when searching for position of header, that the header …
2 parents cb962e8 + 904c28d commit f190b9d

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ The StickyHeaders aren't aware of your adapter so if you must notify them when y
8383
});
8484
```
8585

86+
If the Reccylerview's layout manager implements getExtraLayoutSpace (to preload more content then is visible for preformance resaons), you must implment ItemVisibilityAdapter and pass an instance as a second argment to StickyRecyclerHeadersDecoration's constuctor.
87+
```java
88+
@Override
89+
public boolean isPositionVisible(final int position) {
90+
return layoutManager.findFirstVisibleItemPosition() <= position
91+
&& layoutManager.findLastVisibleItemPosition() >= position;
92+
}
93+
```
94+
95+
8696
Item animators don't play nicely with RecyclerView decorations, so your mileage with that may vary.
8797

8898
Compatibility
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.timehop.stickyheadersrecyclerview;
2+
3+
/**
4+
* ItemVisibilityAdapter provides a way for StickyRecyclerHeadersDecoration
5+
* to know if a row is visible or not. This comes into play if the
6+
* recyclerview's layout manager is set up to provide extra layout space (by
7+
* overriding getExtraLayoutSpace). In this case rows that aren't visible (yet)
8+
* will be bound and StickyRecyclerHeadersDecoration will need to know which
9+
* are visible to correctly calculate the row to base the sticky header on
10+
*
11+
* To use it you must pass an instance of a class that implements this
12+
* interface as a second argment StickyRecyclerHeadersDecoration's constructor.
13+
*
14+
*/
15+
public interface ItemVisibilityAdapter {
16+
17+
/**
18+
*
19+
* Return true the specified adapter position is visible, false otherwise
20+
*
21+
* The implementation of this method will typically return true if
22+
* the position is between the layout manager's findFirstVisibleItemPosition
23+
* and findLastVisibleItemPosition (inclusive).
24+
*
25+
* @param position the adapter position
26+
*/
27+
boolean isPositionVisible(final int position);
28+
}

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

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
public class StickyRecyclerHeadersDecoration extends RecyclerView.ItemDecoration {
1818

1919
private final StickyRecyclerHeadersAdapter mAdapter;
20+
private final ItemVisibilityAdapter mVisibilityAdapter;
2021
private final SparseArray<Rect> mHeaderRects = new SparseArray<>();
2122
private final HeaderProvider mHeaderProvider;
2223
private final OrientationProvider mOrientationProvider;
@@ -32,31 +33,36 @@ public class StickyRecyclerHeadersDecoration extends RecyclerView.ItemDecoration
3233

3334
// TODO: Consider passing in orientation to simplify orientation accounting within calculation
3435
public StickyRecyclerHeadersDecoration(StickyRecyclerHeadersAdapter adapter) {
35-
this(adapter, new LinearLayoutOrientationProvider(), new DimensionCalculator());
36+
this(adapter, new LinearLayoutOrientationProvider(), new DimensionCalculator(), null);
37+
}
38+
39+
public StickyRecyclerHeadersDecoration(StickyRecyclerHeadersAdapter adapter, ItemVisibilityAdapter visibilityAdapter) {
40+
this(adapter, new LinearLayoutOrientationProvider(), new DimensionCalculator(), visibilityAdapter);
3641
}
3742

3843
private StickyRecyclerHeadersDecoration(StickyRecyclerHeadersAdapter adapter, OrientationProvider orientationProvider,
39-
DimensionCalculator dimensionCalculator) {
44+
DimensionCalculator dimensionCalculator, ItemVisibilityAdapter visibilityAdapter) {
4045
this(adapter, orientationProvider, dimensionCalculator, new HeaderRenderer(orientationProvider),
41-
new HeaderViewCache(adapter, orientationProvider));
46+
new HeaderViewCache(adapter, orientationProvider), visibilityAdapter);
4247
}
4348

4449
private StickyRecyclerHeadersDecoration(StickyRecyclerHeadersAdapter adapter, OrientationProvider orientationProvider,
45-
DimensionCalculator dimensionCalculator, HeaderRenderer headerRenderer, HeaderProvider headerProvider) {
50+
DimensionCalculator dimensionCalculator, HeaderRenderer headerRenderer, HeaderProvider headerProvider, ItemVisibilityAdapter visibilityAdapter) {
4651
this(adapter, headerRenderer, orientationProvider, dimensionCalculator, headerProvider,
4752
new HeaderPositionCalculator(adapter, headerProvider, orientationProvider,
48-
dimensionCalculator));
53+
dimensionCalculator), visibilityAdapter);
4954
}
5055

5156
private StickyRecyclerHeadersDecoration(StickyRecyclerHeadersAdapter adapter, HeaderRenderer headerRenderer,
5257
OrientationProvider orientationProvider, DimensionCalculator dimensionCalculator, HeaderProvider headerProvider,
53-
HeaderPositionCalculator headerPositionCalculator) {
58+
HeaderPositionCalculator headerPositionCalculator, ItemVisibilityAdapter visibilityAdapter) {
5459
mAdapter = adapter;
5560
mHeaderProvider = headerProvider;
5661
mOrientationProvider = orientationProvider;
5762
mRenderer = headerRenderer;
5863
mDimensionCalculator = dimensionCalculator;
5964
mHeaderPositionCalculator = headerPositionCalculator;
65+
mVisibilityAdapter = visibilityAdapter;
6066
}
6167

6268
@Override
@@ -130,7 +136,10 @@ public int findHeaderPositionUnder(int x, int y) {
130136
for (int i = 0; i < mHeaderRects.size(); i++) {
131137
Rect rect = mHeaderRects.get(mHeaderRects.keyAt(i));
132138
if (rect.contains(x, y)) {
133-
return mHeaderRects.keyAt(i);
139+
int position = mHeaderRects.keyAt(i);
140+
if (mVisibilityAdapter == null || mVisibilityAdapter.isPositionVisible(position)) {
141+
return position;
142+
}
134143
}
135144
}
136145
return -1;

0 commit comments

Comments
 (0)