@@ -20,6 +20,13 @@ public class HeaderPositionCalculator {
2020 private final HeaderProvider mHeaderProvider ;
2121 private final DimensionCalculator mDimensionCalculator ;
2222
23+ /**
24+ * The following fields are used as buffers for internal calculations. Their sole purpose is to avoid
25+ * allocating new Rect every time we need one.
26+ */
27+ private final Rect mTempRect1 = new Rect ();
28+ private final Rect mTempRect2 = new Rect ();
29+
2330 public HeaderPositionCalculator (StickyRecyclerHeadersAdapter adapter , HeaderProvider headerProvider ,
2431 OrientationProvider orientationProvider , DimensionCalculator dimensionCalculator ) {
2532 mAdapter = adapter ;
@@ -41,12 +48,13 @@ public HeaderPositionCalculator(StickyRecyclerHeadersAdapter adapter, HeaderProv
4148 */
4249 public boolean hasStickyHeader (View itemView , int orientation , int position ) {
4350 int offset , margin ;
51+ mDimensionCalculator .initMargins (mTempRect1 , itemView );
4452 if (orientation == LinearLayout .VERTICAL ) {
4553 offset = itemView .getTop ();
46- margin = mDimensionCalculator . getMargins ( itemView ) .top ;
54+ margin = mTempRect1 .top ;
4755 } else {
4856 offset = itemView .getLeft ();
49- margin = mDimensionCalculator . getMargins ( itemView ) .left ;
57+ margin = mTempRect1 .left ;
5058 }
5159
5260 return offset <= margin && mAdapter .getHeaderId (position ) >= 0 ;
@@ -86,9 +94,9 @@ private boolean indexOutOfBounds(int position) {
8694 return position < 0 || position >= mAdapter .getItemCount ();
8795 }
8896
89- public Rect getHeaderBounds ( RecyclerView recyclerView , View header , View firstView , boolean firstHeader ) {
97+ public void initHeaderBounds ( Rect bounds , RecyclerView recyclerView , View header , View firstView , boolean firstHeader ) {
9098 int orientation = mOrientationProvider .getOrientation (recyclerView );
91- Rect bounds = getDefaultHeaderOffset ( recyclerView , header , firstView , orientation );
99+ initDefaultHeaderOffset ( bounds , recyclerView , header , firstView , orientation );
92100
93101 if (firstHeader && isStickyHeaderBeingPushedOffscreen (recyclerView , header )) {
94102 View viewAfterNextHeader = getFirstViewUnobscuredByHeader (recyclerView , header );
@@ -97,27 +105,25 @@ public Rect getHeaderBounds(RecyclerView recyclerView, View header, View firstVi
97105 translateHeaderWithNextHeader (recyclerView , mOrientationProvider .getOrientation (recyclerView ), bounds ,
98106 header , viewAfterNextHeader , secondHeader );
99107 }
100-
101- return bounds ;
102108 }
103109
104- private Rect getDefaultHeaderOffset ( RecyclerView recyclerView , View header , View firstView , int orientation ) {
110+ private void initDefaultHeaderOffset ( Rect headerMargins , RecyclerView recyclerView , View header , View firstView , int orientation ) {
105111 int translationX , translationY ;
106- Rect headerMargins = mDimensionCalculator .getMargins ( header );
112+ mDimensionCalculator .initMargins ( mTempRect1 , header );
107113 if (orientation == LinearLayoutManager .VERTICAL ) {
108- translationX = firstView .getLeft () + headerMargins .left ;
114+ translationX = firstView .getLeft () + mTempRect1 .left ;
109115 translationY = Math .max (
110- firstView .getTop () - header .getHeight () - headerMargins .bottom ,
111- getListTop (recyclerView ) + headerMargins .top );
116+ firstView .getTop () - header .getHeight () - mTempRect1 .bottom ,
117+ getListTop (recyclerView ) + mTempRect1 .top );
112118 } else {
113- translationY = firstView .getTop () + headerMargins .top ;
119+ translationY = firstView .getTop () + mTempRect1 .top ;
114120 translationX = Math .max (
115- firstView .getLeft () - header .getWidth () - headerMargins .right ,
116- getListLeft (recyclerView ) + headerMargins .left );
121+ firstView .getLeft () - header .getWidth () - mTempRect1 .right ,
122+ getListLeft (recyclerView ) + mTempRect1 .left );
117123 }
118124
119- return new Rect (translationX , translationY , translationX + header .getWidth (),
120- translationY + header .getHeight ());
125+ headerMargins . set (translationX , translationY , translationX + header .getWidth (),
126+ translationY + header .getHeight ());
121127 }
122128
123129 private boolean isStickyHeaderBeingPushedOffscreen (RecyclerView recyclerView , View stickyHeader ) {
@@ -130,18 +136,18 @@ private boolean isStickyHeaderBeingPushedOffscreen(RecyclerView recyclerView, Vi
130136 boolean isReverseLayout = mOrientationProvider .isReverseLayout (recyclerView );
131137 if (firstViewUnderHeaderPosition > 0 && hasNewHeader (firstViewUnderHeaderPosition , isReverseLayout )) {
132138 View nextHeader = mHeaderProvider .getHeader (recyclerView , firstViewUnderHeaderPosition );
133- Rect nextHeaderMargins = mDimensionCalculator .getMargins ( nextHeader );
134- Rect headerMargins = mDimensionCalculator .getMargins ( stickyHeader );
139+ mDimensionCalculator .initMargins ( mTempRect1 , nextHeader );
140+ mDimensionCalculator .initMargins ( mTempRect2 , stickyHeader );
135141
136142 if (mOrientationProvider .getOrientation (recyclerView ) == LinearLayoutManager .VERTICAL ) {
137- int topOfNextHeader = viewAfterHeader .getTop () - nextHeaderMargins .bottom - nextHeader .getHeight () - nextHeaderMargins .top ;
138- int bottomOfThisHeader = recyclerView .getPaddingTop () + stickyHeader .getBottom () + headerMargins .top + headerMargins .bottom ;
143+ int topOfNextHeader = viewAfterHeader .getTop () - mTempRect1 .bottom - nextHeader .getHeight () - mTempRect1 .top ;
144+ int bottomOfThisHeader = recyclerView .getPaddingTop () + stickyHeader .getBottom () + mTempRect2 .top + mTempRect2 .bottom ;
139145 if (topOfNextHeader < bottomOfThisHeader ) {
140146 return true ;
141147 }
142148 } else {
143- int leftOfNextHeader = viewAfterHeader .getLeft () - nextHeaderMargins .right - nextHeader .getWidth () - nextHeaderMargins .left ;
144- int rightOfThisHeader = recyclerView .getPaddingLeft () + stickyHeader .getRight () + headerMargins .left + headerMargins .right ;
149+ int leftOfNextHeader = viewAfterHeader .getLeft () - mTempRect1 .right - nextHeader .getWidth () - mTempRect1 .left ;
150+ int rightOfThisHeader = recyclerView .getPaddingLeft () + stickyHeader .getRight () + mTempRect2 .left + mTempRect2 .right ;
145151 if (leftOfNextHeader < rightOfThisHeader ) {
146152 return true ;
147153 }
@@ -152,18 +158,18 @@ private boolean isStickyHeaderBeingPushedOffscreen(RecyclerView recyclerView, Vi
152158 }
153159
154160 private void translateHeaderWithNextHeader (RecyclerView recyclerView , int orientation , Rect translation ,
155- View currentHeader , View viewAfterNextHeader , View nextHeader ) {
156- Rect nextHeaderMargins = mDimensionCalculator .getMargins ( nextHeader );
157- Rect stickyHeaderMargins = mDimensionCalculator .getMargins ( currentHeader );
161+ View currentHeader , View viewAfterNextHeader , View nextHeader ) {
162+ mDimensionCalculator .initMargins ( mTempRect1 , nextHeader );
163+ mDimensionCalculator .initMargins ( mTempRect2 , currentHeader );
158164 if (orientation == LinearLayoutManager .VERTICAL ) {
159- int topOfStickyHeader = getListTop (recyclerView ) + stickyHeaderMargins .top + stickyHeaderMargins .bottom ;
160- int shiftFromNextHeader = viewAfterNextHeader .getTop () - nextHeader .getHeight () - nextHeaderMargins .bottom - nextHeaderMargins .top - currentHeader .getHeight () - topOfStickyHeader ;
165+ int topOfStickyHeader = getListTop (recyclerView ) + mTempRect2 .top + mTempRect2 .bottom ;
166+ int shiftFromNextHeader = viewAfterNextHeader .getTop () - nextHeader .getHeight () - mTempRect1 .bottom - mTempRect1 .top - currentHeader .getHeight () - topOfStickyHeader ;
161167 if (shiftFromNextHeader < topOfStickyHeader ) {
162168 translation .top += shiftFromNextHeader ;
163169 }
164170 } else {
165- int leftOfStickyHeader = getListLeft (recyclerView ) + stickyHeaderMargins .left + stickyHeaderMargins .right ;
166- int shiftFromNextHeader = viewAfterNextHeader .getLeft () - nextHeader .getWidth () - nextHeaderMargins .right - nextHeaderMargins .left - currentHeader .getWidth () - leftOfStickyHeader ;
171+ int leftOfStickyHeader = getListLeft (recyclerView ) + mTempRect2 .left + mTempRect2 .right ;
172+ int shiftFromNextHeader = viewAfterNextHeader .getLeft () - nextHeader .getWidth () - mTempRect1 .right - mTempRect1 .left - currentHeader .getWidth () - leftOfStickyHeader ;
167173 if (shiftFromNextHeader < leftOfStickyHeader ) {
168174 translation .left += shiftFromNextHeader ;
169175 }
@@ -201,7 +207,7 @@ private View getFirstViewUnobscuredByHeader(RecyclerView parent, View firstHeade
201207 */
202208 private boolean itemIsObscuredByHeader (RecyclerView parent , View item , View header , int orientation ) {
203209 RecyclerView .LayoutParams layoutParams = (RecyclerView .LayoutParams ) item .getLayoutParams ();
204- Rect headerMargins = mDimensionCalculator .getMargins ( header );
210+ mDimensionCalculator .initMargins ( mTempRect1 , header );
205211
206212 int adapterPosition = parent .getChildAdapterPosition (item );
207213 if (adapterPosition == RecyclerView .NO_POSITION || mHeaderProvider .getHeader (parent , adapterPosition ) != header ) {
@@ -212,13 +218,13 @@ private boolean itemIsObscuredByHeader(RecyclerView parent, View item, View head
212218
213219 if (orientation == LinearLayoutManager .VERTICAL ) {
214220 int itemTop = item .getTop () - layoutParams .topMargin ;
215- int headerBottom = header .getBottom () + headerMargins .bottom + headerMargins .top ;
221+ int headerBottom = header .getBottom () + mTempRect1 .bottom + mTempRect1 .top ;
216222 if (itemTop > headerBottom ) {
217223 return false ;
218224 }
219225 } else {
220226 int itemLeft = item .getLeft () - layoutParams .leftMargin ;
221- int headerRight = header .getRight () + headerMargins .right + headerMargins .left ;
227+ int headerRight = header .getRight () + mTempRect1 .right + mTempRect1 .left ;
222228 if (itemLeft > headerRight ) {
223229 return false ;
224230 }
0 commit comments