diff --git a/app/build.gradle b/app/build.gradle
index 5d0796f..8d915aa 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -34,6 +34,7 @@ ext {
dependencies {
compile "com.android.support:appcompat-v7:$supportLibraryVersion"
+ compile "com.android.support:recyclerview-v7:$supportLibraryVersion"
compile "com.android.support:cardview-v7:$supportLibraryVersion"
compile 'com.github.chrisbanes.photoview:library:1.2.4'
}
diff --git a/app/src/main/java/android/support/v7/widget/ConcatAdapter.java b/app/src/main/java/android/support/v7/widget/ConcatAdapter.java
new file mode 100644
index 0000000..ae41adb
--- /dev/null
+++ b/app/src/main/java/android/support/v7/widget/ConcatAdapter.java
@@ -0,0 +1,202 @@
+package android.support.v7.widget;
+
+import android.support.annotation.NonNull;
+import android.util.SparseArray;
+import android.view.ViewGroup;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Adapter which concatenates the items of multiple adapters.
+ * Doesn't support stable ids, but properly delegates changes notifications.
+ *
+ * Adapters may provide multiple view types but they must not overlap.
+ * It's recommended to always use the item layout id as view type.
+ *
+ * Warning: You need to use ConcatAdapter.getAdapterPosition(ViewHolder)
+ * in place of ViewHolder.getAdapterPosition() inside child adapters.
+ *
+ * @author Christophe Beyls
+ */
+public class ConcatAdapter extends RecyclerView.Adapter {
+
+ private final RecyclerView.Adapter[] adapters;
+ private final RecyclerView.AdapterDataObserver[] adapterObservers;
+ final int[] offsets;
+ private final SparseArray> viewTypeAdapters = new SparseArray<>();
+
+ private class InternalObserver extends RecyclerView.AdapterDataObserver {
+
+ private final int adapterIndex;
+
+ InternalObserver(int adapterIndex) {
+ this.adapterIndex = adapterIndex;
+ }
+
+ @Override
+ public void onChanged() {
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount) {
+ notifyItemRangeChanged(positionStart + offsets[adapterIndex], itemCount);
+ }
+
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
+ notifyItemRangeChanged(positionStart + offsets[adapterIndex], itemCount, payload);
+ }
+
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ for (int i = adapterIndex + 1, size = offsets.length; i < size; ++i) {
+ offsets[i] += itemCount;
+ }
+ notifyItemRangeInserted(positionStart + offsets[adapterIndex], itemCount);
+ }
+
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ for (int i = adapterIndex + 1, size = offsets.length; i < size; ++i) {
+ offsets[i] -= itemCount;
+ }
+ notifyItemRangeRemoved(positionStart + offsets[adapterIndex], itemCount);
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ final int offset = offsets[adapterIndex];
+ notifyItemMoved(fromPosition + offset, toPosition + offset);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public ConcatAdapter(RecyclerView.Adapter extends RecyclerView.ViewHolder>... adapters) {
+ this.adapters = (RecyclerView.Adapter[]) adapters;
+ final int size = adapters.length;
+ adapterObservers = new RecyclerView.AdapterDataObserver[size];
+ for (int i = 0; i < size; ++i) {
+ adapterObservers[i] = new InternalObserver(i);
+ }
+ offsets = new int[size];
+ }
+
+ /**
+ * @return The adapter position relative to the child adapter, if any.
+ */
+ public static int getAdapterPosition(@NonNull RecyclerView.ViewHolder holder) {
+ int position = holder.getAdapterPosition();
+ if (position != RecyclerView.NO_POSITION) {
+ RecyclerView.Adapter adapter = holder.mOwnerRecyclerView.getAdapter();
+ if (adapter instanceof ConcatAdapter) {
+ final int[] offsets = ((ConcatAdapter) adapter).offsets;
+ final int index = Arrays.binarySearch(offsets, position);
+ if (index >= 0) {
+ position = 0;
+ } else {
+ position -= offsets[~index - 1];
+ }
+ }
+ }
+ return position;
+ }
+
+ private int getAdapterIndexForPosition(int position) {
+ int index = Arrays.binarySearch(offsets, position);
+ return (index < 0) ? ~index - 1 : index;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ final int index = getAdapterIndexForPosition(position);
+ RecyclerView.Adapter adapter = adapters[index];
+ int viewType = adapter.getItemViewType(position - offsets[index]);
+ if (viewTypeAdapters.get(viewType) == null) {
+ viewTypeAdapters.put(viewType, adapter);
+ }
+ return viewType;
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return viewTypeAdapters.get(viewType).onCreateViewHolder(parent, viewType);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ final int index = getAdapterIndexForPosition(position);
+ adapters[index].onBindViewHolder(holder, position - offsets[index]);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List