Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mtotschnig committed Nov 1, 2014
2 parents af8f7ed + 80e7105 commit 12e956a
Show file tree
Hide file tree
Showing 29 changed files with 1,057 additions and 156 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2014 Emil Sjölander

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ The goal of this project is to deliver a high performance replacement to `ListVi

Installing
---------------
###Maven
Add the following maven dependency exchanging `x.x.x` for the latest release.
```XML
<dependency>
<groupId>se.emilsjolander</groupId>
<artifactId>stickylistheaders</artifactId>
<version>x.x.x</version>
</dependency>
```

###Gradle
Add the following gradle dependency exchanging `x.x.x` for the latest release.
```groovy
Expand All @@ -40,6 +50,8 @@ In the following dialog navigate to StickyListHeaders which you cloned to your c

Getting Started
---------------
###Base usage

Ok lets start with your activities or fragments xml file. It might look something like this.
```xml
<se.emilsjolander.stickylistheaders.StickyListHeadersListView
Expand Down Expand Up @@ -136,6 +148,43 @@ public class MyAdapter extends BaseAdapter implements StickyListHeadersAdapter {

That's it! Look through the API docs below to get know about things to customize and if you have any problems getting started please open an issue as it probably means the getting started guide need some improvement!

###Expandable support
Now,you can use `ExpandableStickyListHeadersListView` to expand/collapse subitems.
xml first
```xml
<se.emilsjolander.stickylistheaders.ExpandableStickyListHeadersListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
```
Then you need to setup your listview on `onCreate()` or `onCreateView()`
```java
ExpandableStickyListHeadersListView expandableStickyList = (ExpandableStickyListHeadersListView) findViewById(R.id.list);
StickyListHeadersAdapter adapter = new MyAdapter(this);
expandableStickyList.setAdapter(adapter);
expandableStickyList.setOnHeaderClickListener(new StickyListHeadersListView.OnHeaderClickListener() {
@Override
public void onHeaderClick(StickyListHeadersListView l, View header, int itemPosition, long headerId, boolean currentlySticky) {
if(expandableStickyList.isHeaderCollapsed(headerId)){
expandableStickyList.expand(headerId);
}else {
expandableStickyList.collapse(headerId);
}
}
});
```
As you see,MyAdapter is just a StickyListHeadersAdapter which is mentioned in the previous section.
You needn't do any more extra operations.

There are three important functions:
`isHeaderCollapsed(long headerId)`,`expand(long headerId)` and `collapse(long headerId)`.

The function `isHeaderCollapsed` is used to check whether the subitems belonging to the header have collapsed.
You can call `expand` or `collapse` method to hide or show subitems.
You can also define a AnimationExecutor which implements `ExpandableStickyListHeadersListView.IAnimationExecutor`,
and put it into the ExpandableStickyListHeadersListView by `setAnimExecutor` method,if you want more fancy animation when hiding or showing subitems.


Upgrading from 1.x versions
---------------------------
First of all the package name has changed from `com.emilsjolander.components.stickylistheaders` -> `se.emilsjolander.stickylistheaders` so update all your imports and xml files using StickyListHeaders!
Expand Down Expand Up @@ -184,6 +233,15 @@ public interface OnStickyHeaderOffsetChangedListener {
}
```

A `OnStickyHeaderChangedListener` listens for changes to the header. This enables UI elements elsewhere to react to the current header (e.g. if each header is a date, then the rest of the UI can update when you scroll to a new date).
```java
public void setOnStickyHeaderChangedListener(OnStickyHeaderChangedListener listener);

public interface OnStickyHeaderChangedListener {
void onStickyHeaderChanged(StickyListHeadersListView l, View header, int itemPosition, long headerId);
}
```

Here are two methods added to the API for inspecting the children of the underlying `ListView`. I could not override the normal `getChildAt()` and `getChildCount()` methods as that would mess up the underlying measurement system of the `FrameLayout` wrapping the `ListView`.
```java
public View getListChildAt(int index);
Expand All @@ -196,6 +254,17 @@ 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();
```

Get the amount of overlap the sticky header has when position in on the top of the list.
```java
public int getHeaderOverlap(int position);
```

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.7.+'
classpath 'com.android.tools.build:gradle:0.12.+'
}
}

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.1.4
VERSION_NAME=2.5.2
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.9-all.zip
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
Empty file modified gradlew
100644 → 100755
Empty file.
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.0'
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'
60 changes: 60 additions & 0 deletions library/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>se.emilsjolander</groupId>
<artifactId>StickylListHeaders</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>apk</packaging>
<name>StickyListHeaders</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<platform.version>4.1.1.4
</platform.version>
<android.plugin.version>3.6.0</android.plugin.version>
</properties>

<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>${platform.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<sourceDirectory>${project.basedir}/src/se/emilsjolander/stickylistheaders</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/res</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>${android.plugin.version}</version>
<extensions>true</extensions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>

<configuration>
<sdk>
<platform>16</platform>

</sdk>
</configuration>
</plugin>
</plugins>
</build>

</project>
1 change: 1 addition & 0 deletions library/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<attr name="android:scrollbarStyle" />
<attr name="android:divider" />
<attr name="android:dividerHeight" />
<attr name="android:transcriptMode" />

<!-- StickyListHeaders attributes -->
<attr name="hasStickyHeaders" format="boolean" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
class AdapterWrapper extends BaseAdapter implements StickyListHeadersAdapter {

interface OnHeaderClickListener {
public void onHeaderClick(View header, int itemPosition, long headerId);
void onHeaderClick(View header, int itemPosition, long headerId);
}

final StickyListHeadersAdapter mDelegate;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package se.emilsjolander.stickylistheaders;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* a hash map can maintain an one-to-many relationship which the value only belongs to one “one” part
* and the map also support getKey by value quickly
*
* @author lsjwzh
*/
class DistinctMultiHashMap<TKey,TItemValue> {
private IDMapper<TKey, TItemValue> mIDMapper;

interface IDMapper<TKey,TItemValue>{
public Object keyToKeyId(TKey key);
public TKey keyIdToKey(Object keyId);
public Object valueToValueId(TItemValue value);
public TItemValue valueIdToValue(Object valueId);
}

LinkedHashMap<Object,List<TItemValue>> mKeyToValuesMap = new LinkedHashMap<Object, List<TItemValue>>();
LinkedHashMap<Object,TKey> mValueToKeyIndexer = new LinkedHashMap<Object, TKey>();

DistinctMultiHashMap(){
this(new IDMapper<TKey, TItemValue>() {
@Override
public Object keyToKeyId(TKey key) {
return key;
}

@Override
public TKey keyIdToKey(Object keyId) {
return (TKey) keyId;
}

@Override
public Object valueToValueId(TItemValue value) {
return value;
}

@Override
public TItemValue valueIdToValue(Object valueId) {
return (TItemValue) valueId;
}
});
}
DistinctMultiHashMap(IDMapper<TKey, TItemValue> idMapper){
mIDMapper = idMapper;
}

public List<TItemValue> get(TKey key){
//todo immutable
return mKeyToValuesMap.get(mIDMapper.keyToKeyId(key));
}
public TKey getKey(TItemValue value){
return mValueToKeyIndexer.get(mIDMapper.valueToValueId(value));
}

public void add(TKey key,TItemValue value){
Object keyId = mIDMapper.keyToKeyId(key);
if(mKeyToValuesMap.get(keyId)==null){
mKeyToValuesMap.put(keyId,new ArrayList<TItemValue>());
}
//remove old relationship
TKey keyForValue = getKey(value);
if(keyForValue !=null){
mKeyToValuesMap.get(mIDMapper.keyToKeyId(keyForValue)).remove(value);
}
mValueToKeyIndexer.put(mIDMapper.valueToValueId(value), key);
if(!containsValue(mKeyToValuesMap.get(mIDMapper.keyToKeyId(key)),value)) {
mKeyToValuesMap.get(mIDMapper.keyToKeyId(key)).add(value);
}
}

public void removeKey(TKey key){
if(mKeyToValuesMap.get(mIDMapper.keyToKeyId(key))!=null){
for (TItemValue value : mKeyToValuesMap.get(mIDMapper.keyToKeyId(key))){
mValueToKeyIndexer.remove(mIDMapper.valueToValueId(value));
}
mKeyToValuesMap.remove(mIDMapper.keyToKeyId(key));
}
}
public void removeValue(TItemValue value){
if(getKey(value)!=null){
List<TItemValue> itemValues = mKeyToValuesMap.get(mIDMapper.keyToKeyId(getKey(value)));
if(itemValues!=null){
itemValues.remove(value);
}
}
mValueToKeyIndexer.remove(mIDMapper.valueToValueId(value));
}

public void clear(){
mValueToKeyIndexer.clear();
mKeyToValuesMap.clear();
}

public void clearValues(){
for (Map.Entry<Object,List<TItemValue>> entry:entrySet()){
if(entry.getValue()!=null){
entry.getValue().clear();
}
}
mValueToKeyIndexer.clear();
}

public Set<Map.Entry<Object,List<TItemValue>>> entrySet(){
return mKeyToValuesMap.entrySet();
}

public Set<Map.Entry<Object,TKey>> reverseEntrySet(){
return mValueToKeyIndexer.entrySet();
}

public int size(){
return mKeyToValuesMap.size();
}
public int valuesSize(){
return mValueToKeyIndexer.size();
}

protected boolean containsValue(List<TItemValue> list,TItemValue value){
for (TItemValue itemValue :list){
if(mIDMapper.valueToValueId(itemValue).equals(mIDMapper.valueToValueId(value))){
return true;
}
}
return false;
}

/**
* @param position
* @return
*/
public TItemValue getValueByPosition(int position){
Object[] vauleIdArray = mValueToKeyIndexer.keySet().toArray();
if(position>vauleIdArray.length){
throw new IndexOutOfBoundsException();
}
Object valueId = vauleIdArray[position];
return mIDMapper.valueIdToValue(valueId);
}
}
Loading

0 comments on commit 12e956a

Please sign in to comment.