diff --git a/library/src/main/java/com/timehop/stickyheadersrecyclerview/HeaderPositionCalculator.java b/library/src/main/java/com/timehop/stickyheadersrecyclerview/HeaderPositionCalculator.java index d7bf82e..d12f03a 100644 --- a/library/src/main/java/com/timehop/stickyheadersrecyclerview/HeaderPositionCalculator.java +++ b/library/src/main/java/com/timehop/stickyheadersrecyclerview/HeaderPositionCalculator.java @@ -74,6 +74,13 @@ public boolean hasNewHeader(int position, boolean isReverseLayout) { return false; } + int numColumns = mAdapter.getNumColumns(); + int columnOfItem = position % numColumns; + if (columnOfItem > 0) { + int firstItemOnRowPosition = position - columnOfItem; + return hasNewHeader(firstItemOnRowPosition, isReverseLayout); + } + long headerId = mAdapter.getHeaderId(position); if (headerId < 0) { diff --git a/library/src/main/java/com/timehop/stickyheadersrecyclerview/StickyRecyclerHeadersAdapter.java b/library/src/main/java/com/timehop/stickyheadersrecyclerview/StickyRecyclerHeadersAdapter.java index 23990fa..0072bc3 100644 --- a/library/src/main/java/com/timehop/stickyheadersrecyclerview/StickyRecyclerHeadersAdapter.java +++ b/library/src/main/java/com/timehop/stickyheadersrecyclerview/StickyRecyclerHeadersAdapter.java @@ -36,4 +36,10 @@ public interface StickyRecyclerHeadersAdapter 0) { continue; } diff --git a/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/AnimalsAdapter.java b/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/AnimalsAdapter.java index 1872b4c..04afa62 100644 --- a/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/AnimalsAdapter.java +++ b/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/AnimalsAdapter.java @@ -12,7 +12,7 @@ */ public abstract class AnimalsAdapter extends RecyclerView.Adapter { - private ArrayList items = new ArrayList(); + protected ArrayList items = new ArrayList(); public AnimalsAdapter() { setHasStableIds(true); diff --git a/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/MainActivity.java b/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/MainActivity.java index 591bd10..52d50aa 100644 --- a/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/MainActivity.java +++ b/sample/src/main/java/com/timehop/stickyheadersrecyclerview/sample/MainActivity.java @@ -6,8 +6,10 @@ import android.os.Handler; import android.os.Looper; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,9 +23,12 @@ import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersTouchListener; import java.security.SecureRandom; +import java.util.Collection; public class MainActivity extends AppCompatActivity { + private static final int NUM_COLUMNS = 3; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -35,7 +40,8 @@ protected void onCreate(Bundle savedInstanceState) { // Set adapter populated with example dummy data final AnimalsHeadersAdapter adapter = new AnimalsHeadersAdapter(); - adapter.add("Animals below!"); + adapter.setNumColumns(NUM_COLUMNS); +// adapter.add("Animals below!"); adapter.addAll(getDummyDataSet()); recyclerView.setAdapter(adapter); @@ -58,7 +64,9 @@ public void run() { // Set layout manager int orientation = getLayoutManagerOrientation(getResources().getConfiguration().orientation); - final LinearLayoutManager layoutManager = new LinearLayoutManager(this, orientation, isReverseButton.isChecked()); +// final LinearLayoutManager layoutManager = new LinearLayoutManager(this, orientation, isReverseButton.isChecked()); + + final GridLayoutManager layoutManager = new GridLayoutManager(this, NUM_COLUMNS); recyclerView.setLayoutManager(layoutManager); // Add the sticky headers decoration @@ -118,6 +126,9 @@ private int getLayoutManagerOrientation(int activityOrientation) { private class AnimalsHeadersAdapter extends AnimalsAdapter implements StickyRecyclerHeadersAdapter { + private static final String EMPTY_NAME = " "; + private int numColumns = 1; + @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) @@ -134,11 +145,12 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { @Override public long getHeaderId(int position) { - if (position == 0) { - return -1; - } else { - return getItem(position).charAt(0); - } + int numColumnOfItem = position % numColumns; + if (numColumnOfItem == 0) { + return getFirstChar(getItem(position)); + } else { + return getHeaderId(position - numColumnOfItem); + } } @Override @@ -163,5 +175,81 @@ private int getRandomColor() { }); } + @Override + public int getNumColumns() { + return numColumns; + } + + public void setNumColumns(int numColumns) { + this.numColumns = numColumns; + } + + @Override + public void add(int index, String object) { + super.add(index, object); + reorderItems(); + } + + @Override + public void add(String object) { + super.add(object); + reorderItems(); + } + + @Override + public void addAll(Collection collection) { + super.addAll(collection); + reorderItems(); + } + + @Override + public void addAll(String... items) { + super.addAll(items); + reorderItems(); + } + + @Override + public void remove(String object) { + super.remove(object); + reorderItems(); + } + + private void reorderItems() { + long firstCharOnLastItem = -1; + + for (int i = 0; i < items.size(); i++) { + String item = items.get(i); + if (getFirstChar(item) != firstCharOnLastItem) { // new header found for item + int numColumnOfItem = i % numColumns; + if (numColumnOfItem > 0 && !EMPTY_NAME.equals(item)) { // fill row with empty items + int emptyVideos = numColumns - numColumnOfItem; + for (int j = 0; j < emptyVideos; j++) { + items.add(i, EMPTY_NAME); + if (j != emptyVideos - 1) { + i++; + } + } + continue; + } else if (numColumnOfItem == 0 && EMPTY_NAME.equals(item)){ + // remove empty items to avoid empty rows when removing items + while (items.get(i).equals(EMPTY_NAME)) { + items.remove(i); + } + i--; + } + if (!EMPTY_NAME.equals(item)) { + firstCharOnLastItem = getFirstChar(item); + } + } + } + } + + private int getFirstChar(String name) { + if (TextUtils.isEmpty(name)) { + return 0; + } else { + return name.charAt(0); + } + } } }