Skip to content

Commit

Permalink
Merge pull request #1 from emilsjolander/master
Browse files Browse the repository at this point in the history
sync with master
  • Loading branch information
lsjwzh committed Jul 3, 2014
2 parents 3208d9c + 750b432 commit 6e6c87c
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 68 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ public void setDrawingListUnderStickyHeader(boolean drawingListUnderStickyHeader
public boolean isDrawingListUnderStickyHeader();
```

If you are using a transparent action bar the following getter+setter will be very helpful. Use them to set the position of the sticky header from the top of the view.
```java
public void setStickyHeaderTopOffset(int stickyHeaderTopOffset);
public int getStickyHeaderTopOffset();
```

Contributing
------------
Contributions are very welcome. Now that this library has grown in popularity i have a hard time keeping upp with all the issues while tending to a multitude of other projects as well as school. So if you find a bug in the library or want a feature and think you can fix it yourself, fork + pull request and i will greatly appreciate it!
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
classpath 'com.android.tools.build:gradle:0.11.+'
}
}

Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION_NAME=2.3.0
VERSION_NAME=2.4.0
GROUP=se.emilsjolander

POM_DESCRIPTION=A small android library that makes it easy to make lists with section headers that stick to the top until a new section header comes along.
Expand All @@ -11,3 +11,4 @@ POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=emilsjolander
POM_DEVELOPER_NAME=Emil Sjolander
POM_DEVELOPER_EMAIL[email protected]
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply plugin: 'android-library'

android {
compileSdkVersion 19
buildToolsVersion '19.0.3'
buildToolsVersion '19.1.0'

sourceSets {
main {
Expand All @@ -13,4 +13,4 @@ android {
}
}

apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/eaa6b5404b7594e6c23b884fdc5795f545db55dd/gradle-mvn-push.gradle'
apply from: 'https://raw.github.com/shamanland/gradle-mvn-push/cc18d56549cdea03f744b6fff27911569394073e/gradle-mvn-push.gradle'
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ void onStickyHeaderChanged(StickyListHeadersListView l, View header,
private boolean mAreHeadersSticky = true;
private boolean mClippingToPadding = true;
private boolean mIsDrawingListUnderStickyHeader = true;
private int mStickyHeaderTopOffset = 0;
private int mPaddingLeft = 0;
private int mPaddingTop = 0;
private int mPaddingRight = 0;
Expand Down Expand Up @@ -136,8 +137,7 @@ public StickyListHeadersListView(Context context, AttributeSet attrs, int defSty
mPaddingRight = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingRight, padding);
mPaddingBottom = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingBottom, padding);

setPadding(mPaddingLeft, mPaddingTop, mPaddingRight,
mPaddingBottom);
setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);

// Set clip to padding on the list and reset value to default on
// wrapper
Expand Down Expand Up @@ -230,10 +230,11 @@ private void ensureHeaderHasCorrectLayoutParams(View header) {
ViewGroup.LayoutParams lp = header.getLayoutParams();
if (lp == null) {
lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
header.setLayoutParams(lp);
} else if (lp.height == LayoutParams.MATCH_PARENT) {
lp.height = LayoutParams.WRAP_CONTENT;
header.setLayoutParams(lp);
}
header.setLayoutParams(lp);
}

private void measureHeader(View header) {
Expand All @@ -249,16 +250,11 @@ private void measureHeader(View header) {
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mList.layout(0, 0, mList.getMeasuredWidth(), getHeight());
if (mHeader != null) {
MarginLayoutParams lp = (MarginLayoutParams) mHeader
.getLayoutParams();
int headerTop = lp.topMargin
+ (mClippingToPadding ? mPaddingTop : 0);
// The left parameter must for some reason be set to 0.
// I think it should be set to mPaddingLeft but apparently not
MarginLayoutParams lp = (MarginLayoutParams) mHeader.getLayoutParams();
int headerTop = lp.topMargin + stickyHeaderTop();
mHeader.layout(mPaddingLeft, headerTop, mHeader.getMeasuredWidth()
+ mPaddingLeft, headerTop + mHeader.getMeasuredHeight());
}
Expand Down Expand Up @@ -298,36 +294,40 @@ private void updateOrClearHeader(int firstVisiblePosition) {
}

final int headerViewCount = mList.getHeaderViewsCount();
final int realFirstVisibleItem = firstVisiblePosition - headerViewCount;
int headerPosition = firstVisiblePosition - headerViewCount;
if (mList.getChildCount() > 0) {
View firstItem = mList.getChildAt(0);
if (firstItem.getBottom() < stickyHeaderTop()) {
headerPosition++;
}
}

// It is not a mistake to call getFirstVisiblePosition() here.
// Most of the time getFixedFirstVisibleItem() should be called
// but that does not work great together with getChildAt()
final boolean doesListHaveChildren = mList.getChildCount() != 0;
final boolean isFirstViewBelowTop = doesListHaveChildren && mList
.getFirstVisiblePosition() == 0
&& mList.getChildAt(0).getTop() > (mClippingToPadding ? mPaddingTop : 0);
final boolean isFirstVisibleItemOutsideAdapterRange = realFirstVisibleItem > adapterCount - 1
|| realFirstVisibleItem < 0;
if (!doesListHaveChildren || isFirstVisibleItemOutsideAdapterRange
|| isFirstViewBelowTop) {
final boolean isFirstViewBelowTop = doesListHaveChildren
&& mList.getFirstVisiblePosition() == 0
&& mList.getChildAt(0).getTop() >= stickyHeaderTop();
final boolean isHeaderPositionOutsideAdapterRange = headerPosition > adapterCount - 1
|| headerPosition < 0;
if (!doesListHaveChildren || isHeaderPositionOutsideAdapterRange || isFirstViewBelowTop) {
clearHeader();
return;
}

updateHeader(realFirstVisibleItem);
updateHeader(headerPosition);
}

private void updateHeader(int firstVisiblePosition) {
private void updateHeader(int headerPosition) {

// check if there is a new header should be sticky
if (mHeaderPosition == null || mHeaderPosition != firstVisiblePosition) {
mHeaderPosition = firstVisiblePosition;
final long headerId = mAdapter.getHeaderId(firstVisiblePosition);
if (mHeaderPosition == null || mHeaderPosition != headerPosition) {
mHeaderPosition = headerPosition;
final long headerId = mAdapter.getHeaderId(headerPosition);
if (mHeaderId == null || mHeaderId != headerId) {
mHeaderId = headerId;
final View header = mAdapter.getHeaderView(mHeaderPosition,
mHeader, this);
final View header = mAdapter.getHeaderView(mHeaderPosition, mHeader, this);
if (mHeader != header) {
if (header == null) {
throw new NullPointerException("header may not be null");
Expand All @@ -337,8 +337,7 @@ private void updateHeader(int firstVisiblePosition) {
ensureHeaderHasCorrectLayoutParams(mHeader);
measureHeader(mHeader);
if(mOnStickyHeaderChangedListener != null) {
mOnStickyHeaderChangedListener.onStickyHeaderChanged(this,
mHeader, firstVisiblePosition, mHeaderId);
mOnStickyHeaderChangedListener.onStickyHeaderChanged(this, mHeader, headerPosition, mHeaderId);
}
// Reset mHeaderOffset to null ensuring
// that it will be set on the header and
Expand All @@ -352,15 +351,12 @@ private void updateHeader(int firstVisiblePosition) {
// Calculate new header offset
// Skip looking at the first view. it never matters because it always
// results in a headerOffset = 0
int headerBottom = mHeader.getMeasuredHeight()
+ (mClippingToPadding ? mPaddingTop : 0);
int headerBottom = mHeader.getMeasuredHeight() + stickyHeaderTop();
for (int i = 0; i < mList.getChildCount(); i++) {
final View child = mList.getChildAt(i);
final boolean doesChildHaveHeader = child instanceof WrapperView
&& ((WrapperView) child).hasHeader();
final boolean doesChildHaveHeader = child instanceof WrapperView && ((WrapperView) child).hasHeader();
final boolean isChildFooter = mList.containsFooterView(child);
if (child.getTop() >= (mClippingToPadding ? mPaddingTop : 0)
&& (doesChildHaveHeader || isChildFooter)) {
if (child.getTop() >= stickyHeaderTop() && (doesChildHaveHeader || isChildFooter)) {
headerOffset = Math.min(child.getTop() - headerBottom, 0);
break;
}
Expand Down Expand Up @@ -401,8 +397,7 @@ public void onClick(View v) {
private void updateHeaderVisibilities() {
int top;
if (mHeader != null) {
top = mHeader.getMeasuredHeight()
+ (mHeaderOffset != null ? mHeaderOffset : 0);
top = mHeader.getMeasuredHeight() + (mHeaderOffset != null ? mHeaderOffset : 0);
} else {
top = mClippingToPadding ? mPaddingTop : 0;
}
Expand Down Expand Up @@ -444,14 +439,12 @@ private void setHeaderOffet(int offset) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mHeader.setTranslationY(mHeaderOffset);
} else {
MarginLayoutParams params = (MarginLayoutParams) mHeader
.getLayoutParams();
MarginLayoutParams params = (MarginLayoutParams) mHeader.getLayoutParams();
params.topMargin = mHeaderOffset;
mHeader.setLayoutParams(params);
}
if (mOnStickyHeaderOffsetChangedListener != null) {
mOnStickyHeaderOffsetChangedListener
.onStickyHeaderOffsetChanged(this, mHeader, -mHeaderOffset);
mOnStickyHeaderOffsetChangedListener.onStickyHeaderOffsetChanged(this, mHeader, -mHeaderOffset);
}
}
}
Expand Down Expand Up @@ -545,6 +538,10 @@ private int getHeaderOverlap(int position) {
return 0;
}

private int stickyHeaderTop() {
return mStickyHeaderTopOffset + (mClippingToPadding ? mPaddingTop : 0);
}

/* ---------- StickyListHeaders specific API ---------- */

public void setAreHeadersSticky(boolean areHeadersSticky) {
Expand All @@ -570,6 +567,20 @@ public boolean getAreHeadersSticky() {
return areHeadersSticky();
}

/**
*
* @param stickyHeaderTopOffset
* The offset of the sticky header fom the top of the view
*/
public void setStickyHeaderTopOffset(int stickyHeaderTopOffset) {
mStickyHeaderTopOffset = stickyHeaderTopOffset;
updateOrClearHeader(mList.getFixedFirstVisibleItem());
}

public int getStickyHeaderTopOffset() {
return mStickyHeaderTopOffset;
}

public void setDrawingListUnderStickyHeader(
boolean drawingListUnderStickyHeader) {
mIsDrawingListUnderStickyHeader = drawingListUnderStickyHeader;
Expand Down
2 changes: 1 addition & 1 deletion sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies {

android {
compileSdkVersion 19
buildToolsVersion '19.0.3'
buildToolsVersion '19.1.0'

sourceSets {
main {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
Expand All @@ -26,7 +25,7 @@
public class TestActivity extends ActionBarActivity implements
AdapterView.OnItemClickListener, StickyListHeadersListView.OnHeaderClickListener,
StickyListHeadersListView.OnStickyHeaderOffsetChangedListener,
StickyListHeadersListView.OnStickyHeaderChangedListener, View.OnTouchListener {
StickyListHeadersListView.OnStickyHeaderChangedListener {

private TestBaseAdapter mAdapter;
private DrawerLayout mDrawerLayout;
Expand Down Expand Up @@ -76,7 +75,6 @@ public void run() {
stickyList.setDrawingListUnderStickyHeader(true);
stickyList.setAreHeadersSticky(true);
stickyList.setAdapter(mAdapter);
stickyList.setOnTouchListener(this);

mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
Expand Down Expand Up @@ -128,7 +126,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}

return super.onOptionsItemSelected(item);
}

Expand Down Expand Up @@ -172,17 +169,13 @@ public void onClick(View view) {
};

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(this, "Item " + position + " clicked!",
Toast.LENGTH_SHORT).show();
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Item " + position + " clicked!", Toast.LENGTH_SHORT).show();
}

@Override
public void onHeaderClick(StickyListHeadersListView l, View header,
int itemPosition, long headerId, boolean currentlySticky) {
Toast.makeText(this, "Header " + headerId + " currentlySticky ? " + currentlySticky,
Toast.LENGTH_SHORT).show();
public void onHeaderClick(StickyListHeadersListView l, View header, int itemPosition, long headerId, boolean currentlySticky) {
Toast.makeText(this, "Header " + headerId + " currentlySticky ? " + currentlySticky, Toast.LENGTH_SHORT).show();
}

@Override
Expand All @@ -194,16 +187,9 @@ public void onStickyHeaderOffsetChanged(StickyListHeadersListView l, View header
}

@Override
public void onStickyHeaderChanged(StickyListHeadersListView l, View header,
int itemPosition, long headerId) {
Toast.makeText(this, "Sticky Header Changed to " + headerId,
Toast.LENGTH_SHORT).show();
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onStickyHeaderChanged(StickyListHeadersListView l, View header, int itemPosition, long headerId) {
header.setAlpha(1);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(this, "OnTouch works", Toast.LENGTH_SHORT).show();
v.setOnTouchListener(null);
return false;
}
}

0 comments on commit 6e6c87c

Please sign in to comment.