Skip to content

Commit 065575a

Browse files
author
Rafael Dominiquini
committed
added position change listener
1 parent 5fc9f9d commit 065575a

File tree

10 files changed

+144
-30
lines changed

10 files changed

+144
-30
lines changed

build.gradle

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
jcenter()
66
}
77
dependencies {
8-
classpath 'com.android.tools.build:gradle:1.5.0'
8+
classpath 'com.android.tools.build:gradle:2.0.0'
99

1010
// NOTE: Do not place your application dependencies here; they belong
1111
// in the individual module build.gradle files
@@ -20,10 +20,10 @@ allprojects {
2020

2121
ext {
2222
compileSdkVersion = 23
23-
buildToolsVersion = '23.0.2'
24-
supportLibsVersion = '23.1.1'
25-
targetSdkVersion = 22
23+
buildToolsVersion = '23.0.3'
24+
supportLibsVersion = '23.3.0'
25+
targetSdkVersion = 23
2626
minSdkVersion = 11
27-
versionCode = 13
28-
versionName = "0.4.3-1"
27+
versionCode = 15
28+
versionName = "0.5.5"
2929
}

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ private boolean indexOutOfBounds(int position) {
9494
return position < 0 || position >= mAdapter.getItemCount();
9595
}
9696

97+
/**
98+
* Verify if header obscure some item on RecyclerView
99+
*
100+
* @param parent RecyclerView containing all the list items
101+
* @return first item that is fully beneath a header
102+
*/
103+
public boolean headerObscuringSomeItem(RecyclerView parent, View firstHeader) {
104+
for (int i = 0; i < parent.getChildCount(); i++) {
105+
View child = parent.getChildAt(i);
106+
if (itemIsObscuredByHeader(parent, child, firstHeader, mOrientationProvider.getOrientation(parent))) {
107+
return true;
108+
}
109+
}
110+
return false;
111+
}
112+
97113
public void initHeaderBounds(Rect bounds, RecyclerView recyclerView, View header, View firstView, boolean firstHeader) {
98114
int orientation = mOrientationProvider.getOrientation(recyclerView);
99115
initDefaultHeaderOffset(bounds, recyclerView, header, firstView, orientation);

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class StickyRecyclerHeadersDecoration extends RecyclerView.ItemDecoration
2424
private final HeaderPositionCalculator mHeaderPositionCalculator;
2525
private final HeaderRenderer mRenderer;
2626
private final DimensionCalculator mDimensionCalculator;
27+
private StickyRecyclerHeadersPositionChangeListener mHeaderListener;
2728

2829
/**
2930
* The following field is used as a buffer for internal calculations. Its sole purpose is to avoid
@@ -121,10 +122,24 @@ public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State st
121122
}
122123
mHeaderPositionCalculator.initHeaderBounds(headerOffset, parent, header, itemView, hasStickyHeader);
123124
mRenderer.drawHeader(parent, canvas, header, headerOffset);
125+
126+
if (mHeaderListener != null) {
127+
mHeaderListener.onHeaderPositionChanged(this, mAdapter.getHeaderId(position), header, position, headerOffset);
128+
}
124129
}
125130
}
126131
}
127132

133+
/**
134+
* Verify if header obscure some item on RecyclerView
135+
*
136+
* @param header The header to verify
137+
* @return first item that is fully beneath a header
138+
*/
139+
public boolean headerObscuringSomeItem(RecyclerView recyclerView, View header) {
140+
return mHeaderPositionCalculator.headerObscuringSomeItem(recyclerView, header);
141+
}
142+
128143
/**
129144
* Gets the position of the header under the specified (x, y) coordinates.
130145
*
@@ -165,4 +180,8 @@ public void invalidateHeaders() {
165180
mHeaderProvider.invalidate();
166181
mHeaderRects.clear();
167182
}
183+
184+
public void setHeaderPositionListener(StickyRecyclerHeadersPositionChangeListener headerListener) {
185+
this.mHeaderListener = headerListener;
186+
}
168187
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.timehop.stickyheadersrecyclerview;
2+
3+
import android.graphics.Rect;
4+
import android.view.View;
5+
6+
/**
7+
* Created by Rafael Baboni Dominiquini on 13/04/16.
8+
*/
9+
public interface StickyRecyclerHeadersPositionChangeListener {
10+
/**
11+
* <p>Called for each header get redrawn.</p>
12+
* <p>Notice coordinates may not actually change for some of the headers
13+
* it's up to the client to track actual coordinates changes</p>
14+
*
15+
* @param headerId id of the header being redrawn
16+
* @param headerRect new coordinates for the header
17+
*/
18+
void onHeaderPositionChanged(StickyRecyclerHeadersDecoration decor, long headerId, View header, int position, Rect headerRect);
19+
}

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.timehop.stickyheadersrecyclerview.sample;
22

33
import android.content.pm.ActivityInfo;
4+
import android.content.res.Resources;
45
import android.graphics.Color;
6+
import android.graphics.Rect;
57
import android.os.Bundle;
68
import android.os.Handler;
79
import android.os.Looper;
810
import android.support.v7.app.AppCompatActivity;
911
import android.support.v7.widget.LinearLayoutManager;
1012
import android.support.v7.widget.RecyclerView;
13+
import android.util.Log;
1114
import android.view.LayoutInflater;
1215
import android.view.View;
1316
import android.view.ViewGroup;
@@ -18,6 +21,7 @@
1821

1922
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter;
2023
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration;
24+
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersPositionChangeListener;
2125
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersTouchListener;
2226

2327
import java.security.SecureRandom;
@@ -65,6 +69,18 @@ public void run() {
6569
final StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(adapter);
6670
recyclerView.addItemDecoration(headersDecor);
6771

72+
headersDecor.setHeaderPositionListener(new StickyRecyclerHeadersPositionChangeListener() {
73+
@Override
74+
public void onHeaderPositionChanged(StickyRecyclerHeadersDecoration decor, long headerId, View header, int position, Rect headerRect) {
75+
boolean headerIsOnTop = header != null && headerRect != null && headerRect.top <= (16 * Resources.getSystem().getDisplayMetrics().density);
76+
boolean headerIsObscuringSomeView = headerIsOnTop && decor.headerObscuringSomeItem(recyclerView, header);
77+
78+
Log.i(MainActivity.class.getSimpleName(), String.format("ON_TOP: %s | OBSCURING_SOME_VIEW: %s", headerIsOnTop, headerIsObscuringSomeView));
79+
80+
header.findViewById(R.id.header_shadow).setVisibility(headerIsObscuringSomeView ? View.VISIBLE : View.INVISIBLE);
81+
}
82+
});
83+
6884
// Add decoration for dividers between list items
6985
recyclerView.addItemDecoration(new DividerDecoration(this));
7086

@@ -151,8 +167,9 @@ public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent, int po
151167

152168
@Override
153169
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) {
154-
TextView textView = (TextView) holder.itemView;
170+
TextView textView = (TextView) holder.itemView.findViewById(R.id.header_text);
155171
textView.setText(String.valueOf(getItem(position).charAt(0)));
172+
156173
holder.itemView.setBackgroundColor(getRandomColor());
157174
}
158175

@@ -162,6 +179,5 @@ private int getRandomColor() {
162179
rgen.nextInt(359), 1, 1
163180
});
164181
}
165-
166182
}
167183
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:shape="rectangle">
4+
5+
<gradient android:startColor="@android:color/transparent"
6+
android:endColor="#44333333"
7+
android:angle="90"/>
8+
9+
</shape>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:shape="rectangle">
4+
5+
<gradient android:startColor="@android:color/transparent"
6+
android:endColor="#44333333"
7+
android:angle="00"/>
8+
9+
</shape>
Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
<?xml version="1.0" encoding="utf-8"?>
22

3-
<TextView
4-
xmlns:android="http://schemas.android.com/apk/res/android"
3+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
54
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="wrap_content"
67
android:orientation="horizontal"
7-
android:layout_width="wrap_content"
8-
android:layout_height="match_parent"
9-
android:padding="@dimen/small"
10-
android:background="#001F3F"
11-
android:textSize="24sp"
12-
android:textColor="@android:color/white"
13-
android:gravity="center_vertical"
14-
tools:text="Animals starting with A"
15-
tools:context=".MainActivity"/>
8+
tools:context=".MainActivity">
9+
10+
<TextView
11+
android:id="@+id/header_text"
12+
android:layout_width="wrap_content"
13+
android:layout_height="match_parent"
14+
android:gravity="center_vertical"
15+
android:orientation="horizontal"
16+
android:padding="@dimen/small"
17+
android:textColor="@android:color/white"
18+
android:textSize="24sp"
19+
tools:text="Animals starting with A" />
20+
21+
<View
22+
android:id="@+id/header_shadow"
23+
android:layout_width="4dp"
24+
android:layout_height="match_parent"
25+
android:alpha="0.64"
26+
android:background="@drawable/shadow_vertical" />
27+
28+
</LinearLayout>
Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
<?xml version="1.0" encoding="utf-8"?>
22

3-
<TextView
4-
xmlns:android="http://schemas.android.com/apk/res/android"
3+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
54
xmlns:tools="http://schemas.android.com/tools"
6-
android:orientation="horizontal"
75
android:layout_width="match_parent"
86
android:layout_height="wrap_content"
9-
android:padding="16dp"
10-
android:background="#001F3F"
11-
android:textSize="28sp"
12-
android:textStyle="bold"
13-
android:textColor="@android:color/white"
14-
tools:text="Animals starting with A"
15-
tools:context=".MainActivity"/>
7+
android:orientation="vertical"
8+
tools:context=".MainActivity">
9+
10+
<TextView
11+
android:id="@+id/header_text"
12+
android:layout_width="match_parent"
13+
android:layout_height="wrap_content"
14+
android:orientation="horizontal"
15+
android:padding="16dp"
16+
android:textColor="@android:color/white"
17+
android:textSize="28sp"
18+
android:textStyle="bold"
19+
tools:text="Animals starting with A" />
20+
21+
<View
22+
android:id="@+id/header_shadow"
23+
android:layout_width="wrap_content"
24+
android:layout_height="4dp"
25+
android:alpha="0.64"
26+
android:background="@drawable/shadow_horizontal" />
27+
28+
</LinearLayout>

0 commit comments

Comments
 (0)