├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml └── vcs.xml ├── HeaderFooterRecyclerView.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── willblaschko │ │ └── android │ │ └── headerfooterrecyclerview │ │ ├── ApplicationTest.java │ │ └── RecyclerViewHeaderFooterAdapterTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── willblaschko │ │ ├── android │ │ └── headerfooterrecyclerview │ │ │ ├── IGridItem.java │ │ │ ├── IRecyclerViewIntermediary.java │ │ │ └── RecyclerViewHeaderFooterAdapter.java │ │ └── example │ │ ├── ExampleHeaderFooter.java │ │ ├── ExampleHorizontalGridActivity.java │ │ ├── ExampleHorizontalLinearLayoutActivity.java │ │ ├── ExampleHorizontalStaggeredGridActivity.java │ │ ├── ExampleIntermediary.java │ │ ├── ExampleLandingActivity.java │ │ ├── ExampleVerticalGridActivity.java │ │ ├── ExampleVerticalLinearLayoutActivity.java │ │ └── ExampleVerticalStaggeredGridActivity.java │ └── res │ ├── layout │ ├── activity_example.xml │ ├── activity_landing.xml │ ├── item_string_1.xml │ ├── item_string_2.xml │ ├── item_string_3.xml │ └── item_string_4.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ └── values │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Windows thumbnail db 19 | Thumbs.db 20 | 21 | # OSX files 22 | .DS_Store 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | 28 | # Android Studio 29 | .idea 30 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 31 | .gradle 32 | build/ -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | HeaderFooterRecyclerView -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HeaderFooterRecyclerView.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # header-footer-recycler-view 2 | This library adds header/footer functionality to vertical and horizontal RecyclerView (for all 3 built-in types--linear, staggered-grid, grid) and abstract RecyclerView.Adapter into an interface for easier usage of multiple ViewHolder types. 3 |

Dependencies

4 | 8 |

Setup Instructions

9 | 12 |

Sample Implementation

13 | Activity/Fragment 14 | ``` 15 | for(int i = 0; i < count; i++){ 16 | mStrings.add(Integer.toString(i)); 17 | } 18 | mIntermediary = new ExampleIntermediary(mStrings); 19 | mLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); 20 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 21 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 22 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 23 | mRecyclerView.setLayoutManager(mLayoutManager); 24 | mRecyclerView.setAdapter(mAdapter); 25 | ``` 26 | IRecyclerViewIntermediary - ExampleIntermediary 27 | ``` 28 | public class ExampleIntermediary implements IRecyclerViewIntermediary { 29 | 30 | private List mItems; 31 | 32 | public ExampleIntermediary(List items){ 33 | mItems=items; 34 | } 35 | 36 | @Override 37 | public int getItemCount() { 38 | return mItems.size(); 39 | } 40 | 41 | @Override 42 | public Object getItem(int position) { 43 | return mItems.get(position); 44 | } 45 | 46 | @Override 47 | public RecyclerView.ViewHolder getViewHolder(ViewGroup viewGroup, int type) { 48 | switch (type){ 49 | ... //based on the type (getItemViewType), return the correct view holder 50 | } 51 | } 52 | 53 | @Override 54 | public int getItemViewType(int position) { 55 | return position % 4; //any logic can go here 56 | } 57 | 58 | @Override 59 | public void populateViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 60 | switch (getItemViewType(position){ 61 | ... 62 | } 63 | } 64 | 65 | 66 | } 67 | ``` -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "com.willblaschko.android.headerfooterrecyclerview" 9 | minSdkVersion 7 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:21.0.2' 25 | compile 'com.android.support:recyclerview-v7:21.0.0' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Android SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/willblaschko/android/headerfooterrecyclerview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.android.headerfooterrecyclerview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/willblaschko/android/headerfooterrecyclerview/RecyclerViewHeaderFooterAdapterTest.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.android.headerfooterrecyclerview; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.GridLayoutManager; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | import android.test.InstrumentationTestCase; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | /** 18 | * Created by Will on 2/8/2015. 19 | */ 20 | public class RecyclerViewHeaderFooterAdapterTest extends InstrumentationTestCase { 21 | 22 | private Context mContext; 23 | private int mCount; 24 | private int mHeaderCount; 25 | private int mFooterCount; 26 | List mStrings; 27 | 28 | @Override 29 | public void setUp(){ 30 | mContext = getInstrumentation().getContext(); 31 | mCount = new Random().nextInt(100)+1; 32 | mHeaderCount = new Random().nextInt(10)+1; 33 | mFooterCount = new Random().nextInt(10)+1; 34 | mStrings = getStrings(mCount); 35 | } 36 | 37 | public void testLinearLayoutManager() { 38 | RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(mContext); 39 | TestIntermediary mIntermeditary = new TestIntermediary(mStrings); 40 | RecyclerViewHeaderFooterAdapter mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermeditary); 41 | 42 | for(int i = 0; i < mHeaderCount; i++){ 43 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + i); 44 | mAdapter.addHeader(new View(mContext)); 45 | } 46 | for(int i = 0; i < mFooterCount; i++){ 47 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + i); 48 | mAdapter.addFooter(new View(mContext)); 49 | } 50 | 51 | assertEquals("Wrong LayoutManager", mAdapter.getManagerType(), RecyclerViewHeaderFooterAdapter.TYPE_MANAGER_LINEAR); 52 | assertEquals("Item List length is wrong size", mStrings.size(), mIntermeditary.getItemCount()); 53 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + mFooterCount); 54 | assertEquals("Wrong header layout span count", mAdapter.getGridSpan(mHeaderCount-1), 1); 55 | assertEquals("Wrong object layout span count", mAdapter.getGridSpan(mHeaderCount), 1); 56 | assertEquals("Wrong footer layout span count", mAdapter.getGridSpan(mHeaderCount+mCount), 1); 57 | } 58 | 59 | public void testGridLayoutMananger() { 60 | int span = new Random().nextInt(4)+1; 61 | RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(mContext, span); 62 | TestIntermediary mIntermeditary = new TestIntermediary(mStrings); 63 | RecyclerViewHeaderFooterAdapter mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermeditary); 64 | 65 | for(int i = 0; i < mHeaderCount; i++){ 66 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + i); 67 | mAdapter.addHeader(new View(mContext)); 68 | } 69 | for(int i = 0; i < mFooterCount; i++){ 70 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + i); 71 | mAdapter.addFooter(new View(mContext)); 72 | } 73 | 74 | assertEquals("Wrong LayoutManager", mAdapter.getManagerType(), RecyclerViewHeaderFooterAdapter.TYPE_MANAGER_GRID); 75 | assertEquals("Item List length is wrong size", mStrings.size(), mIntermeditary.getItemCount()); 76 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + mFooterCount); 77 | assertEquals("Wrong header layout span count", mAdapter.getGridSpan(mHeaderCount-1), span); 78 | assertEquals("Wrong object layout span count", mAdapter.getGridSpan(mHeaderCount), 1); 79 | assertEquals("Wrong footer layout span count", mAdapter.getGridSpan(mHeaderCount+mCount), span); 80 | } 81 | 82 | public void testStaggeredGridLayoutManager() { 83 | int span = new Random().nextInt(4)+1; 84 | RecyclerView.LayoutManager mLayoutManager = new StaggeredGridLayoutManager(span, StaggeredGridLayoutManager.VERTICAL); 85 | TestIntermediary mIntermeditary = new TestIntermediary(mStrings); 86 | RecyclerViewHeaderFooterAdapter mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermeditary); 87 | 88 | for(int i = 0; i < mHeaderCount; i++){ 89 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + i); 90 | mAdapter.addHeader(new View(mContext)); 91 | } 92 | for(int i = 0; i < mFooterCount; i++){ 93 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + i); 94 | mAdapter.addFooter(new View(mContext)); 95 | } 96 | 97 | assertEquals("Wrong LayoutManager", mAdapter.getManagerType(), RecyclerViewHeaderFooterAdapter.TYPE_MANAGER_STAGGERED_GRID); 98 | assertEquals("Item List length is wrong size", mStrings.size(), mIntermeditary.getItemCount()); 99 | assertEquals("Wrong item count (items + header + footer)", mAdapter.getItemCount(), mStrings.size() + mHeaderCount + mFooterCount); 100 | assertEquals("Wrong header layout span count", mAdapter.getGridSpan(mHeaderCount-1), span); 101 | assertEquals("Wrong object layout span count", mAdapter.getGridSpan(mHeaderCount), 1); 102 | assertEquals("Wrong footer layout span count", mAdapter.getGridSpan(mHeaderCount+mCount), span); 103 | } 104 | 105 | private List getStrings(int length){ 106 | List strings = new ArrayList<>(); 107 | for(int i = 0; i < length; i++){ 108 | strings.add(Integer.toString(i)); 109 | } 110 | return strings; 111 | } 112 | 113 | private class TestIntermediary implements IRecyclerViewIntermediary { 114 | 115 | private List mItems; 116 | 117 | public TestIntermediary(List items){ 118 | mItems=items; 119 | } 120 | 121 | @Override 122 | public int getItemCount() { 123 | return mItems.size(); 124 | } 125 | 126 | @Override 127 | public Object getItem(int position) { 128 | return mItems.get(position); 129 | } 130 | 131 | @Override 132 | public RecyclerView.ViewHolder getViewHolder(ViewGroup viewGroup, int type) { 133 | return new TestViewHolder(new TextView(mContext)); 134 | } 135 | 136 | @Override 137 | public int getItemViewType(int position) { 138 | return 0; 139 | } 140 | 141 | @Override 142 | public void populateViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 143 | ((TestViewHolder) viewHolder).mTextView.setText(mItems.get(position)); 144 | } 145 | 146 | private class TestViewHolder extends RecyclerView.ViewHolder{ 147 | TextView mTextView; 148 | public TestViewHolder(View itemView) { 149 | super(itemView); 150 | this.mTextView = (TextView) itemView; 151 | } 152 | } 153 | }; 154 | } 155 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/android/headerfooterrecyclerview/IGridItem.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.android.headerfooterrecyclerview; 2 | 3 | /** 4 | * Created by Will on 2/8/2015. 5 | */ 6 | public interface IGridItem { 7 | int getGridSpan(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/android/headerfooterrecyclerview/IRecyclerViewIntermediary.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.android.headerfooterrecyclerview; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.ViewGroup; 5 | 6 | /** 7 | * Created by Will on 2/8/2015. 8 | */ 9 | public interface IRecyclerViewIntermediary { 10 | public int getItemCount(); 11 | public Object getItem(int position); 12 | public RecyclerView.ViewHolder getViewHolder(ViewGroup viewGroup, int type); 13 | public int getItemViewType(int position); 14 | public void populateViewHolder(RecyclerView.ViewHolder viewHolder, int position); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/android/headerfooterrecyclerview/RecyclerViewHeaderFooterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.android.headerfooterrecyclerview; 2 | 3 | import android.support.v7.widget.GridLayoutManager; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.FrameLayout; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by Will on 2/8/2015. 16 | */ 17 | public class RecyclerViewHeaderFooterAdapter extends RecyclerView.Adapter { 18 | 19 | public static final int TYPE_MANAGER_OTHER = 0; 20 | public static final int TYPE_MANAGER_LINEAR = 1; 21 | public static final int TYPE_MANAGER_GRID = 2; 22 | public static final int TYPE_MANAGER_STAGGERED_GRID = 3; 23 | 24 | 25 | public static final int TYPE_HEADER = 7898; 26 | public static final int TYPE_FOOTER = 7899; 27 | 28 | private List mHeaders = new ArrayList<>(); 29 | private List mFooters = new ArrayList<>(); 30 | 31 | private int mManagerType; 32 | private RecyclerView.LayoutManager mManager; 33 | private IRecyclerViewIntermediary mIntermediary; 34 | 35 | 36 | public RecyclerViewHeaderFooterAdapter(RecyclerView.LayoutManager manager, IRecyclerViewIntermediary intermediary){ 37 | setManager(manager); 38 | this.mIntermediary = intermediary; 39 | } 40 | 41 | public void setLayoutManager(RecyclerView.LayoutManager manager){ 42 | setManager(manager); 43 | } 44 | 45 | private void setManager(RecyclerView.LayoutManager manager){ 46 | mManager = manager; 47 | if(mManager instanceof GridLayoutManager){ 48 | mManagerType = TYPE_MANAGER_GRID; 49 | ((GridLayoutManager) mManager).setSpanSizeLookup(mSpanSizeLookup); 50 | }else if(mManager instanceof LinearLayoutManager){ 51 | mManagerType = TYPE_MANAGER_LINEAR; 52 | }else if(mManager instanceof StaggeredGridLayoutManager){ 53 | mManagerType = TYPE_MANAGER_STAGGERED_GRID; 54 | ((StaggeredGridLayoutManager) mManager).setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS); 55 | }else{ 56 | mManagerType = TYPE_MANAGER_OTHER; 57 | } 58 | } 59 | 60 | public int getManagerType(){ 61 | return mManagerType; 62 | } 63 | 64 | public int getGridSpan(int position){ 65 | if(isHeader(position) || isFooter(position)){ 66 | return getSpan(); 67 | } 68 | position -= mHeaders.size(); 69 | if(mIntermediary.getItem(position) instanceof IGridItem){ 70 | return ((IGridItem) mIntermediary.getItem(position)).getGridSpan(); 71 | } 72 | return 1; 73 | } 74 | 75 | private int getSpan(){ 76 | if(mManager instanceof GridLayoutManager){ 77 | return ((GridLayoutManager) mManager).getSpanCount(); 78 | }else if(mManager instanceof StaggeredGridLayoutManager){ 79 | return ((StaggeredGridLayoutManager) mManager).getSpanCount(); 80 | } 81 | return 1; 82 | } 83 | 84 | private GridLayoutManager.SpanSizeLookup mSpanSizeLookup = new GridLayoutManager.SpanSizeLookup(){ 85 | @Override 86 | public int getSpanSize(int position) { 87 | return getGridSpan(position); 88 | } 89 | }; 90 | 91 | 92 | @Override 93 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) { 94 | //if our position is one of our items (this comes from getItemViewType(int position) below) 95 | if(type != TYPE_HEADER && type != TYPE_FOOTER) { 96 | return mIntermediary.getViewHolder(viewGroup, type); 97 | //else we have a header/footer 98 | }else{ 99 | //create a new framelayout, or inflate from a resource 100 | FrameLayout frameLayout = new FrameLayout(viewGroup.getContext()); 101 | //make sure it fills the space 102 | frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 103 | return new HeaderFooterViewHolder(frameLayout); 104 | } 105 | } 106 | 107 | @Override 108 | public void onBindViewHolder(final RecyclerView.ViewHolder vh, int position) { 109 | //check what type of view our position is 110 | if(isHeader(position)){ 111 | View v = mHeaders.get(position); 112 | //add our view to a header view and display it 113 | prepareHeaderFooter((HeaderFooterViewHolder) vh, v); 114 | }else if(isFooter(position)){ 115 | View v = mFooters.get(position-mIntermediary.getItemCount()-mHeaders.size()); 116 | //add our view to a footer view and display it 117 | prepareHeaderFooter((HeaderFooterViewHolder) vh, v); 118 | }else { 119 | //it's one of our items, display as required 120 | mIntermediary.populateViewHolder(vh, position-mHeaders.size()); 121 | } 122 | } 123 | 124 | private void prepareHeaderFooter(HeaderFooterViewHolder vh, View view){ 125 | 126 | //if it's a staggered grid, span the whole layout 127 | if(mManagerType == TYPE_MANAGER_STAGGERED_GRID){ 128 | StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 129 | layoutParams.setFullSpan(true); 130 | vh.itemView.setLayoutParams(layoutParams); 131 | } 132 | 133 | //if the view already belongs to another layout, remove it 134 | if(view.getParent() != null){ 135 | ((ViewGroup)view.getParent()).removeView(view); 136 | } 137 | 138 | //empty out our FrameLayout and replace with our header/footer 139 | vh.base.removeAllViews(); 140 | vh.base.addView(view); 141 | 142 | } 143 | 144 | private boolean isHeader(int position){ 145 | return(position < mHeaders.size()); 146 | } 147 | private boolean isFooter(int position){ 148 | return(position >= mHeaders.size() + mIntermediary.getItemCount()); 149 | } 150 | 151 | 152 | 153 | @Override 154 | public int getItemCount() { 155 | return mHeaders.size() + mIntermediary.getItemCount() + mFooters.size(); 156 | } 157 | 158 | @Override 159 | public int getItemViewType(int position) { 160 | //check what type our position is, based on the assumption that the order is headers > items > footers 161 | if(isHeader(position)){ 162 | return TYPE_HEADER; 163 | }else if(isFooter(position)){ 164 | return TYPE_FOOTER; 165 | } 166 | int type = mIntermediary.getItemViewType(position); 167 | if(type == TYPE_HEADER || type == TYPE_FOOTER){ 168 | throw new IllegalArgumentException("Item type cannot equal "+TYPE_HEADER+" or "+TYPE_FOOTER); 169 | } 170 | return type; 171 | } 172 | 173 | //add a header to the adapter 174 | public void addHeader(View header){ 175 | if(!mHeaders.contains(header)){ 176 | mHeaders.add(header); 177 | //animate 178 | notifyItemInserted(mHeaders.size()-1); 179 | } 180 | } 181 | 182 | //remove a header from the adapter 183 | public void removeHeader(View header){ 184 | if(mHeaders.contains(header)){ 185 | //animate 186 | notifyItemRemoved(mHeaders.indexOf(header)); 187 | mHeaders.remove(header); 188 | } 189 | } 190 | 191 | //add a footer to the adapter 192 | public void addFooter(View footer){ 193 | if(!mFooters.contains(footer)){ 194 | mFooters.add(footer); 195 | //animate 196 | notifyItemInserted(mHeaders.size()+mIntermediary.getItemCount()+mFooters.size()-1); 197 | } 198 | } 199 | 200 | //remove a footer from the adapter 201 | public void removeFooter(View footer){ 202 | if(mFooters.contains(footer)) { 203 | //animate 204 | notifyItemRemoved(mHeaders.size()+mIntermediary.getItemCount()+mFooters.indexOf(footer)); 205 | mFooters.remove(footer); 206 | } 207 | } 208 | 209 | //our header/footer RecyclerView.ViewHolder is just a FrameLayout 210 | public static class HeaderFooterViewHolder extends RecyclerView.ViewHolder{ 211 | FrameLayout base; 212 | public HeaderFooterViewHolder(View itemView) { 213 | super(itemView); 214 | base = (FrameLayout) itemView; 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleHeaderFooter.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.content.Context; 4 | import android.view.Gravity; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | /** 10 | * Created by Will on 2/8/2015. 11 | */ 12 | public class ExampleHeaderFooter { 13 | public static View getView(Context context, String title){ 14 | TextView view = new TextView(context); 15 | view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 16 | view.setGravity(Gravity.CENTER); 17 | view.setTextSize(30); 18 | view.setPadding(12, 12, 12, 12); 19 | view.setBackgroundColor(0x777777); 20 | view.setText(title); 21 | return view; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleHorizontalGridActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.GridLayoutManager; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | 10 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 11 | import com.willblaschko.android.headerfooterrecyclerview.R; 12 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Random; 17 | 18 | /** 19 | * Created by Will on 2/8/2015. 20 | */ 21 | public class ExampleHorizontalGridActivity extends Activity { 22 | private Context mContext; 23 | private RecyclerView mRecyclerView; 24 | private RecyclerViewHeaderFooterAdapter mAdapter; 25 | private RecyclerView.LayoutManager mLayoutManager; 26 | private IRecyclerViewIntermediary mIntermediary; 27 | 28 | private List mStrings = new ArrayList<>(); 29 | 30 | @Override 31 | public void onCreate(Bundle savedInstanceState){ 32 | super.onCreate(savedInstanceState); 33 | mContext = this; 34 | setContentView(R.layout.activity_example); 35 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 36 | 37 | setTitle("Horizontal Grid"); 38 | } 39 | 40 | private void init(){ 41 | mStrings.clear(); 42 | int count = new Random().nextInt(10)+10; 43 | for(int i = 0; i < count; i++){ 44 | mStrings.add(Integer.toString(i)); 45 | } 46 | mIntermediary = new ExampleIntermediary(mStrings); 47 | 48 | mLayoutManager = new GridLayoutManager(mContext, 3, LinearLayoutManager.HORIZONTAL, false); 49 | 50 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 51 | 52 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 53 | 54 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 55 | 56 | } 57 | 58 | public void onResume(){ 59 | super.onResume(); 60 | init(); 61 | mRecyclerView.setLayoutManager(mLayoutManager); 62 | mRecyclerView.setAdapter(mAdapter); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleHorizontalLinearLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 10 | import com.willblaschko.android.headerfooterrecyclerview.R; 11 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | /** 18 | * Created by Will on 2/8/2015. 19 | */ 20 | public class ExampleHorizontalLinearLayoutActivity extends Activity { 21 | private Context mContext; 22 | private RecyclerView mRecyclerView; 23 | private RecyclerViewHeaderFooterAdapter mAdapter; 24 | private RecyclerView.LayoutManager mLayoutManager; 25 | private IRecyclerViewIntermediary mIntermediary; 26 | 27 | private List mStrings = new ArrayList<>(); 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState){ 31 | super.onCreate(savedInstanceState); 32 | mContext = this; 33 | setContentView(R.layout.activity_example); 34 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 35 | 36 | setTitle("Horizontal Linear Layout"); 37 | } 38 | 39 | private void init(){ 40 | mStrings.clear(); 41 | int count = new Random().nextInt(10)+5; 42 | for(int i = 0; i < count; i++){ 43 | mStrings.add(Integer.toString(i)); 44 | } 45 | mIntermediary = new ExampleIntermediary(mStrings); 46 | 47 | mLayoutManager = new LinearLayoutManager(mContext); 48 | ((LinearLayoutManager) mLayoutManager).setOrientation(LinearLayoutManager.HORIZONTAL); 49 | 50 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 51 | 52 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 53 | 54 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 55 | 56 | } 57 | 58 | public void onResume(){ 59 | super.onResume(); 60 | init(); 61 | mRecyclerView.setLayoutManager(mLayoutManager); 62 | mRecyclerView.setAdapter(mAdapter); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleHorizontalStaggeredGridActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 10 | import com.willblaschko.android.headerfooterrecyclerview.R; 11 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | /** 18 | * Created by Will on 2/8/2015. 19 | */ 20 | public class ExampleHorizontalStaggeredGridActivity extends Activity { 21 | private Context mContext; 22 | private RecyclerView mRecyclerView; 23 | private RecyclerViewHeaderFooterAdapter mAdapter; 24 | private RecyclerView.LayoutManager mLayoutManager; 25 | private IRecyclerViewIntermediary mIntermediary; 26 | 27 | private List mStrings = new ArrayList<>(); 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState){ 31 | super.onCreate(savedInstanceState); 32 | mContext = this; 33 | setContentView(R.layout.activity_example); 34 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 35 | 36 | setTitle("Horizontal Staggered Grid"); 37 | } 38 | 39 | private void init(){ 40 | mStrings.clear(); 41 | int count = new Random().nextInt(10)+5; 42 | for(int i = 0; i < count; i++){ 43 | mStrings.add(Integer.toString(i)); 44 | } 45 | mIntermediary = new ExampleIntermediary(mStrings); 46 | 47 | mLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL); 48 | 49 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 50 | 51 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 52 | 53 | 54 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 55 | 56 | 57 | } 58 | 59 | public void onResume(){ 60 | super.onResume(); 61 | init(); 62 | mRecyclerView.setLayoutManager(mLayoutManager); 63 | mRecyclerView.setAdapter(mAdapter); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleIntermediary.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 10 | import com.willblaschko.android.headerfooterrecyclerview.R; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by Will on 2/8/2015. 16 | */ 17 | public class ExampleIntermediary implements IRecyclerViewIntermediary { 18 | 19 | private List mItems; 20 | 21 | public ExampleIntermediary(List items){ 22 | mItems=items; 23 | } 24 | 25 | @Override 26 | public int getItemCount() { 27 | return mItems.size(); 28 | } 29 | 30 | @Override 31 | public Object getItem(int position) { 32 | return mItems.get(position); 33 | } 34 | 35 | @Override 36 | public RecyclerView.ViewHolder getViewHolder(ViewGroup viewGroup, int type) { 37 | View v; 38 | switch (type){ 39 | case 1: 40 | v = View.inflate(viewGroup.getContext(), R.layout.item_string_1, null); 41 | break; 42 | case 2: 43 | v = View.inflate(viewGroup.getContext(), R.layout.item_string_2, null); 44 | break; 45 | case 3: 46 | v = View.inflate(viewGroup.getContext(), R.layout.item_string_3, null); 47 | break; 48 | default: 49 | v = View.inflate(viewGroup.getContext(), R.layout.item_string_4, null); 50 | break; 51 | } 52 | return new TestViewHolder(v); 53 | } 54 | 55 | @Override 56 | public int getItemViewType(int position) { 57 | return position % 4; //any logic can go here 58 | } 59 | 60 | @Override 61 | public void populateViewHolder(RecyclerView.ViewHolder viewHolder, int position) { 62 | ((TestViewHolder) viewHolder).mTextView.setText(mItems.get(position)); 63 | } 64 | 65 | private class TestViewHolder extends RecyclerView.ViewHolder{ 66 | TextView mTextView; 67 | ImageView mImageView; 68 | public TestViewHolder(View itemView) { 69 | super(itemView); 70 | this.mTextView = (TextView) itemView.findViewById(R.id.text); 71 | this.mImageView = (ImageView) itemView.findViewById(R.id.image); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleLandingActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.R; 10 | 11 | /** 12 | * Created by Will on 2/8/2015. 13 | */ 14 | public class ExampleLandingActivity extends Activity{ 15 | 16 | private Context mContext; 17 | 18 | @Override 19 | public void onCreate(Bundle savedInstanceState){ 20 | super.onCreate(savedInstanceState); 21 | mContext = this; 22 | 23 | setTitle("Header Foot Adapter Example"); 24 | 25 | setContentView(R.layout.activity_landing); 26 | 27 | findViewById(R.id.ll_h).setOnClickListener(new View.OnClickListener() { 28 | @Override 29 | public void onClick(View v) { 30 | Intent i = new Intent(mContext, ExampleHorizontalLinearLayoutActivity.class); 31 | startActivity(i); 32 | } 33 | }); 34 | findViewById(R.id.ll_v).setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | Intent i = new Intent(mContext, ExampleVerticalLinearLayoutActivity.class); 38 | startActivity(i); 39 | } 40 | }); 41 | findViewById(R.id.sg_h).setOnClickListener(new View.OnClickListener() { 42 | @Override 43 | public void onClick(View v) { 44 | Intent i = new Intent(mContext, ExampleHorizontalStaggeredGridActivity.class); 45 | startActivity(i); 46 | } 47 | }); 48 | findViewById(R.id.sg_v).setOnClickListener(new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | Intent i = new Intent(mContext, ExampleVerticalStaggeredGridActivity.class); 52 | startActivity(i); 53 | } 54 | }); 55 | findViewById(R.id.g_h).setOnClickListener(new View.OnClickListener() { 56 | @Override 57 | public void onClick(View v) { 58 | Intent i = new Intent(mContext, ExampleHorizontalGridActivity.class); 59 | startActivity(i); 60 | } 61 | }); 62 | findViewById(R.id.g_v).setOnClickListener(new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | Intent i = new Intent(mContext, ExampleVerticalGridActivity.class); 66 | startActivity(i); 67 | } 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleVerticalGridActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.GridLayoutManager; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | 10 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 11 | import com.willblaschko.android.headerfooterrecyclerview.R; 12 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Random; 17 | 18 | /** 19 | * Created by Will on 2/8/2015. 20 | */ 21 | public class ExampleVerticalGridActivity extends Activity { 22 | private Context mContext; 23 | private RecyclerView mRecyclerView; 24 | private RecyclerViewHeaderFooterAdapter mAdapter; 25 | private RecyclerView.LayoutManager mLayoutManager; 26 | private IRecyclerViewIntermediary mIntermediary; 27 | 28 | private List mStrings = new ArrayList<>(); 29 | 30 | @Override 31 | public void onCreate(Bundle savedInstanceState){ 32 | super.onCreate(savedInstanceState); 33 | mContext = this; 34 | setContentView(R.layout.activity_example); 35 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 36 | setTitle("Vertical Grid"); 37 | } 38 | 39 | private void init(){ 40 | mStrings.clear(); 41 | int count = new Random().nextInt(10)+5; 42 | for(int i = 0; i < count; i++){ 43 | mStrings.add(Integer.toString(i)); 44 | } 45 | mIntermediary = new ExampleIntermediary(mStrings); 46 | 47 | mLayoutManager = new GridLayoutManager(mContext, 3, LinearLayoutManager.VERTICAL, false); 48 | 49 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 50 | 51 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 52 | 53 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 54 | 55 | } 56 | 57 | public void onResume(){ 58 | super.onResume(); 59 | init(); 60 | 61 | mRecyclerView.setLayoutManager(mLayoutManager); 62 | mRecyclerView.setAdapter(mAdapter); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleVerticalLinearLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 10 | import com.willblaschko.android.headerfooterrecyclerview.R; 11 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | /** 18 | * Created by Will on 2/8/2015. 19 | */ 20 | public class ExampleVerticalLinearLayoutActivity extends Activity { 21 | private Context mContext; 22 | private RecyclerView mRecyclerView; 23 | private RecyclerViewHeaderFooterAdapter mAdapter; 24 | private RecyclerView.LayoutManager mLayoutManager; 25 | private IRecyclerViewIntermediary mIntermediary; 26 | 27 | private List mStrings = new ArrayList<>(); 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState){ 31 | super.onCreate(savedInstanceState); 32 | mContext = this; 33 | setContentView(R.layout.activity_example); 34 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 35 | setTitle("Vertical Linear Layout"); 36 | } 37 | 38 | private void init(){ 39 | mStrings.clear(); 40 | int count = new Random().nextInt(10)+5; 41 | for(int i = 0; i < count; i++){ 42 | mStrings.add(Integer.toString(i)); 43 | } 44 | mIntermediary = new ExampleIntermediary(mStrings); 45 | 46 | mLayoutManager = new LinearLayoutManager(mContext); 47 | ((LinearLayoutManager) mLayoutManager).setOrientation(LinearLayoutManager.VERTICAL); 48 | 49 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 50 | 51 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 52 | 53 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 54 | 55 | } 56 | 57 | public void onResume(){ 58 | super.onResume(); 59 | init(); 60 | 61 | mRecyclerView.setLayoutManager(mLayoutManager); 62 | mRecyclerView.setAdapter(mAdapter); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/willblaschko/example/ExampleVerticalStaggeredGridActivity.java: -------------------------------------------------------------------------------- 1 | package com.willblaschko.example; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | 9 | import com.willblaschko.android.headerfooterrecyclerview.IRecyclerViewIntermediary; 10 | import com.willblaschko.android.headerfooterrecyclerview.R; 11 | import com.willblaschko.android.headerfooterrecyclerview.RecyclerViewHeaderFooterAdapter; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | /** 18 | * Created by Will on 2/8/2015. 19 | */ 20 | public class ExampleVerticalStaggeredGridActivity extends Activity { 21 | private Context mContext; 22 | private RecyclerView mRecyclerView; 23 | private RecyclerViewHeaderFooterAdapter mAdapter; 24 | private RecyclerView.LayoutManager mLayoutManager; 25 | private IRecyclerViewIntermediary mIntermediary; 26 | 27 | private List mStrings = new ArrayList<>(); 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState){ 31 | super.onCreate(savedInstanceState); 32 | mContext = this; 33 | setContentView(R.layout.activity_example); 34 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 35 | 36 | setTitle("Vertical Staggered Grid"); 37 | } 38 | 39 | private void init(){ 40 | mStrings.clear(); 41 | int count = new Random().nextInt(100)+5; 42 | for(int i = 0; i < count; i++){ 43 | mStrings.add(Integer.toString(i)); 44 | } 45 | mIntermediary = new ExampleIntermediary(mStrings); 46 | 47 | mLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); 48 | 49 | mAdapter = new RecyclerViewHeaderFooterAdapter(mLayoutManager, mIntermediary); 50 | 51 | 52 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header")); 53 | 54 | mAdapter.addHeader(ExampleHeaderFooter.getView(mContext, "Header 2")); 55 | 56 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer")); 57 | 58 | mAdapter.addFooter(ExampleHeaderFooter.getView(mContext, "Footer 2")); 59 | 60 | } 61 | 62 | public void onResume(){ 63 | super.onResume(); 64 | init(); 65 | mRecyclerView.setLayoutManager(mLayoutManager); 66 | mRecyclerView.setAdapter(mAdapter); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_landing.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |