├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── sys │ │ └── blackcat │ │ └── stickheaderlayout │ │ └── demo │ │ ├── DemoUtils.java │ │ ├── GridViewDemo.java │ │ ├── ListViewDemo.java │ │ ├── MainActivity.java │ │ ├── RecyclerViewDemo.java │ │ ├── ScrollViewDemo.java │ │ ├── ViewPagerDemo.java │ │ ├── adapter │ │ ├── FragmentAdapter.java │ │ └── MyAdapter.java │ │ └── fragment │ │ ├── GridViewFragment.java │ │ ├── ListViewFragment.java │ │ ├── RecyclerViewFragment.java │ │ └── ScrollViewFragment.java │ └── res │ ├── layout │ ├── activity_grid_demo.xml │ ├── activity_list_demo.xml │ ├── activity_main.xml │ ├── activity_recycler_view_demo.xml │ ├── activity_scroll_view_demo.xml │ ├── activity_view_pager_demo.xml │ ├── list_head.xml │ ├── recycler_view_fragment.xml │ └── scroll_view_fragment.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image └── pp.gif ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── sys │ │ └── blackcat │ │ └── stickheaderlayout │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── sys │ │ │ └── blackcat │ │ │ └── stickheaderlayout │ │ │ ├── IpmlScrollChangListener.java │ │ │ └── StickHeaderLayout.java │ └── res │ │ └── values │ │ ├── attrs.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── sys │ └── blackcat │ └── stickheaderlayout │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | 10 | # built application files 11 | *.apk 12 | *.ap_ 13 | 14 | # files for the dex VM 15 | # Built application files 16 | *.apk 17 | *.ap_ 18 | 19 | # Files for the Dalvik VM 20 | *.dex 21 | 22 | # Java class files 23 | *.class 24 | 25 | # built native files (uncomment if you build your own) 26 | # *.o 27 | # *.so 28 | 29 | # generated files 30 | bin/ 31 | gen/ 32 | 33 | # Ignore gradle files 34 | # Generated files 35 | bin/ 36 | gen/ 37 | 38 | # Gradle files 39 | .gradle/ 40 | build/ 41 | 42 | # Local configuration file (sdk path, etc) 43 | local.properties 44 | 45 | # Proguard folder generated by Eclipse 46 | proguard/ 47 | 48 | # Eclipse Metadata 49 | .metadata/ 50 | 51 | # Mac OS X clutter 52 | *.DS_Store 53 | 54 | # Windows clutter 55 | Thumbs.db 56 | 57 | # Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067) 58 | .idea/workspace.xml 59 | .idea/tasks.xml 60 | .idea/datasources.xml 61 | .idea/dataSources.ids 62 | # Log Files 63 | *.log 64 | 65 | # Android Studio Navigation editor temp files 66 | .navigation/ 67 | 68 | # Android Studio captures folder 69 | captures/ 70 | .idea/gradle.xml 71 | .idea/misc.xml 72 | .idea/vcs.xml 73 | 74 | .idea/modules.xml 75 | .idea/compiler.xml 76 | .idea/encodings.xml 77 | .idea/runConfigurations.xml 78 | .idea/findbugs-idea.xml 79 | .idea/.name 80 | 81 | gradle.properties 82 | .idea/copyright/profiles_settings.xml 83 | 84 | .idea/* 85 | .idea 86 | 87 | 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stickheaderlayout 2 | stickheaderlayout 3 | 4 | ## maven 引用 5 | ``` 6 | 7 | com.sys.blackcat.stickheaderlayout 8 | library 9 | 1.3.5 10 | pom 11 | 12 | ``` 13 | ------------------- 14 | ## Gradle 引用 15 | compile 'com.sys.blackcat.stickheaderlayout:library:1.3.4' 16 | 17 | ### [ ![Download](https://api.bintray.com/packages/yang747046912/maven/StickHeaderLayout/images/download.svg) ](https://bintray.com/yang747046912/maven/StickHeaderLayout/_latestVersion) 18 | 19 | 20 | #自定义Stickheaderlayout介绍 21 | ##效果 22 | ![Stickheaderlayout](https://raw.githubusercontent.com/yang747046912/Stickheaderlayout/master/image/pp.gif) 23 | ##原理 24 | Stickheaderlayout 继承 ViewGroup ,总体分为三块 25 | - 头部 26 | 可以放置上下不可滚动的view 27 | - 标题 28 | 可以放置上下不可滚动的view(不想出现标题则可以仅放一条横线) 29 | - 内容 30 | 可以放置GridView、ListView、RecyclerView、ScrollView、ViewPager并且兼容下拉刷新跟上拉自动加载更多 31 | 32 | 使用ViewDragHelper跟View事件的拦截相关的东西,ViewDragHelper不了解的可访问http://www.jianshu.com/p/bfe857e509c9 33 | 34 | ##IpmlScrollChangListener 介绍 35 | 包含四个方法 36 | - boolean isReadyForPull() 37 | 是否可以将head拉下来 38 | - void onStartScroll() 39 | 滚动开始 40 | - void onStopScroll() 41 | 滚动开始 42 | - void onScrollChange(int dy, int totallDy) 43 | 滚动距离的变化 dy:滚动的距离 totallDy:可滚动的最大距离 配合 setRetentionHeight(int )可以用于做渐变的titlebar (见viewPagerDemo效果图) 44 | 45 | ##StickHeaderLayout 方法介绍 46 | - setRetentionHeight(int retentionHeight) 47 | 设置向上滚动headView 保留的高度 48 | - setScroll(IpmlScrollChangListener scroll) 49 | 设置滚动回调 50 | 51 | ##ViewDragHelper初始化 52 | - 滚动状态监听 53 | ``` 54 | public void onViewDragStateChanged(int state) { 55 | super.onViewDragStateChanged(state); 56 | if (scroll != null) { 57 | if (state == ViewDragHelper.STATE_IDLE) { 58 | scroll.onStopScroll(); 59 | } 60 | if (state == ViewDragHelper.STATE_SETTLING) { 61 | scroll.onStartScroll(); 62 | } 63 | } 64 | } 65 | ``` 66 | - 判断ViewDragHelper是否触发滚动 头部、标题、内容都可以滑动 67 | ``` 68 | public boolean tryCaptureView(View child, int pointerId) { 69 | return true; 70 | } 71 | ``` 72 | - 手指按住contentView时滚动时,头部、标题、内容的位置变化,返回contentView是移动距离 73 | ``` 74 | public int clampViewPositionVertical(View child, int top, int dy) { 75 | if (child == headView) { 76 | int headViewTop = headView.getTop() + dy; 77 | if (headViewTop > 0) { 78 | headViewTop = 0; 79 | } else if (headViewTop < -headHeight + retentionHeight) { 80 | headViewTop = -headHeight + retentionHeight; 81 | } 82 | return headViewTop; 83 | } 84 | if (child == titleView) { 85 | int titleTop = titleView.getTop() + dy; 86 | if (titleTop > headHeight) { 87 | titleTop = headHeight; 88 | } else if (titleTop < retentionHeight) { 89 | titleTop = retentionHeight; 90 | } 91 | return titleTop; 92 | } 93 | int contentTop = contentView.getTop() + dy; 94 | if (contentTop > headHeight + titleHeight) { 95 | contentTop = headHeight + titleHeight; 96 | } else if (contentTop < titleHeight + retentionHeight) { 97 | contentTop = titleHeight + retentionHeight; 98 | } 99 | return contentTop; 100 | } 101 | ``` 102 | - 手指离开屏幕时,触发快速滚动 103 | ``` 104 | public void onViewReleased(View releasedChild, float xvel, float yvel) { 105 | super.onViewReleased(releasedChild, xvel, yvel); 106 | if (dragEdge == DragEdge.Bottom) { 107 | if (yvel < -mDragHelper.getMinVelocity()) { 108 | mDragHelper.smoothSlideViewTo(contentView, 0, titleHeight + retentionHeight); 109 | } else if (releasedChild == headView) { 110 | mDragHelper.smoothSlideViewTo(headView, 0, -headHeight + retentionHeight); 111 | } else { 112 | mDragHelper.smoothSlideViewTo(titleView, 0, retentionHeight); 113 | } 114 | } else if (dragEdge == DragEdge.Top) { 115 | if (releasedChild == contentView) { 116 | mDragHelper.smoothSlideViewTo(contentView, 0, titleHeight + headHeight); 117 | } else if (releasedChild == headView) { 118 | mDragHelper.smoothSlideViewTo(headView, 0, 0); 119 | } else { 120 | mDragHelper.smoothSlideViewTo(titleView, 0, headHeight); 121 | } 122 | } 123 | invalidate(); 124 | } 125 | ``` 126 | - 触发快速滚动后头部、标题、内容的位置变化 127 | ``` 128 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 129 | super.onViewPositionChanged(changedView, left, top, dx, dy); 130 | if (changedView == contentView) { 131 | int contentTop = contentView.getTop(); 132 | titleView.layout(0, contentTop - titleHeight, titleView.getMeasuredWidth(), contentTop); 133 | headView.layout(0, contentTop - titleHeight - headHeight, titleView.getMeasuredWidth(), contentTop - titleHeight); 134 | } else if (changedView == headView) { 135 | int contentTop = headView.getTop(); 136 | titleView.layout(0, contentTop + headHeight, titleView.getMeasuredWidth(), contentTop + headHeight + titleHeight); 137 | contentView.layout(0, contentTop + headHeight + titleHeight, contentView.getMeasuredWidth(), contentTop + headHeight + titleHeight + contentHeight); 138 | } else { 139 | int contentTop = titleView.getTop(); 140 | headView.layout(0, contentTop - headHeight, headView.getMeasuredWidth(), contentTop); 141 | contentView.layout(0, contentTop + titleHeight, contentView.getMeasuredWidth(), contentTop + titleHeight + contentHeight); 142 | } 143 | if (scroll != null) { 144 | scroll.onScrollChange(Math.abs(headView.getTop()), headHeight - retentionHeight); 145 | } 146 | } 147 | ``` 148 | 149 | ##手势的相关处理 150 | - 事件的拦截 151 | ``` 152 | public boolean onInterceptTouchEvent(MotionEvent ev) { 153 | final int action = MotionEventCompat.getActionMasked(ev); 154 | switch (action) { 155 | case MotionEvent.ACTION_DOWN: 156 | mDragHelper.processTouchEvent(ev); 157 | sX = ev.getRawX(); 158 | sY = ev.getRawY(); 159 | mIsBeingDragged = false; 160 | break; 161 | case MotionEvent.ACTION_MOVE: 162 | checkCanDrag(ev); 163 | if (dragEdge == DragEdge.Left || dragEdge == DragEdge.Right || dragEdge == DragEdge.None) { 164 | return false; 165 | } 166 | if (scroll != null && !scroll.isReadyForPull()) { 167 | if (dragEdge == DragEdge.Bottom && titleView.getTop() == headHeight) { 168 | return true; 169 | } 170 | return false; 171 | } else { 172 | if (dragEdge == DragEdge.Bottom) { 173 | if (titleView.getTop() == retentionHeight) { 174 | mIsBeingDragged = false; 175 | dragEdge = DragEdge.None; 176 | } 177 | } else if (dragEdge == DragEdge.Top) { 178 | if (titleView.getTop() == headHeight) { 179 | dragEdge = DragEdge.None; 180 | mIsBeingDragged = false; 181 | } 182 | } 183 | } 184 | break; 185 | case MotionEvent.ACTION_UP: 186 | case MotionEvent.ACTION_CANCEL: 187 | mIsBeingDragged = false; 188 | mDragHelper.processTouchEvent(ev); 189 | break; 190 | default: 191 | mDragHelper.processTouchEvent(ev); 192 | break; 193 | } 194 | return mIsBeingDragged; 195 | } 196 | ``` 197 | - 判断手势的滑动方向 198 | ``` 199 | public enum DragEdge { 200 | None, 201 | Left, 202 | Top, 203 | Right, 204 | Bottom 205 | } 206 | private void checkCanDrag(MotionEvent ev) { 207 | float dx = ev.getRawX() - sX; 208 | float dy = ev.getRawY() - sY; 209 | float angle = Math.abs(dy / dx); 210 | angle = (float) Math.toDegrees(Math.atan(angle)); 211 | if (angle < 45) { 212 | if (dx > 0) { 213 | dragEdge = DragEdge.Left; 214 | } else if (dx < 0) { 215 | dragEdge = DragEdge.Right; 216 | } 217 | } else { 218 | if (dy > 0) { 219 | dragEdge = DragEdge.Top; 220 | } else if (dy < 0) { 221 | dragEdge = DragEdge.Bottom; 222 | } 223 | } 224 | mIsBeingDragged = true; 225 | } 226 | ``` 227 | - 事件的处理 228 | ``` 229 | public boolean onTouchEvent(MotionEvent event) { 230 | int action = event.getActionMasked(); 231 | switch (action) { 232 | case MotionEvent.ACTION_DOWN: 233 | mDragHelper.processTouchEvent(event); 234 | case MotionEvent.ACTION_MOVE: { 235 | checkCanDrag(event); 236 | if (mIsBeingDragged) { 237 | getParent().requestDisallowInterceptTouchEvent(true); 238 | try { 239 | mDragHelper.processTouchEvent(event); 240 | } catch (Exception e) { 241 | } 242 | } 243 | break; 244 | } 245 | case MotionEvent.ACTION_UP: 246 | case MotionEvent.ACTION_CANCEL: 247 | mIsBeingDragged = false; 248 | mDragHelper.processTouchEvent(event); 249 | break; 250 | default://handle other action, such as ACTION_POINTER_DOWN/UP 251 | mDragHelper.processTouchEvent(event); 252 | } 253 | return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN; 254 | } 255 | ``` 256 | 257 | ##使用 以ListView 为例子 258 | - 布局文件 259 | ``` 260 | 261 | 265 | 266 | 273 | 274 | 281 | 282 | 287 | 288 | ``` 289 | - Activity 逻辑处理 290 | ``` 291 | public class ListViewDemo extends AppCompatActivity { 292 | private StickHeaderLayout layout; 293 | private ListView listView; 294 | @Override 295 | protected void onCreate(Bundle savedInstanceState) { 296 | super.onCreate(savedInstanceState); 297 | setContentView(R.layout.activity_list_demo); 298 | setTitle(R.string.list_example); 299 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 300 | listView = (ListView) findViewById(R.id.list); 301 | layout.setScroll(new IpmlScrollChangListener() { 302 | @Override 303 | public boolean isReadyForPull() { 304 | return DemoUtils.isOnTop(listView); 305 | } 306 | 307 | @Override 308 | public void onStartScroll() { 309 | 310 | } 311 | 312 | @Override 313 | public void onStopScroll() { 314 | 315 | } 316 | 317 | @Override 318 | public void onScrollChange(int dy, int totallDy) { 319 | 320 | } 321 | }); 322 | listView.addHeaderView(getLayoutInflater().inflate(R.layout.list_head, null)); 323 | listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, DemoUtils.getData())); 324 | } 325 | } 326 | ``` 327 | - DemoUtils 判断内容部分是否可以滑动 328 | ``` 329 | public static boolean isOnTop(ViewGroup viewGroup) { 330 | int[] groupLocation = new int[2]; 331 | viewGroup.getLocationOnScreen(groupLocation); 332 | int[] itemLocation = new int[2]; 333 | if (viewGroup.getChildAt(0) != null) { 334 | viewGroup.getChildAt(0).getLocationOnScreen(itemLocation); 335 | return groupLocation[1] == itemLocation[1]; 336 | } 337 | return false; 338 | } 339 | ``` 340 | 341 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.sys.blackcat.stickheaderlayout.demo" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0.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(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.3.0' 26 | compile 'com.android.support:recyclerview-v7:23.3.0' 27 | compile project(':library') 28 | } 29 | -------------------------------------------------------------------------------- /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 /home/yangcai/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/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/DemoUtils.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.view.ViewGroup; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by yangcai on 16-6-4. 10 | */ 11 | public class DemoUtils { 12 | 13 | public static List getData() { 14 | List data = new ArrayList<>(); 15 | for (int i = 0; i < 100; i++) { 16 | data.add("我是第" + i + "条数据"); 17 | } 18 | return data; 19 | } 20 | 21 | /** 22 | * 判断listView 是否可以滑动 23 | * 24 | * @param viewGroup 25 | * @return 26 | */ 27 | public static boolean isOnTop(ViewGroup viewGroup) { 28 | int[] groupLocation = new int[2]; 29 | viewGroup.getLocationOnScreen(groupLocation); 30 | int[] itemLocation = new int[2]; 31 | if (viewGroup.getChildAt(0) != null) { 32 | viewGroup.getChildAt(0).getLocationOnScreen(itemLocation); 33 | return groupLocation[1] == itemLocation[1]; 34 | } 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/GridViewDemo.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.widget.ArrayAdapter; 6 | import android.widget.GridView; 7 | 8 | import com.sys.blackcat.stickheaderlayout.IpmlScrollChangListener; 9 | import com.sys.blackcat.stickheaderlayout.StickHeaderLayout; 10 | 11 | public class GridViewDemo extends AppCompatActivity { 12 | 13 | 14 | private StickHeaderLayout layout; 15 | private GridView gridView; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_grid_demo); 21 | setTitle(R.string.grid_example); 22 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 23 | gridView = (GridView) findViewById(R.id.grid); 24 | layout.setScroll(new IpmlScrollChangListener() { 25 | @Override 26 | public boolean isReadyForPull() { 27 | return DemoUtils.isOnTop(gridView); 28 | } 29 | 30 | @Override 31 | public void onStartScroll() { 32 | 33 | } 34 | 35 | @Override 36 | public void onStopScroll() { 37 | 38 | } 39 | 40 | @Override 41 | public void onScrollChange(int dy, int totallDy) { 42 | 43 | } 44 | }); 45 | gridView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, DemoUtils.getData())); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/ListViewDemo.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.widget.ArrayAdapter; 6 | import android.widget.ListView; 7 | 8 | import com.sys.blackcat.stickheaderlayout.IpmlScrollChangListener; 9 | import com.sys.blackcat.stickheaderlayout.StickHeaderLayout; 10 | 11 | public class ListViewDemo extends AppCompatActivity { 12 | 13 | private StickHeaderLayout layout; 14 | private ListView listView; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_list_demo); 20 | setTitle(R.string.list_example); 21 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 22 | listView = (ListView) findViewById(R.id.list); 23 | layout.setScroll(new IpmlScrollChangListener() { 24 | @Override 25 | public boolean isReadyForPull() { 26 | return DemoUtils.isOnTop(listView); 27 | } 28 | 29 | @Override 30 | public void onStartScroll() { 31 | 32 | } 33 | 34 | @Override 35 | public void onStopScroll() { 36 | 37 | } 38 | 39 | @Override 40 | public void onScrollChange(int dy, int totallDy) { 41 | 42 | } 43 | }); 44 | listView.addHeaderView(getLayoutInflater().inflate(R.layout.list_head, null)); 45 | listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, DemoUtils.getData())); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | } 15 | 16 | 17 | public void onClick(View view) { 18 | switch (view.getId()) { 19 | case R.id.btn_list: 20 | openActivty(ListViewDemo.class); 21 | break; 22 | case R.id.btn_grid: 23 | openActivty(GridViewDemo.class); 24 | break; 25 | case R.id.btn_scrollview: 26 | openActivty(ScrollViewDemo.class); 27 | break; 28 | case R.id.btn_recycler_view: 29 | openActivty(RecyclerViewDemo.class); 30 | break; 31 | case R.id.btn_view_pager: 32 | openActivty(ViewPagerDemo.class); 33 | break; 34 | } 35 | } 36 | 37 | private void openActivty(Class cl) { 38 | Intent intent = new Intent(this, cl); 39 | startActivity(intent); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/RecyclerViewDemo.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | 8 | import com.sys.blackcat.stickheaderlayout.IpmlScrollChangListener; 9 | import com.sys.blackcat.stickheaderlayout.StickHeaderLayout; 10 | import com.sys.blackcat.stickheaderlayout.demo.adapter.MyAdapter; 11 | 12 | public class RecyclerViewDemo extends AppCompatActivity { 13 | 14 | 15 | private StickHeaderLayout layout; 16 | private RecyclerView recyclerView; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_recycler_view_demo); 22 | setTitle(R.string.recyclerView_example); 23 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 24 | recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 25 | layout.setScroll(new IpmlScrollChangListener() { 26 | @Override 27 | public boolean isReadyForPull() { 28 | return DemoUtils.isOnTop(recyclerView); 29 | } 30 | 31 | @Override 32 | public void onStartScroll() { 33 | 34 | } 35 | 36 | @Override 37 | public void onStopScroll() { 38 | 39 | } 40 | 41 | @Override 42 | public void onScrollChange(int dy, int totallDy) { 43 | 44 | } 45 | }); 46 | 47 | MyAdapter myAdapter = new MyAdapter(); 48 | myAdapter.addAll(DemoUtils.getData()); 49 | // LinearLayoutManager manager = new LinearLayoutManager(this); 50 | // manager.setOrientation(LinearLayoutManager.VERTICAL); 51 | // GridLayoutManager manager = new GridLayoutManager(this,3); 52 | StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); 53 | recyclerView.setLayoutManager(manager); 54 | recyclerView.setAdapter(myAdapter); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/ScrollViewDemo.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.widget.ScrollView; 6 | 7 | import com.sys.blackcat.stickheaderlayout.IpmlScrollChangListener; 8 | import com.sys.blackcat.stickheaderlayout.StickHeaderLayout; 9 | 10 | public class ScrollViewDemo extends AppCompatActivity { 11 | 12 | 13 | private StickHeaderLayout layout; 14 | private ScrollView scrollView; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_scroll_view_demo); 20 | setTitle(R.string.scrollView_example); 21 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 22 | scrollView = (ScrollView) findViewById(R.id.scroll_view); 23 | layout.setScroll(new IpmlScrollChangListener() { 24 | @Override 25 | public boolean isReadyForPull() { 26 | return DemoUtils.isOnTop(scrollView); 27 | } 28 | 29 | @Override 30 | public void onStartScroll() { 31 | 32 | } 33 | 34 | @Override 35 | public void onStopScroll() { 36 | 37 | } 38 | 39 | @Override 40 | public void onScrollChange(int dy, int totallDy) { 41 | 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/ViewPagerDemo.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.view.ViewPager; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.sys.blackcat.stickheaderlayout.IpmlScrollChangListener; 12 | import com.sys.blackcat.stickheaderlayout.StickHeaderLayout; 13 | import com.sys.blackcat.stickheaderlayout.demo.adapter.FragmentAdapter; 14 | import com.sys.blackcat.stickheaderlayout.demo.fragment.GridViewFragment; 15 | import com.sys.blackcat.stickheaderlayout.demo.fragment.ListViewFragment; 16 | import com.sys.blackcat.stickheaderlayout.demo.fragment.RecyclerViewFragment; 17 | import com.sys.blackcat.stickheaderlayout.demo.fragment.ScrollViewFragment; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class ViewPagerDemo extends AppCompatActivity { 23 | 24 | private StickHeaderLayout layout; 25 | private ViewPager viewPager; 26 | private FragmentAdapter adapter; 27 | private TextView txt; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_view_pager_demo); 33 | setTitle(R.string.viewPager_example); 34 | layout = (StickHeaderLayout) findViewById(R.id.stick_header_layout); 35 | adapter = new FragmentAdapter(getSupportFragmentManager(), getFragment()); 36 | viewPager = (ViewPager) findViewById(R.id.vp_view_pager); 37 | txt = (TextView) findViewById(R.id.tv_txt); 38 | layout.setScroll(new IpmlScrollChangListener() { 39 | private int rColor = 0xff; 40 | private int gColor = 0xff; 41 | private int bColor = 0x00; 42 | 43 | @Override 44 | public boolean isReadyForPull() { 45 | ViewGroup view = (ViewGroup) adapter.getItem(viewPager.getCurrentItem()).getView(); 46 | if (view != null) { 47 | return DemoUtils.isOnTop(view); 48 | } 49 | return true; 50 | } 51 | 52 | @Override 53 | public void onStartScroll() { 54 | 55 | } 56 | 57 | @Override 58 | public void onStopScroll() { 59 | 60 | } 61 | 62 | @Override 63 | public void onScrollChange(int dy, int totallDy) { 64 | int aColor = (dy * 255) / totallDy; 65 | txt.setBackgroundColor(Color.argb(aColor, rColor, gColor, bColor)); 66 | } 67 | }); 68 | viewPager.setAdapter(adapter); 69 | } 70 | 71 | 72 | private List getFragment() { 73 | List list = new ArrayList<>(); 74 | list.add(new GridViewFragment()); 75 | list.add(new ListViewFragment()); 76 | list.add(new ScrollViewFragment()); 77 | list.add(new RecyclerViewFragment()); 78 | return list; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/adapter/FragmentAdapter.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by Administrator on 2016/6/9. 12 | */ 13 | public class FragmentAdapter extends FragmentPagerAdapter { 14 | private List list = new ArrayList<>(); 15 | 16 | public FragmentAdapter(FragmentManager fm, List list) { 17 | super(fm); 18 | this.list = list; 19 | } 20 | 21 | @Override 22 | public Fragment getItem(int position) { 23 | return list.get(position); 24 | } 25 | 26 | @Override 27 | public int getCount() { 28 | return list.size(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/adapter/MyAdapter.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.TextView; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by Administrator on 2016/6/9. 13 | */ 14 | public class MyAdapter extends RecyclerView.Adapter { 15 | 16 | private List data = new ArrayList<>(); 17 | 18 | @Override 19 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 20 | View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null); 21 | return new Holder(view); 22 | } 23 | 24 | @Override 25 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 26 | ((TextView) (holder.itemView)).setText(data.get(position)); 27 | } 28 | 29 | @Override 30 | public int getItemCount() { 31 | return data.size(); 32 | } 33 | 34 | public void addAll(List data) { 35 | this.data.addAll(data); 36 | notifyDataSetChanged(); 37 | } 38 | 39 | class Holder extends RecyclerView.ViewHolder { 40 | 41 | public Holder(View itemView) { 42 | super(itemView); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/fragment/GridViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.AbsListView; 10 | import android.widget.ArrayAdapter; 11 | import android.widget.GridView; 12 | 13 | import com.sys.blackcat.stickheaderlayout.demo.DemoUtils; 14 | 15 | /** 16 | * Created by Administrator on 2016/6/9. 17 | */ 18 | public class GridViewFragment extends Fragment { 19 | @Nullable 20 | @Override 21 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 22 | GridView mGridView = new GridView(getActivity()); 23 | mGridView.setNumColumns(4); 24 | mGridView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT)); 25 | mGridView.setAdapter(new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, DemoUtils.getData())); 26 | return mGridView; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/fragment/ListViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.AbsListView; 10 | import android.widget.ArrayAdapter; 11 | import android.widget.ListView; 12 | 13 | import com.sys.blackcat.stickheaderlayout.demo.DemoUtils; 14 | 15 | /** 16 | * Created by Administrator on 2016/6/9. 17 | */ 18 | public class ListViewFragment extends Fragment { 19 | @Nullable 20 | @Override 21 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 22 | ListView mListView = new ListView(getActivity()); 23 | mListView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT)); 24 | mListView.setAdapter(new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, DemoUtils.getData())); 25 | return mListView; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/fragment/RecyclerViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.sys.blackcat.stickheaderlayout.demo.DemoUtils; 13 | import com.sys.blackcat.stickheaderlayout.demo.R; 14 | import com.sys.blackcat.stickheaderlayout.demo.adapter.MyAdapter; 15 | 16 | /** 17 | * Created by Administrator on 2016/6/9. 18 | */ 19 | public class RecyclerViewFragment extends Fragment { 20 | private RecyclerView recyclerView; 21 | 22 | @Nullable 23 | @Override 24 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 25 | return inflater.inflate(R.layout.recycler_view_fragment, null); 26 | } 27 | 28 | @Override 29 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 30 | super.onActivityCreated(savedInstanceState); 31 | recyclerView = (RecyclerView) getView(); 32 | MyAdapter myAdapter = new MyAdapter(); 33 | myAdapter.addAll(DemoUtils.getData()); 34 | // LinearLayoutManager manager = new LinearLayoutManager(this); 35 | // manager.setOrientation(LinearLayoutManager.VERTICAL); 36 | // GridLayoutManager manager = new GridLayoutManager(this,3); 37 | StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); 38 | recyclerView.setLayoutManager(manager); 39 | recyclerView.setAdapter(myAdapter); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/sys/blackcat/stickheaderlayout/demo/fragment/ScrollViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.sys.blackcat.stickheaderlayout.demo.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.sys.blackcat.stickheaderlayout.demo.R; 11 | 12 | /** 13 | * Created by Administrator on 2016/6/9. 14 | */ 15 | public class ScrollViewFragment extends Fragment { 16 | @Nullable 17 | @Override 18 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 19 | return inflater.inflate(R.layout.scroll_view_fragment, null); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_grid_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 22 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_list_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 22 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |