├── bin ├── headergridview.jar ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ └── drawable-xhdpi │ │ └── ic_launcher.png ├── R.txt ├── classes │ └── com │ │ └── origamilabs │ │ └── library │ │ └── headergridview │ │ ├── R.class │ │ ├── R$attr.class │ │ ├── R$style.class │ │ ├── R$drawable.class │ │ ├── R$string.class │ │ ├── BuildConfig.class │ │ └── views │ │ └── HeaderGridView.class └── AndroidManifest.xml ├── libs └── android-support-v4.jar ├── res ├── values │ ├── strings.xml │ └── styles.xml ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── values-v11 │ └── styles.xml └── values-v14 │ └── styles.xml ├── gen └── com │ └── origamilabs │ └── library │ └── headergridview │ ├── BuildConfig.java │ └── R.java ├── .classpath ├── AndroidManifest.xml ├── project.properties ├── proguard-project.txt ├── .project ├── README.md └── src └── com └── origamilabs └── library └── headergridview └── views └── HeaderGridView.java /bin/headergridview.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/headergridview.jar -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/libs/android-support-v4.jar -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HeaderGridView 4 | 5 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /bin/R.txt: -------------------------------------------------------------------------------- 1 | int drawable ic_launcher 0x7f020000 2 | int string app_name 0x7f030000 3 | int style AppBaseTheme 0x7f040000 4 | int style AppTheme 0x7f040001 5 | -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/R.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/R.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/R$attr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/R$attr.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/R$style.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/R$style.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/R$drawable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/R$drawable.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/R$string.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/R$string.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/BuildConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/BuildConfig.class -------------------------------------------------------------------------------- /bin/classes/com/origamilabs/library/headergridview/views/HeaderGridView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maurycyw/HeaderGridView/HEAD/bin/classes/com/origamilabs/library/headergridview/views/HeaderGridView.class -------------------------------------------------------------------------------- /gen/com/origamilabs/library/headergridview/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.origamilabs.library.headergridview; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /bin/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-17 15 | android.library=true 16 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | HeaderGridView 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HeaderGridView 2 | ======= 3 | 4 | ## Introduction 5 | 6 | This is an updated version of GridView which allows for Headers. The Headers themselves are not part of the adapter / data source. This means that the headers only are not being recycled. 7 | 8 | ## Setup 9 | 10 | To use HeaderGridView in your projects, simply add this project to your workspace then add it as a library project to your current project. 11 | 12 | ## Usage 13 | 14 | HeaderGridView can be added as a custom view to any layout. 15 | 16 | instead of ``` ``` use… 17 | ```xml 18 | 19 | ``` 20 | then simply add header views via 21 | ```xml 22 | // same methods as ListView 23 | addHeaderView(View v, Object data, boolean isSelectable); 24 | addHeaderView(View v); 25 | ``` 26 | 27 | ## Tests 28 | 29 | None. 30 | 31 | 32 | ## TODO: 33 | 34 | * implement Footer support. should be simple 35 | * develop tests 36 | 37 | -------------------------------------------------------------------------------- /gen/com/origamilabs/library/headergridview/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.origamilabs.library.headergridview; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static int ic_launcher=0x7f020000; 15 | } 16 | public static final class string { 17 | public static int app_name=0x7f030000; 18 | } 19 | public static final class style { 20 | /** 21 | Base application theme, dependent on API level. This theme is replaced 22 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 23 | 24 | 25 | Theme customizations available in newer API levels can go in 26 | res/values-vXX/styles.xml, while customizations related to 27 | backward-compatibility can go here. 28 | 29 | 30 | Base application theme for API 11+. This theme completely replaces 31 | AppBaseTheme from res/values/styles.xml on API 11+ devices. 32 | 33 | API 11 theme customizations can go here. 34 | 35 | Base application theme for API 14+. This theme completely replaces 36 | AppBaseTheme from BOTH res/values/styles.xml and 37 | res/values-v11/styles.xml on API 14+ devices. 38 | 39 | API 14 theme customizations can go here. 40 | */ 41 | public static int AppBaseTheme=0x7f040000; 42 | /** Application theme. 43 | All customizations that are NOT specific to a particular API-level can go here. 44 | */ 45 | public static int AppTheme=0x7f040001; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/origamilabs/library/headergridview/views/HeaderGridView.java: -------------------------------------------------------------------------------- 1 | package com.origamilabs.library.headergridview.views; 2 | 3 | 4 | import java.util.ArrayList; 5 | 6 | import android.app.Activity; 7 | import android.content.Context; 8 | import android.graphics.Canvas; 9 | import android.util.AttributeSet; 10 | import android.util.DisplayMetrics; 11 | import android.view.View; 12 | import android.widget.AbsListView; 13 | import android.widget.AbsListView.OnScrollListener; 14 | import android.widget.GridView; 15 | import android.widget.ListAdapter; 16 | import android.widget.ListView; 17 | import android.widget.ListView.FixedViewInfo; 18 | 19 | public class HeaderGridView extends GridView implements OnScrollListener{ 20 | 21 | private ListAdapter mAdapter; 22 | private boolean mShowHeader = false; 23 | private Context mContext; 24 | private int mScrollOfsset; 25 | private int initialTopPadding; 26 | private int mDisplayWidth = 0; 27 | 28 | public HeaderGridView(Context context, AttributeSet attrs, int defStyle) { 29 | super(context, attrs, defStyle); 30 | init(context); 31 | } 32 | 33 | public HeaderGridView(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | init(context); 36 | } 37 | 38 | public HeaderGridView(Context context) { 39 | super(context); 40 | init(context); 41 | } 42 | 43 | private void init(Context context){ 44 | mContext = context; 45 | super.setOnScrollListener(this); 46 | } 47 | /** 48 | * A class that represents a fixed view in a list, for example a header at the top 49 | * or a footer at the bottom. 50 | */ 51 | 52 | private ArrayList mHeaderViewInfos = new ArrayList(); 53 | // TODO: add in footer view support. pull request someone? 54 | private ArrayList mFooterViewInfos = new ArrayList(); 55 | 56 | private void notifiyChanged(){ 57 | this.requestLayout(); 58 | this.invalidate(); 59 | } 60 | 61 | public void addHeaderView(View v, Object data, boolean isSelectable) { 62 | 63 | FixedViewInfo info = new ListView(getContext()).new FixedViewInfo(); 64 | info.view = v; 65 | info.data = data; 66 | info.isSelectable = isSelectable; 67 | mHeaderViewInfos.add(info); 68 | 69 | setupView(v); 70 | 71 | int topPadding = this.getPaddingTop(); 72 | if(initialTopPadding == 0){ 73 | initialTopPadding = topPadding; 74 | } 75 | this.setPadding(this.getPaddingLeft(), topPadding+v.getMeasuredHeight(), this.getPaddingRight(), this.getPaddingBottom()); 76 | 77 | // in the case of re-adding a header view, or adding one later on, 78 | // we need to notify the observer 79 | this.notifiyChanged(); 80 | } 81 | 82 | private void setupView(View v){ 83 | // in my application the views are merely just inflated... because of this measure and layout need to be called 84 | 85 | boolean isLayedOut = !((v.getRight()==0) && (v.getLeft()==0) && (v.getTop()==0) && (v.getBottom()==0)); 86 | 87 | // no need to do this more than nce per view. Sometimes people repeat headers. 88 | if(v.getMeasuredHeight() != 0 && isLayedOut ) return; 89 | 90 | if(mDisplayWidth == 0){ 91 | DisplayMetrics displaymetrics = new DisplayMetrics(); 92 | ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); 93 | mDisplayWidth = displaymetrics.widthPixels; 94 | } 95 | 96 | v.measure(MeasureSpec.makeMeasureSpec(mDisplayWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 97 | v.layout(0, getTotalHeaderHeight(), v.getMeasuredWidth(), getTotalHeaderHeight() + v.getMeasuredHeight()); 98 | } 99 | 100 | public void addHeaderView(View v) { 101 | this.addHeaderView(v, null, false); 102 | } 103 | 104 | private void drawHeaders(Canvas canvas) { 105 | int startPos = -mScrollOfsset; // translate view all way up first... 106 | int saveCount = canvas.save(); 107 | for(FixedViewInfo header: mHeaderViewInfos){ 108 | View view = header.view; 109 | canvas.translate(0, startPos); 110 | startPos = view.getMeasuredHeight(); 111 | view.draw(canvas); 112 | } 113 | canvas.restoreToCount(saveCount); 114 | } 115 | 116 | @Override 117 | protected void dispatchDraw(Canvas canvas) { 118 | super.dispatchDraw(canvas); 119 | drawHeaders(canvas); 120 | } 121 | 122 | private void invalidateIfAnimating() { 123 | invalidate(); 124 | } 125 | 126 | public int getHeaderViewCount(){ 127 | return mHeaderViewInfos.size(); 128 | } 129 | 130 | private int getTotalHeaderHeight(){ 131 | int totalHeaderHeight = 0; 132 | for(FixedViewInfo h: mHeaderViewInfos){ 133 | totalHeaderHeight += h.view.getMeasuredHeight(); 134 | } 135 | return totalHeaderHeight; 136 | } 137 | 138 | @Override 139 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 140 | if(this.getAdapter()!=null){ 141 | int count = this.getChildCount(); 142 | int totalHeaderHeight = getTotalHeaderHeight(); 143 | 144 | if(count > 0 && firstVisibleItem == 0){ 145 | View child = this.getChildAt(0); 146 | mScrollOfsset = totalHeaderHeight - child.getTop() + initialTopPadding; 147 | 148 | // need to check to see if should show header 149 | // no need to dispatch otherwise 150 | if(child.getTop() >= 0){ 151 | mShowHeader = true; 152 | }else{ 153 | mShowHeader = false; 154 | } 155 | }else{ 156 | mShowHeader = false; 157 | } 158 | 159 | if(mShowHeader){ 160 | this.invalidateIfAnimating(); 161 | } 162 | } 163 | 164 | } 165 | 166 | /** 167 | * Remove the view and return true is a view has been removed. 168 | * @param v 169 | * @return 170 | */ 171 | public boolean removeHeaderView(View v) { 172 | if (mHeaderViewInfos.size() > 0) { 173 | return removeFixedViewInfo(v, mHeaderViewInfos); 174 | } 175 | return false; 176 | } 177 | 178 | private boolean removeFixedViewInfo(View v, ArrayList where) { 179 | int len = where.size(); 180 | int count = 0; 181 | for (int i = 0; i < len; ++i) { 182 | FixedViewInfo info = where.get(i); 183 | if (info.view == v) { 184 | this.setPadding(this.getPaddingLeft(), getPaddingTop()-v.getMeasuredHeight(), this.getPaddingRight(), this.getPaddingBottom()); 185 | where.remove(i); 186 | count++; 187 | break; 188 | } 189 | } 190 | 191 | return count > 0; 192 | } 193 | 194 | @Override 195 | public void onScrollStateChanged(AbsListView view, int scrollState) { 196 | } 197 | } 198 | --------------------------------------------------------------------------------