├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zcolin │ │ └── recyclerdemo │ │ ├── App.java │ │ ├── DecorationActivity.java │ │ ├── GridLayoutActivity.java │ │ ├── MainActivity.java │ │ ├── MultiTypeLayoutActivity.java │ │ ├── RelativeLayoutActivity.java │ │ ├── ScrollViewLayoutActivity.java │ │ ├── StaggeredGridLayoutActivity.java │ │ ├── SwipeMenuLayoutActivity.java │ │ ├── TextViewActivity.java │ │ ├── WebViewActivity.java │ │ └── adapter │ │ ├── MultiTypeAdapter.java │ │ ├── RecyclerAdapter.java │ │ └── SwipeMenuRecyclerAdapter.java │ └── res │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_main.xml │ ├── activity_relativelayout.xml │ ├── activity_scrollview.xml │ ├── activity_swipemenu.xml │ ├── activity_textview.xml │ ├── activity_webview.xml │ ├── item_swipemenu_content.xml │ ├── item_swipemenu_menu.xml │ ├── view_recycler_empty.xml │ ├── view_recycler_item.xml │ ├── view_recycler_item_1.xml │ ├── view_recycler_item_2.xml │ ├── view_recyclerfooter.xml │ ├── view_recyclerheader.xml │ └── view_swipemenu.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libPullRecyclerView ├── .gitignore ├── build.gradle ├── javadoc.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zcolin │ │ └── gui │ │ └── pullrecyclerview │ │ ├── AppBarStateChangeListener.java │ │ ├── BaseRecyclerAdapter.java │ │ ├── CommonHolder.java │ │ ├── PullRecyclerView.java │ │ ├── PullScrollView.java │ │ ├── PullSwipeMenuRecyclerView.java │ │ ├── RecycleViewDivider.java │ │ ├── WrapperRecyclerAdapter.java │ │ ├── hfooter │ │ ├── DefLoadMoreFooter.java │ │ ├── DefRefreshHeader.java │ │ ├── ILoadMoreFooter.java │ │ └── IRefreshHeader.java │ │ ├── progressindicator │ │ ├── AVLoadingIndicatorView.java │ │ ├── ProgressStyle.java │ │ ├── SimpleViewSwitcher.java │ │ └── indicators │ │ │ ├── BallBeatIndicator.java │ │ │ ├── BallClipRotateIndicator.java │ │ │ ├── BallClipRotateMultipleIndicator.java │ │ │ ├── BallClipRotatePulseIndicator.java │ │ │ ├── BallGridBeatIndicator.java │ │ │ ├── BallGridPulseIndicator.java │ │ │ ├── BallPulseIndicator.java │ │ │ ├── BallPulseRiseIndicator.java │ │ │ ├── BallPulseSyncIndicator.java │ │ │ ├── BallRotateIndicator.java │ │ │ ├── BallScaleIndicator.java │ │ │ ├── BallScaleMultipleIndicator.java │ │ │ ├── BallScaleRippleIndicator.java │ │ │ ├── BallScaleRippleMultipleIndicator.java │ │ │ ├── BallSpinFadeLoaderIndicator.java │ │ │ ├── BallTrianglePathIndicator.java │ │ │ ├── BallZigZagDeflectIndicator.java │ │ │ ├── BallZigZagIndicator.java │ │ │ ├── CubeTransitionIndicator.java │ │ │ ├── Indicator.java │ │ │ ├── LineScaleIndicator.java │ │ │ ├── LineScalePartyIndicator.java │ │ │ ├── LineScalePulseOutIndicator.java │ │ │ ├── LineScalePulseOutRapidIndicator.java │ │ │ ├── LineSpinFadeLoaderIndicator.java │ │ │ ├── PacmanIndicator.java │ │ │ ├── SemiCircleSpinIndicator.java │ │ │ ├── SquareSpinIndicator.java │ │ │ └── TriangleSkewSpinIndicator.java │ │ └── swipemenu │ │ └── SwipeMenuLayout.java │ └── res │ ├── drawable-xhdpi │ ├── gui_ic_pullrecyclerview_loading_rotate.png │ └── gui_ic_pullrecyclerview_pulltorefresh_arrow.png │ ├── layout │ ├── gui_pullrecyclerview_footer.xml │ └── gui_pullrecyclerview_header.xml │ └── values │ ├── gui_zrecycler_view_attrs.xml │ ├── gui_zrecycler_view_ids.xml │ └── gui_zrecycler_view_style.xml ├── screenshot ├── 1.gif └── 2.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea/ 4 | /local.properties 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PullRecyclerViewLib 2 | = 3 | ### RecyclerView的下拉刷新到底加载的库,基于[SuperRecycleView](https://github.com/supercwn/SuperRecycleView)修改,
加载效果使用[AVLoadingIndicatorView](https://github.com/81813780/AVLoadingIndicatorView),特此感谢。 4 | #### 但就我个人而言,更喜欢谷歌的下拉小圆圈,所以我一般使用[ZRecyclerView](https://github.com/zcolin/ZRecyclerView)。ZRecyclerView的接口和PullRecyclerView的接口基本完全一样,可以无缝切换。 5 | 6 | 7 | 8 | Feature 9 | = 10 | 1. 制定自定义样式加载Footer请实现ILoadMoreFooter,参照DefLoadMoreFooter. 11 | 2. 制定自定义样式下拉Header请实现IRefreshHeader,参照DefRefreshHeader. 12 | 3. 可以设置HeaderView、FooterView、emptypView、下拉样式、加载样式等操作. 13 | 4. 所有设置在PullRecyclerView中操作,不再在Adapter中进行操作. 14 | 5. 支持滑动菜单. 15 | 16 | Demo 17 | = 18 | ![](screenshot/1.gif) 19 | ![](screenshot/2.gif) 20 | 21 | 22 | ## Gradle 23 | app的build.gradle中添加 24 | ``` 25 | dependencies { 26 | implementation 'androidx.cardview:cardview:1.0.0' 27 | implementation 'androidx.appcompat:appcompat:1.0.2' 28 | implementation 'com.google.android.material:material:1.0.0' 29 | implementation 'androidx.recyclerview:recyclerview:1.0.0' 30 | implementation 'com.github.zcolin:PullRecyclerView:latest.release' 31 | } 32 | ``` 33 | 工程的build.gradle中添加 34 | ``` 35 | allprojects { 36 | repositories { 37 | ... 38 | maven { url 'https://jitpack.io' } 39 | } 40 | } 41 | ``` 42 | 43 | usage 44 | = 45 | 46 | ``` 47 | //默认已设置LinearLayoutManager 48 | recyclerView.setLinearLayout(false); 49 | 50 | //设置刷新和加载更多回调 51 | recyclerView.setOnPullLoadMoreListener(new PullRecyclerView.PullLoadMoreListener() { 52 | @Override 53 | public void onRefresh() { 54 | 55 | } 56 | 57 | @Override 58 | public void onLoadMore() { 59 | 60 | } 61 | }); 62 | 63 | //设置数据为空时的EmptyView,DataObserver是注册在adapter之上的,也就是setAdapter是注册上,notifyDataSetChanged的时候才会生效 64 | recyclerView.setEmptyView(this, R.layout.view_recycler_empty); 65 | 66 | //设置HeaderView和footerView 67 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 68 | recyclerView.addFooterView(this, R.layout.view_recyclerfooter); 69 | // recyclerView.removeHeaderView(View) 70 | 71 | //设置下拉刷新进度条样式 72 | recyclerView.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 73 | 74 | //设置加载更多进度条样式 75 | recyclerView.setLoadMoreProgressStyle(ProgressStyle.LineScaleIndicator); 76 | 77 | //设置Item监听 78 | recyclerView.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() { 79 | @Override 80 | public void onItemClick(View covertView, int position, String data) { 81 | Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT) 82 | .show(); 83 | } 84 | }); 85 | 86 | //所有数据加载完毕后,不显示已加载全部 87 | recyclerView.setIsShowNoMore(false); 88 | 89 | //到底加载是否可用 90 | recyclerView.setIsLoadMoreEnabled(false); 91 | 92 | //下拉刷新是否可用 93 | recyclerView.setIsRefreshEnabled(false); 94 | 95 | //设置下拉刷新显示的文字 96 | recyclerView.setRefreshHeaderText("下拉刷新", "释放立即刷新", "正在刷新", "刷新完成"); 97 | 98 | //有下拉刷新效果,手动调用刷新数据 99 | recyclerView.refreshWithPull(); 100 | 101 | //没有下拉刷新效果,直接刷新数据 102 | recyclerView.refresh(); 103 | 104 | //只有下拉刷新效果,不刷新数据 105 | recyclerView.setRefreshing(true); 106 | ``` 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | buildToolsVersion rootProject.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | applicationId "com.zcolin.recyclerdemo" 9 | minSdkVersion rootProject.ext.minSdkVersion 10 | targetSdkVersion rootProject.ext.targetSdkVersion 11 | versionCode rootProject.ext.versionCode 12 | versionName rootProject.ext.versionName 13 | } 14 | 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: 'libs', include: ['*.jar']) 30 | implementation project(path: ':libPullRecyclerView') 31 | implementation 'androidx.cardview:cardview:1.0.0' 32 | implementation 'androidx.appcompat:appcompat:1.0.2' 33 | implementation 'com.google.android.material:material:1.0.0' 34 | implementation 'androidx.recyclerview:recyclerview:1.0.0' 35 | } 36 | -------------------------------------------------------------------------------- /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 D:\as_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 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.app.Application; 13 | 14 | public class App extends Application { 15 | 16 | @Override 17 | public void onCreate() { 18 | super.onCreate(); 19 | Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> ex.printStackTrace()); 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/DecorationActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | 15 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 16 | import com.zcolin.recyclerdemo.adapter.RecyclerAdapter; 17 | 18 | import java.util.ArrayList; 19 | 20 | import androidx.appcompat.app.AppCompatActivity; 21 | 22 | public class DecorationActivity extends AppCompatActivity { 23 | 24 | private PullRecyclerView recyclerView; 25 | private RecyclerAdapter recyclerAdapter; 26 | private int mPage = 1; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_main); 32 | 33 | recyclerView = findViewById(R.id.recycler_view); 34 | recyclerView.addDefaultItemDecoration(); 35 | //设置HeaderView和footerView 36 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 37 | recyclerView.addFooterView(this, R.layout.view_recyclerfooter); 38 | 39 | recyclerView.setIsShowNoMore(false); 40 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 41 | notifyData(new ArrayList<>(), false); 42 | recyclerView.refreshWithPull(); //有下拉效果的数据刷新 43 | } 44 | 45 | /** 46 | * 设置数据Adapter 47 | */ 48 | public void notifyData(ArrayList list, boolean isClear) { 49 | if (recyclerAdapter == null) { 50 | recyclerAdapter = new RecyclerAdapter(RecyclerAdapter.TYPE_LISTVIEW); 51 | recyclerAdapter.addDatas(list); 52 | recyclerView.setAdapter(recyclerAdapter); 53 | } else { 54 | if (isClear) { 55 | recyclerAdapter.setDatas(list); 56 | } else { 57 | recyclerAdapter.addDatas(list); 58 | } 59 | recyclerAdapter.notifyDataSetChanged(); 60 | } 61 | } 62 | 63 | /** 64 | * 模仿从网络请求数据 65 | */ 66 | public void requestData(final int page) { 67 | new Handler().postDelayed(() -> { 68 | notifyData(setList(page), page == 1); 69 | recyclerView.setPullLoadMoreCompleted(); 70 | if (page == 2) { 71 | recyclerView.setNoMore(true); 72 | } 73 | }, 1000); 74 | } 75 | 76 | //制造假数据 77 | private ArrayList setList(int page) { 78 | ArrayList dataList = new ArrayList<>(); 79 | int start = 15 * (page - 1); 80 | for (int i = start; i < 15 * page; i++) { 81 | if (i == 0) { 82 | dataList.add("WebView"); 83 | } else if (i == 1) { 84 | dataList.add("ScrollView"); 85 | } else if (i == 2) { 86 | dataList.add("TextView"); 87 | } else if (i == 3) { 88 | dataList.add("RelativeLayout"); 89 | } else if (i == 4) { 90 | dataList.add("GridLayout"); 91 | } else if (i == 5) { 92 | dataList.add("StaggeredGridLayout"); 93 | } else { 94 | dataList.add(String.format("第%d条数据", i)); 95 | } 96 | } 97 | return dataList; 98 | } 99 | 100 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 101 | @Override 102 | public void onRefresh() { 103 | mPage = 1; 104 | requestData(mPage); 105 | recyclerView.setNoMore(false); 106 | } 107 | 108 | @Override 109 | public void onLoadMore() { 110 | mPage = mPage + 1; 111 | requestData(mPage); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/GridLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import android.widget.Toast; 16 | 17 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 18 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 19 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 20 | import com.zcolin.recyclerdemo.adapter.RecyclerAdapter; 21 | 22 | import java.util.ArrayList; 23 | 24 | public class GridLayoutActivity extends AppCompatActivity { 25 | 26 | private PullRecyclerView recyclerView; 27 | private RecyclerAdapter recyclerAdapter; 28 | private int mPage = 1; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_main); 34 | 35 | recyclerView = findViewById(R.id.recycler_view); 36 | recyclerView.setGridLayout(false, 2);//默认为LinearLayoutManager 37 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 38 | 39 | //设置数据为空时的EmptyView,DataObserver是注册在adapter之上的,也就是setAdapter是注册上,notifyDataSetChanged的时候才会生效 40 | recyclerView.setEmptyView(this, R.layout.view_recycler_empty); 41 | 42 | //设置HeaderView和footerView 43 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 44 | recyclerView.addFooterView(this, R.layout.view_recyclerfooter); 45 | 46 | //下拉和到底加载的进度条样式,默认为 ProgressStyle.BallSpinFadeLoaderIndicator 47 | recyclerView.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 48 | recyclerView.setLoadMoreProgressStyle(ProgressStyle.LineScaleIndicator); 49 | 50 | recyclerView.setOnItemClickListener((BaseRecyclerAdapter.OnItemClickListener) (covertView, position, 51 | data) -> Toast 52 | .makeText(GridLayoutActivity.this, data, Toast.LENGTH_SHORT) 53 | .show()); 54 | 55 | //recyclerView.setIsShowNoMore(false); //不显示已加载全部 56 | //recyclerView.setIsLoadMoreEnabled(false);//到底加载是否可用 57 | //recyclerView.setIsRefreshEnabled(false); //下拉刷新是否可用 58 | notifyData(new ArrayList<>(), false);//绑定Adapter 59 | 60 | recyclerView.refreshWithPull(); //有下拉效果的数据刷新 61 | // recyclerView.refresh(); //没有下拉刷新效果,直接刷新数据 62 | // recyclerView.setRefreshing(true);//只有下拉刷新效果,不刷新数据 63 | } 64 | 65 | /** 66 | * 设置数据Adapter 67 | */ 68 | public void notifyData(ArrayList list, boolean isClear) { 69 | if (recyclerAdapter == null) { 70 | recyclerAdapter = new RecyclerAdapter(); 71 | recyclerAdapter.addDatas(list); 72 | recyclerView.setAdapter(recyclerAdapter); 73 | } else { 74 | if (isClear) { 75 | recyclerAdapter.setDatas(list); 76 | } else { 77 | recyclerAdapter.addDatas(list); 78 | } 79 | recyclerAdapter.notifyDataSetChanged(); 80 | } 81 | } 82 | 83 | /** 84 | * 模仿从网络请求数据 85 | */ 86 | public void requestData(final int page) { 87 | new Handler().postDelayed(() -> { 88 | notifyData(setList(page), page == 1); 89 | recyclerView.setPullLoadMoreCompleted(); 90 | if (page == 2) { 91 | recyclerView.setNoMore(true); 92 | } 93 | }, 1000); 94 | } 95 | 96 | //制造假数据 97 | private ArrayList setList(int page) { 98 | ArrayList dataList = new ArrayList<>(); 99 | int start = 15 * (page - 1); 100 | for (int i = start; i < 15 * page; i++) { 101 | dataList.add(String.format("第%d条数据", i)); 102 | } 103 | return dataList; 104 | } 105 | 106 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 107 | @Override 108 | public void onRefresh() { 109 | mPage = 1; 110 | requestData(mPage); 111 | recyclerView.setNoMore(false); 112 | } 113 | 114 | @Override 115 | public void onLoadMore() { 116 | mPage = mPage + 1; 117 | requestData(mPage); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.content.Intent; 13 | import android.os.Bundle; 14 | import android.os.Handler; 15 | import androidx.appcompat.app.AppCompatActivity; 16 | import android.view.LayoutInflater; 17 | import android.view.View; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 22 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 23 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 24 | import com.zcolin.recyclerdemo.adapter.RecyclerAdapter; 25 | 26 | import java.util.ArrayList; 27 | 28 | public class MainActivity extends AppCompatActivity { 29 | 30 | private PullRecyclerView recyclerView; 31 | private RecyclerAdapter recyclerAdapter; 32 | private View headerView2; 33 | private int mPage = 1; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_main); 39 | 40 | recyclerView = findViewById(R.id.recycler_view); 41 | 42 | // recyclerView.setGridLayout(false);//默认为LinearLayoutManager 43 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 44 | 45 | //设置数据为空时的EmptyView,DataObserver是注册在adapter之上的,也就是setAdapter是注册上,notifyDataSetChanged的时候才会生效 46 | recyclerView.setEmptyView(this, R.layout.view_recycler_empty); 47 | 48 | //设置HeaderView和footerView 49 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 50 | headerView2 = LayoutInflater.from(this).inflate(R.layout.view_recyclerheader, null); 51 | ((TextView) headerView2.findViewById(R.id.textView)).setText("HEDER 2"); 52 | recyclerView.addHeaderView(headerView2); 53 | recyclerView.addFooterView(this, R.layout.view_recyclerfooter); 54 | 55 | //下拉和到底加载的进度条样式,默认为 ProgressStyle.BallSpinFadeLoaderIndicator 56 | recyclerView.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 57 | recyclerView.setLoadMoreProgressStyle(ProgressStyle.LineScaleIndicator); 58 | 59 | recyclerView.setOnItemClickListener((BaseRecyclerAdapter.OnItemClickListener) (covertView, position, 60 | data) -> { 61 | Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); 62 | if (position == 0) { 63 | Intent intent = new Intent(MainActivity.this, WebViewActivity.class); 64 | startActivity(intent); 65 | } else if (position == 1) { 66 | Intent intent = new Intent(MainActivity.this, ScrollViewLayoutActivity.class); 67 | startActivity(intent); 68 | } else if (position == 2) { 69 | Intent intent = new Intent(MainActivity.this, TextViewActivity.class); 70 | startActivity(intent); 71 | } else if (position == 3) { 72 | Intent intent = new Intent(MainActivity.this, RelativeLayoutActivity.class); 73 | startActivity(intent); 74 | } else if (position == 4) { 75 | Intent intent = new Intent(MainActivity.this, GridLayoutActivity.class); 76 | startActivity(intent); 77 | } else if (position == 5) { 78 | Intent intent = new Intent(MainActivity.this, StaggeredGridLayoutActivity.class); 79 | startActivity(intent); 80 | } else if (position == 6) { 81 | Intent intent = new Intent(MainActivity.this, MultiTypeLayoutActivity.class); 82 | startActivity(intent); 83 | } else if (position == 7) { 84 | Intent intent = new Intent(MainActivity.this, DecorationActivity.class); 85 | startActivity(intent); 86 | } else if (position == 8) { 87 | Intent intent = new Intent(MainActivity.this, SwipeMenuLayoutActivity.class); 88 | startActivity(intent); 89 | } else if (position == 9) { 90 | recyclerView.removeHeaderView(headerView2); 91 | } 92 | }); 93 | recyclerView.setOnItemLongClickListener((BaseRecyclerAdapter.OnItemLongClickListener) (covertView, 94 | position, data) -> { 95 | recyclerAdapter.getDatas().remove(position); 96 | recyclerAdapter.notifyItemRemoved(position); 97 | recyclerAdapter.notifyItemRangeChanged(position, recyclerAdapter.getDatas().size() - position); 98 | return true; 99 | }); 100 | 101 | 102 | // recyclerView.setIsShowNoMore(false);//不显示《已加载全部》 103 | // recyclerView.setIsLoadMoreEnabled(false);//到底加载是否可用 104 | // recyclerView.setIsRefreshEnabled(false);//下拉刷新是否可用 105 | 106 | //下拉刷新的文字显示 107 | recyclerView.setRefreshHeaderText("下拉刷新", "释放立即刷新", "正在刷新", "刷新完成"); 108 | 109 | //绑定Adapter 110 | notifyData(new ArrayList<>(), false); 111 | 112 | recyclerView.refreshWithPull(); //有下拉效果的数据刷新 113 | // recyclerView.refresh(); //没有下拉刷新效果,直接刷新数据 114 | // recyclerView.setRefreshing(true);//只有下拉刷新效果,不刷新数据 115 | } 116 | 117 | /** 118 | * 设置数据Adapter 119 | */ 120 | public void notifyData(ArrayList list, boolean isClear) { 121 | if (recyclerAdapter == null) { 122 | recyclerAdapter = new RecyclerAdapter(); 123 | recyclerAdapter.addDatas(list); 124 | recyclerView.setAdapter(recyclerAdapter); 125 | } else { 126 | if (isClear) { 127 | recyclerAdapter.setDatas(list); 128 | } else { 129 | recyclerAdapter.addDatas(list); 130 | } 131 | recyclerAdapter.notifyDataSetChanged(); 132 | } 133 | } 134 | 135 | /** 136 | * 模仿从网络请求数据 137 | */ 138 | public void requestData(final int page) { 139 | new Handler().postDelayed(() -> { 140 | notifyData(setList(page), page == 1); 141 | recyclerView.setPullLoadMoreCompleted(); 142 | if (page == 2) { 143 | recyclerView.setNoMore(true); 144 | } 145 | }, 1000); 146 | } 147 | 148 | //制造假数据 149 | private ArrayList setList(int page) { 150 | ArrayList dataList = new ArrayList<>(); 151 | int start = 15 * (page - 1); 152 | for (int i = start; i < 15 * page; i++) { 153 | if (i == 0) { 154 | dataList.add("WebView"); 155 | } else if (i == 1) { 156 | dataList.add("ScrollView"); 157 | } else if (i == 2) { 158 | dataList.add("TextView"); 159 | } else if (i == 3) { 160 | dataList.add("RelativeLayout"); 161 | } else if (i == 4) { 162 | dataList.add("GridLayout"); 163 | } else if (i == 5) { 164 | dataList.add("StaggeredGridLayout"); 165 | } else if (i == 6) { 166 | dataList.add("MultiTypeLayout"); 167 | } else if (i == 7) { 168 | dataList.add("Decoration"); 169 | } else if (i == 8) { 170 | dataList.add("SwipeMenuLayout"); 171 | } else if (i == 9) { 172 | dataList.add("移除Header2"); 173 | } else { 174 | dataList.add(String.format("第%d条数据", i)); 175 | } 176 | } 177 | return dataList; 178 | } 179 | 180 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 181 | @Override 182 | public void onRefresh() { 183 | mPage = 1; 184 | requestData(mPage); 185 | recyclerView.setNoMore(false); 186 | } 187 | 188 | @Override 189 | public void onLoadMore() { 190 | mPage = mPage + 1; 191 | requestData(mPage); 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/MultiTypeLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import android.widget.Toast; 16 | 17 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 18 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 19 | import com.zcolin.recyclerdemo.adapter.MultiTypeAdapter; 20 | 21 | import java.util.ArrayList; 22 | 23 | public class MultiTypeLayoutActivity extends AppCompatActivity { 24 | 25 | private PullRecyclerView recyclerView; 26 | private MultiTypeAdapter recyclerAdapter; 27 | private int mPage = 1; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_main); 33 | 34 | recyclerView = findViewById(R.id.recycler_view); 35 | recyclerView.setGridLayout(false, 3);//默认已设置LinearLayoutManager 36 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 37 | recyclerView.setEmptyView(this, R.layout.view_recycler_empty); 38 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 39 | 40 | recyclerView.setOnItemClickListener((BaseRecyclerAdapter.OnItemClickListener) (covertView, position, 41 | data) -> Toast 42 | .makeText(MultiTypeLayoutActivity.this, data, Toast.LENGTH_SHORT) 43 | .show()); 44 | 45 | notifyData(new ArrayList<>(), false); 46 | recyclerView.refreshWithPull(); 47 | } 48 | 49 | /** 50 | * 设置数据Adapter 51 | */ 52 | public void notifyData(ArrayList list, boolean isClear) { 53 | if (recyclerAdapter == null) { 54 | recyclerAdapter = new MultiTypeAdapter(); 55 | recyclerAdapter.addDatas(list); 56 | recyclerView.setAdapter(recyclerAdapter); 57 | } else { 58 | if (isClear) { 59 | recyclerAdapter.setDatas(list); 60 | } else { 61 | recyclerAdapter.addDatas(list); 62 | } 63 | recyclerAdapter.notifyDataSetChanged(); 64 | } 65 | } 66 | 67 | /** 68 | * 模仿从网络请求数据 69 | */ 70 | public void requestData(final int page) { 71 | new Handler().postDelayed(() -> { 72 | notifyData(setList(page), page == 1); 73 | recyclerView.setPullLoadMoreCompleted(); 74 | if (page == 2) { 75 | recyclerView.setNoMore(true); 76 | } 77 | }, 1000); 78 | } 79 | 80 | //制造假数据 81 | private ArrayList setList(int page) { 82 | ArrayList dataList = new ArrayList<>(); 83 | int start = 15 * (page - 1); 84 | for (int i = start; i < 15 * page; i++) { 85 | dataList.add(String.format("第%d条数据", i)); 86 | } 87 | return dataList; 88 | } 89 | 90 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 91 | @Override 92 | public void onRefresh() { 93 | mPage = 1; 94 | requestData(mPage); 95 | recyclerView.setNoMore(false); 96 | } 97 | 98 | @Override 99 | public void onLoadMore() { 100 | mPage = mPage + 1; 101 | requestData(mPage); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/RelativeLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | 16 | import com.zcolin.gui.pullrecyclerview.PullScrollView; 17 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 18 | 19 | public class RelativeLayoutActivity extends AppCompatActivity { 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_relativelayout); 25 | 26 | final PullScrollView refreshLayout = findViewById(R.id.refresh_layout); 27 | // refreshLayout.setIsRefreshEnabled(false); //下拉刷新是否可用 28 | // refreshLayout.setRefreshHeader(new DefRefreshHeader(this)); //设置默认或者自定义的刷新Header 29 | // refreshLayout.getRefreshHeaderView().setBackgroundColor(Color.BLUE);//加载Header的背景颜色 30 | refreshLayout.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 31 | refreshLayout.setRefreshListener(() -> new Handler().postDelayed(() -> refreshLayout.setRefreshCompleted(), 32 | 1000)); 33 | 34 | refreshLayout.refreshWithPull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/ScrollViewLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | 16 | import com.zcolin.gui.pullrecyclerview.PullScrollView; 17 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 18 | 19 | public class ScrollViewLayoutActivity extends AppCompatActivity { 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_scrollview); 25 | 26 | final PullScrollView refreshLayout = findViewById(R.id.refresh_layout); 27 | // refreshLayout.setIsRefreshEnabled(false); //下拉刷新是否可用 28 | // refreshLayout.setRefreshHeader(new DefRefreshHeader(this)); //设置默认或者自定义的刷新Header 29 | // refreshLayout.getRefreshHeaderView().setBackgroundColor(Color.BLUE);//加载Header的背景颜色 30 | refreshLayout.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 31 | refreshLayout.setRefreshListener(() -> new Handler().postDelayed(() -> refreshLayout.setRefreshCompleted(), 32 | 1000)); 33 | 34 | refreshLayout.refreshWithPull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/StaggeredGridLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import android.widget.Toast; 16 | 17 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 18 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 19 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 20 | import com.zcolin.recyclerdemo.adapter.RecyclerAdapter; 21 | 22 | import java.util.ArrayList; 23 | 24 | public class StaggeredGridLayoutActivity extends AppCompatActivity { 25 | 26 | private PullRecyclerView recyclerView; 27 | private RecyclerAdapter recyclerAdapter; 28 | private int mPage = 1; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_main); 34 | 35 | recyclerView = findViewById(R.id.recycler_view); 36 | 37 | recyclerView.setStaggeredGridLayout(false, 2); //默认为LinearLayoutManager 38 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 39 | 40 | //设置数据为空时的EmptyView,DataObserver是注册在adapter之上的,也就是setAdapter是注册上,notifyDataSetChanged的时候才会生效 41 | recyclerView.setEmptyView(this, R.layout.view_recycler_empty); 42 | 43 | //设置HeaderView和footerView 44 | recyclerView.addHeaderView(this, R.layout.view_recyclerheader); 45 | recyclerView.addFooterView(this, R.layout.view_recyclerfooter); 46 | 47 | //下拉和到底加载的进度条样式,默认为 ProgressStyle.BallSpinFadeLoaderIndicator 48 | recyclerView.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 49 | recyclerView.setLoadMoreProgressStyle(ProgressStyle.LineScaleIndicator); 50 | 51 | recyclerView.setOnItemClickListener((BaseRecyclerAdapter.OnItemClickListener) (covertView, position, 52 | data) -> Toast 53 | .makeText(StaggeredGridLayoutActivity.this, data, Toast.LENGTH_SHORT) 54 | .show()); 55 | 56 | // recyclerView.setIsShowNoMore(false); //不显示已加载全部 57 | // recyclerView.setIsLoadMoreEnabled(false);//到底加载是否可用 58 | // recyclerView.setIsRefreshEnabled(false); //下拉刷新是否可用 59 | notifyData(new ArrayList<>(), false); 60 | 61 | recyclerView.refreshWithPull(); //有下拉效果的数据刷新 62 | // recyclerView.refresh(); //没有下拉刷新效果,直接刷新数据 63 | // recyclerView.setRefreshing(true);//只有下拉刷新效果,不刷新数据 64 | } 65 | 66 | /** 67 | * 设置数据Adapter 68 | */ 69 | public void notifyData(ArrayList list, boolean isClear) { 70 | if (recyclerAdapter == null) { 71 | recyclerAdapter = new RecyclerAdapter(); 72 | recyclerAdapter.addDatas(list); 73 | recyclerView.setAdapter(recyclerAdapter); 74 | } else { 75 | if (isClear) { 76 | recyclerAdapter.setDatas(list); 77 | } else { 78 | recyclerAdapter.addDatas(list); 79 | } 80 | recyclerAdapter.notifyDataSetChanged(); 81 | } 82 | } 83 | 84 | /** 85 | * 模仿从网络请求数据 86 | */ 87 | public void requestData(final int page) { 88 | new Handler().postDelayed(() -> { 89 | notifyData(setList(page), page == 1); 90 | recyclerView.setPullLoadMoreCompleted(); 91 | if (page == 2) { 92 | recyclerView.setNoMore(true); 93 | } 94 | }, 1000); 95 | } 96 | 97 | //制造假数据 98 | private ArrayList setList(int page) { 99 | ArrayList dataList = new ArrayList<>(); 100 | int start = 15 * (page - 1); 101 | for (int i = start; i < 15 * page; i++) { 102 | dataList.add(String.format("第%d条数据", i)); 103 | } 104 | return dataList; 105 | } 106 | 107 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 108 | @Override 109 | public void onRefresh() { 110 | mPage = 1; 111 | requestData(mPage); 112 | recyclerView.setNoMore(false); 113 | } 114 | 115 | @Override 116 | public void onLoadMore() { 117 | mPage = mPage + 1; 118 | requestData(mPage); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/SwipeMenuLayoutActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.graphics.Color; 13 | import android.os.Bundle; 14 | import android.os.Handler; 15 | import androidx.appcompat.app.AppCompatActivity; 16 | import android.widget.LinearLayout; 17 | import android.widget.Toast; 18 | 19 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 20 | import com.zcolin.gui.pullrecyclerview.PullRecyclerView; 21 | import com.zcolin.gui.pullrecyclerview.PullSwipeMenuRecyclerView; 22 | import com.zcolin.gui.pullrecyclerview.RecycleViewDivider; 23 | import com.zcolin.recyclerdemo.adapter.SwipeMenuRecyclerAdapter; 24 | 25 | import java.util.ArrayList; 26 | 27 | public class SwipeMenuLayoutActivity extends AppCompatActivity { 28 | 29 | private PullSwipeMenuRecyclerView recyclerView; 30 | private SwipeMenuRecyclerAdapter recyclerAdapter; 31 | private int mPage = 1; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_swipemenu); 37 | 38 | recyclerView = findViewById(R.id.recycler_view); 39 | recyclerView.setOnPullLoadMoreListener(new PullLoadMoreListener()); 40 | recyclerView.addItemDecoration(new RecycleViewDivider(this, LinearLayout.HORIZONTAL, 1, Color.GREEN)); 41 | recyclerView.getLoadMoreFooterView().setBackgroundColor(Color.BLUE); 42 | recyclerView.setOnItemClickListener((BaseRecyclerAdapter.OnItemClickListener) (covertView, position, 43 | data) -> Toast 44 | .makeText(SwipeMenuLayoutActivity.this, data, Toast.LENGTH_SHORT) 45 | .show()); 46 | 47 | recyclerView.refreshWithPull(); 48 | } 49 | 50 | /** 51 | * 设置数据Adapter 52 | */ 53 | public void notifyData(ArrayList list, boolean isClear) { 54 | if (recyclerAdapter == null) { 55 | recyclerAdapter = new SwipeMenuRecyclerAdapter(); 56 | recyclerAdapter.addDatas(list); 57 | recyclerView.setAdapter(recyclerAdapter); 58 | } else { 59 | if (isClear) { 60 | recyclerAdapter.setDatas(list); 61 | } else { 62 | recyclerAdapter.addDatas(list); 63 | } 64 | recyclerAdapter.notifyDataSetChanged(); 65 | } 66 | } 67 | 68 | /** 69 | * 模仿从网络请求数据 70 | */ 71 | public void requestData(final int page) { 72 | new Handler().postDelayed(() -> { 73 | notifyData(setList(page), page == 1); 74 | recyclerView.setPullLoadMoreCompleted(); 75 | if (page == 2) { 76 | recyclerView.setNoMore(true); 77 | } 78 | }, 1000); 79 | } 80 | 81 | //制造假数据 82 | private ArrayList setList(int page) { 83 | ArrayList dataList = new ArrayList<>(); 84 | int start = 15 * (page - 1); 85 | for (int i = start; i < 15 * page; i++) { 86 | dataList.add(String.format("第%d条数据", i)); 87 | } 88 | return dataList; 89 | } 90 | 91 | class PullLoadMoreListener implements PullRecyclerView.PullLoadMoreListener { 92 | @Override 93 | public void onRefresh() { 94 | mPage = 1; 95 | requestData(mPage); 96 | recyclerView.setNoMore(false); 97 | } 98 | 99 | @Override 100 | public void onLoadMore() { 101 | mPage = mPage + 1; 102 | requestData(mPage); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/TextViewActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | 16 | import com.zcolin.gui.pullrecyclerview.PullScrollView; 17 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 18 | 19 | public class TextViewActivity extends AppCompatActivity { 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_textview); 25 | 26 | final PullScrollView refreshLayout = findViewById(R.id.refresh_layout); 27 | // refreshLayout.setIsRefreshEnabled(false); 28 | // refreshLayout.setRefreshHeader(new DefRefreshHeader(this)); 29 | // refreshLayout.getRefreshHeaderView().setBackgroundColor(Color.BLUE); 30 | refreshLayout.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 31 | refreshLayout.setRefreshListener(() -> new Handler().postDelayed(() -> refreshLayout.setRefreshCompleted(), 32 | 1000)); 33 | 34 | refreshLayout.refreshWithPull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo; 11 | 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import android.webkit.WebChromeClient; 16 | import android.webkit.WebView; 17 | import android.webkit.WebViewClient; 18 | 19 | import com.zcolin.gui.pullrecyclerview.PullScrollView; 20 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 21 | 22 | public class WebViewActivity extends AppCompatActivity { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_webview); 28 | 29 | 30 | final PullScrollView refreshLayout = findViewById(R.id.refresh_layout); 31 | final WebView webView = findViewById(R.id.webview); 32 | webView.getSettings().setJavaScriptEnabled(true); 33 | webView.setWebChromeClient(new WebChromeClient()); 34 | webView.setWebViewClient(new WebViewClient()); 35 | // refreshLayout.setIsRefreshEnabled(false); 36 | // refreshLayout.setRefreshHeader(new DefRefreshHeader(this)); 37 | // refreshLayout.getRefreshHeaderView().setBackgroundColor(Color.BLUE); 38 | refreshLayout.setRefreshProgressStyle(ProgressStyle.LineScaleIndicator); 39 | refreshLayout.setRefreshListener(() -> new Handler().postDelayed(() -> { 40 | webView.loadUrl("http://www.sina.com.cn/"); 41 | refreshLayout.setRefreshCompleted(); 42 | }, 1000)); 43 | 44 | refreshLayout.refreshWithPull(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/adapter/MultiTypeAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | package com.zcolin.recyclerdemo.adapter; 10 | 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | 14 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 15 | import com.zcolin.recyclerdemo.R; 16 | 17 | 18 | public class MultiTypeAdapter extends BaseRecyclerAdapter { 19 | 20 | public static final int TYPE_0 = 0; 21 | public static final int TYPE_1 = 1; 22 | public static final int TYPE_2 = 2; 23 | 24 | @Override 25 | public int getItemLayoutId(int viewType) { 26 | if (viewType == TYPE_0) { 27 | return R.layout.view_recycler_item; 28 | } else { 29 | return R.layout.view_recycler_item_2; 30 | } 31 | } 32 | 33 | @Override 34 | public int getItemViewType(int position) { 35 | if (position % 3 == 0) { 36 | return TYPE_2; 37 | } else if (position % 4 == 0) { 38 | return TYPE_0; 39 | } else { 40 | return TYPE_1; 41 | } 42 | } 43 | 44 | @Override 45 | public int getGridItemSpanCount(int position, int viewType) { 46 | if (viewType == TYPE_0) { 47 | return 0; 48 | } else if (viewType == TYPE_1) { 49 | return 2; 50 | } else { 51 | return 1; 52 | } 53 | } 54 | 55 | @Override 56 | public void setUpData(CommonHolder holder, int position, int viewType, String data) { 57 | TextView textView = getView(holder, R.id.textView); 58 | textView.setText(data); 59 | if (viewType == TYPE_0) { 60 | ImageView imageView = getView(holder, R.id.imageView); 61 | imageView.setImageResource(R.drawable.ic_launcher); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/adapter/RecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | package com.zcolin.recyclerdemo.adapter; 10 | 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | 14 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 15 | import com.zcolin.recyclerdemo.R; 16 | 17 | 18 | public class RecyclerAdapter extends BaseRecyclerAdapter { 19 | 20 | public static final int TYPE_CARDVIEW = 0; 21 | public static final int TYPE_LISTVIEW = 1; 22 | 23 | public int showType = TYPE_CARDVIEW; 24 | 25 | public RecyclerAdapter() { 26 | } 27 | 28 | public RecyclerAdapter(int showType) { 29 | this.showType = showType; 30 | } 31 | 32 | @Override 33 | public int getItemLayoutId(int viewType) { 34 | return showType == TYPE_CARDVIEW ? R.layout.view_recycler_item : R.layout.view_recycler_item_1; 35 | } 36 | 37 | @Override 38 | public void setUpData(CommonHolder holder, int position, int viewType, String data) { 39 | TextView textView = getView(holder, R.id.textView); 40 | ImageView imageView = getView(holder, R.id.imageView); 41 | imageView.setImageResource(R.drawable.ic_launcher); 42 | textView.setText(data); 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/recyclerdemo/adapter/SwipeMenuRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.recyclerdemo.adapter; 11 | 12 | 13 | import android.widget.ImageView; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.zcolin.gui.pullrecyclerview.BaseRecyclerAdapter; 18 | import com.zcolin.gui.pullrecyclerview.swipemenu.SwipeMenuLayout; 19 | import com.zcolin.recyclerdemo.R; 20 | 21 | 22 | public class SwipeMenuRecyclerAdapter extends BaseRecyclerAdapter { 23 | 24 | @Override 25 | public int getItemLayoutId(int viewType) { 26 | return R.layout.view_swipemenu; 27 | } 28 | 29 | @Override 30 | public void setUpData(CommonHolder holder, int position, int viewType, String data) { 31 | final SwipeMenuLayout superSwipeMenuLayout = (SwipeMenuLayout) holder.itemView; 32 | superSwipeMenuLayout.setSwipeEnable(true);//设置是否可以侧滑 33 | TextView tvOpen = getView(holder, R.id.btOpen); 34 | TextView tvDel = getView(holder, R.id.btDelete); 35 | ImageView iv = getView(holder, R.id.image_iv); 36 | TextView tvName = getView(holder, R.id.name_tv); 37 | 38 | tvName.setText(String.format("第%d条数据", position)); 39 | 40 | tvOpen.setOnClickListener(v -> Toast.makeText(superSwipeMenuLayout.getContext(), "Open", Toast.LENGTH_SHORT) 41 | .show()); 42 | tvDel.setOnClickListener(v -> Toast.makeText(superSwipeMenuLayout.getContext(), "Delete", Toast.LENGTH_SHORT) 43 | .show()); 44 | 45 | iv.setOnClickListener(v -> { 46 | if (superSwipeMenuLayout.isOpen()) { 47 | superSwipeMenuLayout.closeMenu(); 48 | } else { 49 | superSwipeMenuLayout.openMenu(); 50 | } 51 | }); 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_relativelayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 16 | 17 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_scrollview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 19 | 20 | 26 | 27 | 33 | 34 | 40 | 41 | 47 | 48 | 54 | 55 | 61 | 62 | 68 | 69 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_swipemenu.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_textview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_swipemenu_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 25 | 26 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_swipemenu_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 27 | 28 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recycler_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recycler_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 24 | 25 | 29 | 30 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recycler_item_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 20 | 21 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recycler_item_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 24 | 25 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recyclerfooter.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_recyclerheader.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_swipemenu.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 19 | 20 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 14 | 64dp 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 16dp 13 | 16dp 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | PullRecyclerViewLib 12 | 13 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | 4 | //正常情况能连外网,且网络良好或者有vpn 5 | repositories { 6 | mavenCentral() 7 | google() 8 | jcenter() 9 | } 10 | 11 | //正常情况能连外网,但网络质量较差或者无vpn 12 | // repositories { 13 | // maven { url 'https://maven.aliyun.com/repository/google' } 14 | // maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } 15 | // maven { url 'https://maven.aliyun.com/repository/public' } 16 | // maven { url 'https://maven.aliyun.com/repository/jcenter' } 17 | // mavenLocal() 18 | // } 19 | 20 | //离线开发环境,使用内网搭建的nexus仓库 21 | // repositories { 22 | // maven { url 'http://192.168.1.3:8081/repository/android-proxy/' } 23 | // } 24 | 25 | dependencies { 26 | classpath 'com.android.tools.build:gradle:3.2.1' 27 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' 28 | 29 | // NOTE: Do not place your application dependencies here; they belong 30 | // in the individual module build.gradle files 31 | } 32 | } 33 | 34 | allprojects { 35 | //正常情况能连外网,且网络良好或者有vpn 36 | repositories { 37 | mavenCentral() 38 | google() 39 | jcenter() 40 | maven { url "https://jitpack.io" } 41 | } 42 | 43 | //正常情况能连外网,但网络质量较差或者无vpn 44 | // repositories { 45 | // maven { url 'https://maven.aliyun.com/repository/google' } 46 | // maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } 47 | // maven { url 'https://maven.aliyun.com/repository/public' } 48 | // maven { url 'https://maven.aliyun.com/repository/jcenter' } 49 | // maven { url "https://jitpack.io" } 50 | // mavenLocal() 51 | // } 52 | 53 | //离线开发环境,使用内网搭建的nexus仓库 54 | // repositories { 55 | // maven { url 'http://192.168.1.3:8081/repository/android-proxy/' } 56 | // } 57 | } 58 | 59 | task clean(type: Delete) { 60 | delete rootProject.buildDir 61 | } 62 | 63 | //project级别的全局统一配置,在module的build.gradle中引用如:compileSdkVersion rootProject.ext.compileSdkVersion 64 | ext { 65 | compileSdkVersion = 28 66 | buildToolsVersion = "28.0.3" 67 | supprotVersion = "28.0.0" 68 | minSdkVersion = 15 69 | targetSdkVersion = 24 70 | 71 | versionCode = 1 72 | versionName = "1.0" 73 | 74 | release_path = '../.release_apk' 75 | } 76 | 77 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/gradle.properties -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 29 13:44:26 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /libPullRecyclerView/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libPullRecyclerView/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | buildToolsVersion rootProject.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_8 21 | targetCompatibility JavaVersion.VERSION_1_8 22 | } 23 | } 24 | 25 | dependencies { 26 | api fileTree(dir: 'libs', include: ['*.jar']) 27 | compileOnly 'com.google.android.material:material:1.0.0' 28 | compileOnly 'androidx.appcompat:appcompat:1.0.2' 29 | compileOnly 'androidx.recyclerview:recyclerview:1.0.0' 30 | } 31 | 32 | apply from: './javadoc.gradle' -------------------------------------------------------------------------------- /libPullRecyclerView/javadoc.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.dcendents.android-maven' 2 | 3 | group = 'com.github.zcolin' 4 | 5 | /* 6 | * ********************************************************* 7 | * author colin 8 | * company telchina 9 | * email wanglin2046@126.com 10 | * date 18-1-9 下午3:05 11 | * ******************************************************** 12 | */ 13 | 14 | // 指定编码 15 | tasks.withType(JavaCompile) { 16 | options.encoding = "UTF-8" 17 | } 18 | 19 | // 打包源码 20 | task sourcesJar(type: Jar) { 21 | from android.sourceSets.main.java.srcDirs 22 | classifier = 'sources' 23 | } 24 | 25 | task javadoc(type: Javadoc) { 26 | failOnError false 27 | source = android.sourceSets.main.java.sourceFiles 28 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 29 | classpath += configurations.compile 30 | } 31 | 32 | // 制作文档(Javadoc) 33 | task javadocJar(type: Jar, dependsOn: javadoc) { 34 | classifier = 'javadoc' 35 | from javadoc.destinationDir 36 | } 37 | 38 | artifacts { 39 | archives sourcesJar 40 | archives javadocJar 41 | } -------------------------------------------------------------------------------- /libPullRecyclerView/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 D:\as_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 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/AppBarStateChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview; 11 | 12 | import com.google.android.material.appbar.AppBarLayout; 13 | 14 | /** 15 | * Created by Jack on 2015/10/19. 16 | */ 17 | public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { 18 | 19 | public enum State { 20 | EXPANDED, 21 | COLLAPSED, 22 | IDLE 23 | } 24 | 25 | private State mCurrentState = State.IDLE; 26 | 27 | @Override 28 | public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { 29 | if (i == 0) { 30 | if (mCurrentState != State.EXPANDED) { 31 | onStateChanged(appBarLayout, State.EXPANDED); 32 | } 33 | mCurrentState = State.EXPANDED; 34 | } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { 35 | if (mCurrentState != State.COLLAPSED) { 36 | onStateChanged(appBarLayout, State.COLLAPSED); 37 | } 38 | mCurrentState = State.COLLAPSED; 39 | } else { 40 | if (mCurrentState != State.IDLE) { 41 | onStateChanged(appBarLayout, State.IDLE); 42 | } 43 | mCurrentState = State.IDLE; 44 | } 45 | } 46 | 47 | public abstract void onStateChanged(AppBarLayout appBarLayout, State state); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/BaseRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview; 11 | 12 | import androidx.recyclerview.widget.RecyclerView; 13 | import android.util.SparseArray; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | * 可以设置Header并且封装了基本方法的的Adapter 23 | */ 24 | public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter { 25 | 26 | private ArrayList listData = new ArrayList<>(); 27 | private OnItemClickListener itemClickListener; 28 | private OnItemLongClickListener itemLongClickListener; 29 | private long minClickIntervaltime = 100; //ITEM点击的最小间隔 30 | private long mLastClickTime;//上次点击时间 31 | 32 | /** 33 | * 获取布局ID 34 | * 35 | * @return 布局Id, ex:R.layout.listitem_*** 36 | */ 37 | public abstract int getItemLayoutId(int viewType); 38 | 39 | /** 40 | * 获取布局ID 41 | * 42 | * @return 布局Id, ex:R.layout.listitem_*** 43 | */ 44 | public View getItemLayout(ViewGroup parent, int viewType) { 45 | return LayoutInflater.from(parent.getContext()).inflate(getItemLayoutId(viewType), parent, false); 46 | } 47 | 48 | /** 49 | * 客户自己定义的GridLayoutManager的item需要跨的行数 50 | * 51 | * @return GridLayoutManager 0为占满,其他为占的具体行数,最多为占满 52 | */ 53 | public int getGridItemSpanCount(int position, int viewType) { 54 | return 1; 55 | } 56 | 57 | /** 58 | * 客户自己定义的StaggeredLayoutManager的item是否需要占满 59 | * 60 | * @return true为占满, false为1行 61 | */ 62 | public boolean getIsStaggeredItemFullSpan(int position, int viewType) { 63 | return false; 64 | } 65 | 66 | /** 67 | * 设置Item点击的最小间隔 68 | * 69 | * @param minClickIntervaltime millionSeconds 70 | */ 71 | public void setItemMinClickIntervalTime(long minClickIntervaltime) { 72 | this.minClickIntervaltime = minClickIntervaltime; 73 | } 74 | 75 | /** 76 | * 设置显示数据,替代getView,在此函数中进行赋值操作 77 | *

78 | * ex: 79 | * TextView tvNumb = getView(view, R.id.tv); 80 | * tvNumb.setText(String.valueOf(position + 1)); 81 | */ 82 | public abstract void setUpData(CommonHolder holder, int position, int viewType, T data); 83 | 84 | public void setOnItemClickListener(OnItemClickListener li) { 85 | itemClickListener = li; 86 | } 87 | 88 | public void setOnItemLongClickListener(OnItemLongClickListener li) { 89 | itemLongClickListener = li; 90 | } 91 | 92 | /** 93 | * 追加条目数据 94 | */ 95 | public void addDatas(List datas) { 96 | if (datas != null) { 97 | listData.addAll(datas); 98 | } 99 | notifyDataSetChanged(); 100 | } 101 | 102 | /** 103 | * 将数据替换为传入的数据集 104 | */ 105 | public void setDatas(List datas) { 106 | listData.clear(); 107 | if (datas != null) { 108 | listData.addAll(datas); 109 | } 110 | notifyDataSetChanged(); 111 | } 112 | 113 | /** 114 | * 清空数据集 115 | */ 116 | public void clearDatas() { 117 | listData.clear(); 118 | notifyDataSetChanged(); 119 | } 120 | 121 | /** 122 | * 获取数据集 123 | */ 124 | public ArrayList getDatas() { 125 | return listData; 126 | } 127 | 128 | public T getItem(int position) { 129 | return listData.get(position); 130 | } 131 | 132 | 133 | @Override 134 | public int getItemCount() { 135 | return listData.size(); 136 | } 137 | 138 | @Override 139 | public CommonHolder onCreateViewHolder(ViewGroup parent, final int viewType) { 140 | View v = getItemLayout(parent, viewType); 141 | return new CommonHolder((RecyclerView) parent, v); 142 | } 143 | 144 | @Override 145 | public void onBindViewHolder(final CommonHolder viewHolder, final int position) { 146 | final T data = listData.get(position); 147 | if (itemClickListener != null) { 148 | viewHolder.itemView.setOnClickListener(v -> { 149 | long curTime = System.currentTimeMillis(); 150 | if (curTime - mLastClickTime > minClickIntervaltime) { 151 | mLastClickTime = curTime; 152 | itemClickListener.onItemClick(viewHolder.itemView, position, data); 153 | } 154 | }); 155 | } 156 | 157 | if (itemLongClickListener != null) { 158 | viewHolder.itemView.setOnLongClickListener(v -> { 159 | long curTime = System.currentTimeMillis(); 160 | if (curTime - mLastClickTime > minClickIntervaltime) { 161 | mLastClickTime = curTime; 162 | return itemLongClickListener.onItemLongClick(viewHolder.itemView, position, data); 163 | } 164 | return false; 165 | }); 166 | } 167 | 168 | setUpData(viewHolder, position, getItemViewType(position), data); 169 | } 170 | 171 | /** 172 | * @return 返回 173 | */ 174 | protected E getView(CommonHolder holder, int id) { 175 | SparseArray spHolder = holder.spHolder; 176 | View childView = spHolder.get(id); 177 | if (null == childView) { 178 | childView = holder.itemView.findViewById(id); 179 | spHolder.put(id, childView); 180 | } 181 | return (E) childView; 182 | } 183 | 184 | /** 185 | * @return 返回 186 | * 187 | * @deprecated use {@link #getView(CommonHolder, int)} 188 | */ 189 | protected E get(CommonHolder holder, int id) { 190 | return getView(holder, id); 191 | } 192 | 193 | public static class CommonHolder extends RecyclerView.ViewHolder { 194 | public SparseArray spHolder = new SparseArray<>(); 195 | public RecyclerView viewParent; 196 | 197 | public CommonHolder(RecyclerView viewParent, View itemView) { 198 | super(itemView); 199 | this.viewParent = viewParent; 200 | } 201 | } 202 | 203 | public interface OnItemClickListener { 204 | void onItemClick(View covertView, int position, T data); 205 | } 206 | 207 | public interface OnItemLongClickListener { 208 | boolean onItemLongClick(View covertView, int position, T data); 209 | } 210 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/CommonHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview; 11 | 12 | import androidx.recyclerview.widget.RecyclerView; 13 | import android.util.SparseArray; 14 | import android.view.View; 15 | 16 | public class CommonHolder extends RecyclerView.ViewHolder { 17 | public SparseArray spHolder = new SparseArray<>(); 18 | public RecyclerView viewParent; 19 | 20 | public CommonHolder(RecyclerView viewParent, View itemView) { 21 | super(itemView); 22 | this.viewParent = viewParent; 23 | } 24 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/PullScrollView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview; 11 | 12 | import android.content.Context; 13 | import com.google.android.material.appbar.AppBarLayout; 14 | import androidx.coordinatorlayout.widget.CoordinatorLayout; 15 | import android.util.AttributeSet; 16 | import android.view.MotionEvent; 17 | import android.view.View; 18 | import android.view.ViewGroup; 19 | import android.view.ViewParent; 20 | import android.widget.LinearLayout; 21 | import android.widget.ScrollView; 22 | 23 | import com.zcolin.gui.pullrecyclerview.hfooter.DefRefreshHeader; 24 | import com.zcolin.gui.pullrecyclerview.hfooter.IRefreshHeader; 25 | 26 | 27 | /** 28 | * 下拉刷新的ScrollView 29 | *

30 | */ 31 | public class PullScrollView extends ScrollView { 32 | private RefreshListener mRefreshListener; 33 | 34 | private IRefreshHeader refreshHeader; 35 | private boolean isRefreshEnabled = true; //设置下拉刷新是否可用 36 | private float dragRate = 2; //下拉刷新滑动阻力系数,越大需要手指下拉的距离越大才能刷新 37 | 38 | private boolean isRefreshing; //是否正在刷新 39 | private float mLastY = -1; //上次触摸的的Y值 40 | private int topY; 41 | private float sumOffSet; 42 | private boolean isAdded; 43 | 44 | private AppBarStateChangeListener.State appbarState = AppBarStateChangeListener.State.EXPANDED; 45 | 46 | public PullScrollView(Context context) { 47 | this(context, null); 48 | } 49 | 50 | public PullScrollView(Context context, AttributeSet attrs) { 51 | this(context, attrs, 0); 52 | } 53 | 54 | public PullScrollView(Context context, AttributeSet attrs, int defStyle) { 55 | super(context, attrs, defStyle); 56 | init(); 57 | } 58 | 59 | private void init() { 60 | if (isRefreshEnabled) { 61 | refreshHeader = new DefRefreshHeader(getContext()); 62 | } 63 | } 64 | 65 | private void setLayout() { 66 | if (!isAdded) { 67 | isAdded = true; 68 | 69 | ViewGroup group = (ViewGroup) getParent(); 70 | LinearLayout container = new LinearLayout(getContext()); 71 | container.setOrientation(LinearLayout.VERTICAL); 72 | int index = group.indexOfChild(this); 73 | group.removeView(this); 74 | group.addView(container, index, getLayoutParams()); 75 | container.addView(refreshHeader.getHeaderView(), 76 | new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 77 | ViewGroup.LayoutParams.WRAP_CONTENT)); 78 | container.addView(this, 79 | new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 80 | ViewGroup.LayoutParams.MATCH_PARENT)); 81 | } 82 | } 83 | 84 | public View getRefreshHeaderView() { 85 | return refreshHeader.getHeaderView(); 86 | } 87 | 88 | /** 89 | * 设置下拉刷新上拉加载回调 90 | */ 91 | public void setRefreshListener(RefreshListener listener) { 92 | mRefreshListener = listener; 93 | } 94 | 95 | /** 96 | * 设置自定义的header 97 | */ 98 | public PullScrollView setRefreshHeader(IRefreshHeader refreshHeader) { 99 | this.refreshHeader = refreshHeader; 100 | return this; 101 | } 102 | 103 | /** 104 | * 下拉刷新是否可用 105 | */ 106 | public PullScrollView setIsRefreshEnabled(boolean enabled) { 107 | isRefreshEnabled = enabled; 108 | return this; 109 | } 110 | 111 | /** 112 | * 下拉刷新滑动阻力系数,越大需要手指下拉的距离越大才能刷新 113 | */ 114 | public PullScrollView setDragRate(int dragRate) { 115 | this.dragRate = dragRate; 116 | return this; 117 | } 118 | 119 | /** 120 | * 设置下拉刷新的进度条风格 121 | */ 122 | public PullScrollView setRefreshProgressStyle(String style) { 123 | if (refreshHeader != null && refreshHeader instanceof DefRefreshHeader) { 124 | ((DefRefreshHeader) refreshHeader).setProgressStyle(style); 125 | } 126 | return this; 127 | } 128 | 129 | /** 130 | * 设置加载更多的进度条风格 131 | */ 132 | public PullScrollView setRefreshHeaderText(String str1, String str2, String str3, String str4) { 133 | if (refreshHeader != null && refreshHeader instanceof DefRefreshHeader) { 134 | ((DefRefreshHeader) refreshHeader).setInfoText(str1, str2, str3, str4); 135 | } 136 | return this; 137 | } 138 | 139 | /** 140 | * 设置下拉刷新的箭头图标 141 | */ 142 | public PullScrollView setArrowImage(int resId) { 143 | if (refreshHeader != null && refreshHeader instanceof DefRefreshHeader) { 144 | ((DefRefreshHeader) refreshHeader).setArrowImageView(resId); 145 | } 146 | return this; 147 | } 148 | 149 | 150 | /** 151 | * 手动调用直接刷新,无下拉效果 152 | */ 153 | public void refresh() { 154 | if (mRefreshListener != null) { 155 | isRefreshing = true; 156 | mRefreshListener.onRefresh(); 157 | } 158 | } 159 | 160 | /** 161 | * 手动调用下拉刷新,有下拉效果 162 | */ 163 | public void refreshWithPull() { 164 | setRefreshing(true); 165 | refresh(); 166 | } 167 | 168 | /** 169 | * 下拉刷新和到底加载完成 170 | */ 171 | public void setRefreshCompleted() { 172 | if (isRefreshing) { 173 | isRefreshing = false; 174 | refreshHeader.onComplete(); 175 | } 176 | } 177 | 178 | /** 179 | * 手动调用加载状态,此函数不会调用 {@link RefreshListener#onRefresh()}加载数据 180 | * 如果需要加载数据和状态显示调用 {@link #refreshWithPull()} 181 | */ 182 | public void setRefreshing(final boolean refreshing) { 183 | if (refreshing && isRefreshEnabled) { 184 | isRefreshing = true; 185 | refreshHeader.onRefreshing(); 186 | 187 | int offSet = refreshHeader.getHeaderView().getMeasuredHeight(); 188 | refreshHeader.onMove(offSet, offSet); 189 | } 190 | } 191 | 192 | 193 | @Override 194 | public boolean onTouchEvent(MotionEvent ev) { 195 | if (mLastY == -1) { 196 | mLastY = ev.getRawY(); 197 | } 198 | 199 | switch (ev.getAction()) { 200 | case MotionEvent.ACTION_DOWN: 201 | mLastY = ev.getRawY(); 202 | sumOffSet = 0; 203 | break; 204 | case MotionEvent.ACTION_MOVE: 205 | final float deltaY = (ev.getRawY() - mLastY) / dragRate; 206 | mLastY = ev.getRawY(); 207 | sumOffSet += deltaY; 208 | if (isOnTop() && isRefreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) { 209 | refreshHeader.onMove(deltaY, sumOffSet); 210 | if (refreshHeader.getVisibleHeight() > 0 && !isRefreshing) { 211 | return false; 212 | } 213 | } 214 | break; 215 | default: 216 | mLastY = -1; // reset 217 | if (isOnTop() && isRefreshEnabled && appbarState == AppBarStateChangeListener.State.EXPANDED) { 218 | if (refreshHeader.onRelease()) { 219 | if (mRefreshListener != null) { 220 | isRefreshing = true; 221 | mRefreshListener.onRefresh(); 222 | } 223 | } 224 | } 225 | break; 226 | } 227 | return super.onTouchEvent(ev); 228 | } 229 | 230 | @Override 231 | protected void onScrollChanged(int l, int t, int oldl, int oldt) { 232 | super.onScrollChanged(l, t, oldl, oldt); 233 | topY = t; 234 | } 235 | 236 | /** 237 | * 如果在HeaderView已经被添加到布局中,说明已经到顶部 238 | */ 239 | private boolean isOnTop() { 240 | return topY == 0; 241 | } 242 | 243 | @Override 244 | protected void onAttachedToWindow() { 245 | super.onAttachedToWindow(); 246 | 247 | //解决和AppBarLayout冲突的问题 248 | ViewParent p = getParent(); 249 | while (p != null) { 250 | if (p instanceof CoordinatorLayout) { 251 | break; 252 | } 253 | p = p.getParent(); 254 | } 255 | 256 | if (p != null) { 257 | AppBarLayout appBarLayout = null; 258 | CoordinatorLayout coordinatorLayout = (CoordinatorLayout) p; 259 | final int childCount = coordinatorLayout.getChildCount(); 260 | for (int i = childCount - 1; i >= 0; i--) { 261 | final View child = coordinatorLayout.getChildAt(i); 262 | if (child instanceof AppBarLayout) { 263 | appBarLayout = (AppBarLayout) child; 264 | break; 265 | } 266 | } 267 | 268 | if (appBarLayout != null) { 269 | appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { 270 | @Override 271 | public void onStateChanged(AppBarLayout appBarLayout, State state) { 272 | appbarState = state; 273 | } 274 | }); 275 | } 276 | } 277 | setLayout(); 278 | } 279 | 280 | public interface RefreshListener { 281 | void onRefresh(); 282 | } 283 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/RecycleViewDivider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview; 11 | 12 | import android.content.Context; 13 | import android.content.res.TypedArray; 14 | import android.graphics.Canvas; 15 | import android.graphics.Paint; 16 | import android.graphics.Rect; 17 | import android.graphics.drawable.Drawable; 18 | import androidx.core.content.ContextCompat; 19 | import androidx.recyclerview.widget.LinearLayoutManager; 20 | import androidx.recyclerview.widget.RecyclerView; 21 | import android.view.View; 22 | 23 | public class RecycleViewDivider extends RecyclerView.ItemDecoration { 24 | 25 | private Paint mPaint; 26 | private Drawable mDivider; 27 | private int mDividerHeight = 2;//分割线高度,默认为1px 28 | private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL 29 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; 30 | 31 | /** 32 | * 默认分割线:高度为2px,颜色为灰色 33 | * 34 | * @param orientation 列表方向 35 | */ 36 | public RecycleViewDivider(Context context, int orientation) { 37 | if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) { 38 | throw new IllegalArgumentException("请输入正确的参数!"); 39 | } 40 | mOrientation = orientation; 41 | 42 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 43 | mDivider = a.getDrawable(0); 44 | a.recycle(); 45 | } 46 | 47 | /** 48 | * 自定义分割线 49 | * 50 | * @param orientation 列表方向 51 | * @param drawableId 分割线图片 52 | */ 53 | public RecycleViewDivider(Context context, int orientation, int drawableId) { 54 | this(context, orientation); 55 | mDivider = ContextCompat.getDrawable(context, drawableId); 56 | mDividerHeight = mDivider.getIntrinsicHeight(); 57 | } 58 | 59 | /** 60 | * 自定义分割线 61 | * 62 | * @param orientation 列表方向 63 | * @param dividerHeight 分割线高度 64 | * @param dividerColor 分割线颜色 65 | */ 66 | public RecycleViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) { 67 | this(context, orientation); 68 | mDividerHeight = dividerHeight; 69 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 70 | mPaint.setColor(dividerColor); 71 | mPaint.setStyle(Paint.Style.FILL); 72 | } 73 | 74 | 75 | //获取分割线尺寸 76 | @Override 77 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 78 | super.getItemOffsets(outRect, view, parent, state); 79 | outRect.set(0, 0, 0, mDividerHeight); 80 | } 81 | 82 | //绘制分割线 83 | @Override 84 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 85 | super.onDraw(c, parent, state); 86 | if (mOrientation == LinearLayoutManager.VERTICAL) { 87 | drawVertical(c, parent); 88 | } else { 89 | drawHorizontal(c, parent); 90 | } 91 | } 92 | 93 | //绘制横向 item 分割线 94 | private void drawHorizontal(Canvas canvas, RecyclerView parent) { 95 | final int left = parent.getPaddingLeft(); 96 | final int right = parent.getMeasuredWidth() - parent.getPaddingRight(); 97 | final int childSize = parent.getChildCount(); 98 | 99 | for (int i = 0; i < childSize; i++) { 100 | final View child = parent.getChildAt(i); 101 | //所有header和footer都不画线 102 | if (child.getTag() != null && child.getTag() instanceof String) { 103 | String tag = ((String) child.getTag()); 104 | if ("reservedView".equals(tag)) { 105 | continue; 106 | } 107 | } 108 | 109 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 110 | final int top = child.getBottom() + layoutParams.bottomMargin; 111 | final int bottom = top + mDividerHeight; 112 | if (mDivider != null) { 113 | mDivider.setBounds(left, top, right, bottom); 114 | mDivider.draw(canvas); 115 | } 116 | if (mPaint != null) { 117 | canvas.drawRect(left, top, right, bottom, mPaint); 118 | } 119 | } 120 | } 121 | 122 | //绘制纵向 item 分割线 123 | 124 | private void drawVertical(Canvas canvas, RecyclerView parent) { 125 | final int top = parent.getPaddingTop(); 126 | final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom(); 127 | final int childSize = parent.getChildCount(); 128 | for (int i = 0; i < childSize; i++) { 129 | final View child = parent.getChildAt(i); 130 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 131 | final int left = child.getRight() + layoutParams.rightMargin; 132 | final int right = left + mDividerHeight; 133 | if (mDivider != null) { 134 | mDivider.setBounds(left, top, right, bottom); 135 | mDivider.draw(canvas); 136 | } 137 | if (mPaint != null) { 138 | canvas.drawRect(left, top, right, bottom, mPaint); 139 | } 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/hfooter/DefLoadMoreFooter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.hfooter; 11 | 12 | import android.content.Context; 13 | import androidx.recyclerview.widget.RecyclerView; 14 | import android.util.AttributeSet; 15 | import android.view.Gravity; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.LinearLayout; 19 | import android.widget.ProgressBar; 20 | import android.widget.TextView; 21 | 22 | import com.zcolin.gui.pullrecyclerview.progressindicator.AVLoadingIndicatorView; 23 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 24 | import com.zcolin.gui.pullrecyclerview.progressindicator.SimpleViewSwitcher; 25 | 26 | 27 | /** 28 | * 默认的加载更多FooterView,如需要简单的变换,可以直接在{@link com.zcolin.gui.pullrecyclerview.PullRecyclerView}中设置 29 | * 复杂的需要继承此类重写或者实现{@link ILoadMoreFooter} 接口 30 | */ 31 | public class DefLoadMoreFooter extends LinearLayout implements ILoadMoreFooter { 32 | 33 | public static String STR_LOADING = "正在加载"; 34 | public static String STR_LOAD_COMPLETE = "正在加载"; 35 | public static String STR_NOMORE = "已加载全部"; 36 | 37 | private SimpleViewSwitcher mProgressBar; 38 | private TextView mText; 39 | private boolean isShowNoMore = true; 40 | private int mMeasuredHeight; 41 | 42 | public DefLoadMoreFooter(Context context) { 43 | this(context, null); 44 | } 45 | 46 | public DefLoadMoreFooter(Context context, AttributeSet attrs) { 47 | super(context, attrs); 48 | initView(); 49 | } 50 | 51 | public void initView() { 52 | setGravity(Gravity.CENTER); 53 | setPadding(0, 25, 0, 25); 54 | setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 55 | ViewGroup.LayoutParams.WRAP_CONTENT)); 56 | setProgressStyle(ProgressStyle.BallSpinFadeLoaderIndicator); 57 | 58 | mText = new TextView(getContext()); 59 | mText.setText(STR_LOADING); 60 | LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 61 | ViewGroup.LayoutParams.WRAP_CONTENT); 62 | layoutParams.setMargins(20, 0, 0, 0); 63 | addView(mText, layoutParams); 64 | 65 | onReset();//初始为隐藏状态 66 | 67 | measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 68 | mMeasuredHeight = getMeasuredHeight(); 69 | } 70 | 71 | 72 | public void setProgressStyle(String style) { 73 | if (mProgressBar == null) { 74 | mProgressBar = new SimpleViewSwitcher(getContext()); 75 | mProgressBar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 76 | ViewGroup.LayoutParams.WRAP_CONTENT)); 77 | addView(mProgressBar); 78 | } 79 | 80 | if (ProgressStyle.SysProgress.equals(style)) { 81 | mProgressBar.setView(new ProgressBar(getContext(), null, android.R.attr.progressBarStyle)); 82 | } else { 83 | AVLoadingIndicatorView progressView = new AVLoadingIndicatorView(this.getContext()); 84 | progressView.setIndicatorColor(0xffB5B5B5); 85 | progressView.setIndicator(style); 86 | mProgressBar.setView(progressView); 87 | } 88 | } 89 | 90 | @Override 91 | public void setIsShowNoMore(boolean isShow) { 92 | isShowNoMore = isShow; 93 | } 94 | 95 | @Override 96 | public void onReset() { 97 | onComplete(); 98 | } 99 | 100 | @Override 101 | public void onLoading() { 102 | mProgressBar.setVisibility(View.VISIBLE); 103 | mText.setText(STR_LOADING); 104 | this.getLayoutParams().height = mMeasuredHeight;//动态设置高度,否则在列表中会占位高度 105 | this.setVisibility(View.VISIBLE); 106 | } 107 | 108 | @Override 109 | public void onComplete() { 110 | mText.setText(STR_LOAD_COMPLETE); 111 | this.getLayoutParams().height = mMeasuredHeight; 112 | this.setVisibility(View.INVISIBLE); 113 | } 114 | 115 | @Override 116 | public void onNoMore() { 117 | mText.setText(STR_NOMORE); 118 | mProgressBar.setVisibility(View.GONE); 119 | this.setVisibility(isShowNoMore ? View.VISIBLE : View.GONE); 120 | this.getLayoutParams().height = isShowNoMore ? mMeasuredHeight : 5; 121 | } 122 | 123 | @Override 124 | public View getFootView() { 125 | return this; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/hfooter/DefRefreshHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.hfooter; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.content.Context; 14 | import android.content.SharedPreferences; 15 | import android.os.Handler; 16 | import android.util.AttributeSet; 17 | import android.view.Gravity; 18 | import android.view.LayoutInflater; 19 | import android.view.View; 20 | import android.view.ViewGroup; 21 | import android.view.animation.Animation; 22 | import android.view.animation.RotateAnimation; 23 | import android.widget.ImageView; 24 | import android.widget.LinearLayout; 25 | import android.widget.ProgressBar; 26 | import android.widget.TextView; 27 | 28 | import com.zcolin.gui.pullrecyclerview.R; 29 | import com.zcolin.gui.pullrecyclerview.progressindicator.AVLoadingIndicatorView; 30 | import com.zcolin.gui.pullrecyclerview.progressindicator.ProgressStyle; 31 | import com.zcolin.gui.pullrecyclerview.progressindicator.SimpleViewSwitcher; 32 | 33 | /** 34 | * 默认的下拉更多HeaderView,如需要简单的变换,可以直接在{@link com.zcolin.gui.pullrecyclerview.PullRecyclerView}中设置 35 | * 复杂的需要继承此类重写或者实现{@link IRefreshHeader} 接口 36 | */ 37 | public class DefRefreshHeader extends LinearLayout implements IRefreshHeader { 38 | private static final int ROTATE_ANIM_DURATION = 180; 39 | 40 | private int mState; 41 | 42 | private String strInfo1 = "下拉刷新"; 43 | private String strInfo2 = "释放立即刷新"; 44 | private String strInfo3 = "正在刷新"; 45 | private String strInfo4 = "刷新完成"; 46 | 47 | private LinearLayout mContainer; 48 | private ImageView mArrowImageView; 49 | private SimpleViewSwitcher mProgressBar; 50 | private TextView mStatusTextView; 51 | private TextView mHeaderTimeView; 52 | 53 | private Animation mRotateUpAnim; 54 | private Animation mRotateDownAnim; 55 | 56 | public int mMeasuredHeight; 57 | 58 | public DefRefreshHeader(Context context) { 59 | this(context, null); 60 | } 61 | 62 | public DefRefreshHeader(Context context, AttributeSet attrs) { 63 | super(context, attrs); 64 | initView(); 65 | } 66 | 67 | private void initView() { 68 | // 初始情况,设置下拉刷新view高度为0 69 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 70 | lp.setMargins(0, 0, 0, 0); 71 | this.setLayoutParams(lp); 72 | this.setPadding(0, 0, 0, 0); 73 | 74 | mContainer = (LinearLayout) LayoutInflater.from(getContext()) 75 | .inflate(R.layout.gui_pullrecyclerview_header, null); 76 | addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0)); 77 | setGravity(Gravity.BOTTOM); 78 | 79 | mArrowImageView = findViewById(R.id.listview_header_arrow); 80 | mStatusTextView = findViewById(R.id.refresh_status_textview); 81 | 82 | mProgressBar = findViewById(R.id.listview_header_progressbar); 83 | setProgressStyle(ProgressStyle.BallSpinFadeLoaderIndicator); 84 | 85 | mRotateUpAnim = new RotateAnimation(0.0f, 86 | -180.0f, 87 | Animation.RELATIVE_TO_SELF, 88 | 0.5f, 89 | Animation.RELATIVE_TO_SELF, 90 | 0.5f); 91 | mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION); 92 | mRotateUpAnim.setFillAfter(true); 93 | 94 | mRotateDownAnim = new RotateAnimation(-180.0f, 95 | 0.0f, 96 | Animation.RELATIVE_TO_SELF, 97 | 0.5f, 98 | Animation.RELATIVE_TO_SELF, 99 | 0.5f); 100 | mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION); 101 | mRotateDownAnim.setFillAfter(true); 102 | 103 | mHeaderTimeView = findViewById(R.id.last_refresh_time); 104 | measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 105 | mMeasuredHeight = getMeasuredHeight(); 106 | } 107 | 108 | /** 109 | * 设置加载进度框样式 110 | * 111 | * @param style {@link ProgressStyle} 112 | */ 113 | public void setProgressStyle(String style) { 114 | if (ProgressStyle.SysProgress.equals(style)) { 115 | mProgressBar.setView(new ProgressBar(getContext(), null, android.R.attr.progressBarStyle)); 116 | } else { 117 | AVLoadingIndicatorView progressView = new AVLoadingIndicatorView(this.getContext()); 118 | progressView.setIndicatorColor(0xffB5B5B5); 119 | progressView.setIndicator(style); 120 | mProgressBar.setView(progressView); 121 | } 122 | } 123 | 124 | /** 125 | * 设置控件的不同状态的文字 126 | * 127 | * @param str1 下拉时显示的文字, 如‘下拉刷新’ 128 | * @param str2 拉到可以刷新的距离显示 如‘释放立即刷新’ 129 | * @param str3 刷新中的文字 如‘正在刷新’ 130 | * @param str4 刷新完成的文字 如‘刷新完成’ 131 | */ 132 | public void setInfoText(String str1, String str2, String str3, String str4) { 133 | strInfo1 = str1; 134 | strInfo2 = str2; 135 | strInfo3 = str3; 136 | strInfo4 = str4; 137 | } 138 | 139 | /** 140 | * 设置下拉箭头的图标 141 | */ 142 | public void setArrowImageView(int resid) { 143 | mArrowImageView.setImageResource(resid); 144 | } 145 | 146 | 147 | @Override 148 | public void onReset() { 149 | mArrowImageView.setVisibility(View.VISIBLE); 150 | mProgressBar.setVisibility(View.INVISIBLE); 151 | 152 | if (mState == STATE_PREPARED) { 153 | mArrowImageView.startAnimation(mRotateDownAnim); 154 | } 155 | if (mState == STATE_REFRESHING) { 156 | mArrowImageView.clearAnimation(); 157 | } 158 | mStatusTextView.setText(strInfo1); 159 | mState = STATE_NORMAL; 160 | } 161 | 162 | @Override 163 | public void onPrepare() { 164 | mArrowImageView.setVisibility(View.VISIBLE); 165 | mProgressBar.setVisibility(View.INVISIBLE); 166 | 167 | if (mState != STATE_PREPARED) { 168 | mArrowImageView.clearAnimation(); 169 | mArrowImageView.startAnimation(mRotateUpAnim); 170 | mStatusTextView.setText(strInfo2); 171 | } 172 | mState = STATE_PREPARED; 173 | } 174 | 175 | @Override 176 | public void onMove(float offSet, float sumOffSet) { 177 | if (getVisibleHeight() > 0 || offSet > 0) { 178 | setVisibleHeight((int) offSet + getVisibleHeight()); 179 | if (mState <= STATE_PREPARED) { // 未处于刷新状态,更新箭头 180 | if (getVisibleHeight() > mMeasuredHeight) { 181 | onPrepare(); 182 | } else { 183 | onReset(); 184 | } 185 | } 186 | } 187 | } 188 | 189 | @Override 190 | public boolean onRelease() { 191 | int height = getVisibleHeight(); 192 | if (height > mMeasuredHeight && mState < STATE_REFRESHING) { 193 | onRefreshing(); 194 | } 195 | 196 | // refreshing and header isn't shown fully. do nothing. 197 | if (mState == STATE_REFRESHING && height <= mMeasuredHeight) { 198 | //return; 199 | } 200 | 201 | int destHeight = 0; // default: scroll back to dismiss header. 202 | // is refreshing, just scroll back to show all the header. 203 | if (mState == STATE_REFRESHING) { 204 | destHeight = mMeasuredHeight; 205 | } 206 | smoothScrollTo(destHeight); 207 | return mState == STATE_REFRESHING; 208 | } 209 | 210 | @Override 211 | public void onRefreshing() { 212 | mArrowImageView.clearAnimation(); 213 | mArrowImageView.setVisibility(View.INVISIBLE); 214 | mProgressBar.setVisibility(View.VISIBLE); 215 | mStatusTextView.setText(strInfo3); 216 | mState = STATE_REFRESHING; 217 | } 218 | 219 | @Override 220 | public void onComplete() { 221 | mArrowImageView.setVisibility(View.INVISIBLE); 222 | mProgressBar.setVisibility(View.INVISIBLE); 223 | 224 | SharedPreferences pre = getContext().getApplicationContext() 225 | .getSharedPreferences("pullrecyclerview", Context.MODE_PRIVATE); 226 | mHeaderTimeView.setText(friendlyTime(pre.getLong("refresh_time", 0))); 227 | new Handler().postDelayed(() -> reset(), 200); 228 | mStatusTextView.setText(strInfo4); 229 | 230 | //当前刷新时间存入到本地 231 | long timestamp = System.currentTimeMillis(); 232 | pre.edit().putLong("refresh_time", timestamp).apply(); 233 | mState = STATE_COMPLETE; 234 | } 235 | 236 | /** 237 | * 回归初始状态,刷新完成时调用 238 | */ 239 | private void reset() { 240 | smoothScrollTo(0); 241 | new Handler().postDelayed(() -> onReset(), 500); 242 | } 243 | 244 | /** 245 | * 平滑的显示Header偏移 246 | */ 247 | private void smoothScrollTo(int destHeight) { 248 | ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), destHeight); 249 | animator.setDuration(300).start(); 250 | animator.addUpdateListener(animation -> setVisibleHeight((int) animation.getAnimatedValue())); 251 | animator.start(); 252 | } 253 | 254 | 255 | /** 256 | * 设置下拉Header需要显示的高度 257 | */ 258 | private void setVisibleHeight(int height) { 259 | if (height < 0) { 260 | height = 0; 261 | } 262 | LayoutParams lp = (LayoutParams) mContainer.getLayoutParams(); 263 | lp.height = height; 264 | mContainer.setLayoutParams(lp); 265 | } 266 | 267 | 268 | @Override 269 | public int getVisibleHeight() { 270 | LayoutParams lp = (LayoutParams) mContainer.getLayoutParams(); 271 | return lp.height; 272 | } 273 | 274 | @Override 275 | public View getHeaderView() { 276 | return this; 277 | } 278 | 279 | private String friendlyTime(long timestamp) { 280 | if (timestamp == 0) { 281 | return ""; 282 | } 283 | 284 | int ct = (int) ((System.currentTimeMillis() - timestamp) / 1000); 285 | if (ct >= 0 && ct < 60) { 286 | return "刚刚"; 287 | } 288 | if (ct >= 60 && ct < 3600) { 289 | return Math.max(ct / 60, 1) + "分钟前"; 290 | } 291 | if (ct >= 3600 && ct < 86400) { 292 | return ct / 3600 + "小时前"; 293 | } 294 | if (ct >= 86400 && ct < 2592000) { //86400 * 30 295 | int day = ct / 86400; 296 | return day + "天前"; 297 | } 298 | if (ct >= 2592000 && ct < 31104000) { //86400 * 30 299 | return ct / 2592000 + "月前"; 300 | } 301 | return ct / 31104000 + "年前"; 302 | } 303 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/hfooter/ILoadMoreFooter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.hfooter; 11 | 12 | import android.view.View; 13 | 14 | /** 15 | * 加载更多FooterView需要实现的接口 16 | */ 17 | public interface ILoadMoreFooter { 18 | 19 | /** 20 | * 状态回调,回复初始设置 21 | */ 22 | void onReset(); 23 | 24 | /** 25 | * 状态回调,加载中 26 | */ 27 | void onLoading(); 28 | 29 | /** 30 | * 状态回调,加载完成 31 | */ 32 | void onComplete(); 33 | 34 | /** 35 | * 状态回调,已全部加载完成 36 | */ 37 | void onNoMore(); 38 | 39 | /** 40 | * 是否显示没有更多 41 | */ 42 | void setIsShowNoMore(boolean isShow); 43 | 44 | /** 45 | * 加载更多的View 46 | */ 47 | View getFootView(); 48 | } 49 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/hfooter/IRefreshHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.hfooter; 11 | 12 | import android.view.View; 13 | 14 | /** 15 | * 下拉HeadrView需要实现的接口 16 | */ 17 | public interface IRefreshHeader { 18 | 19 | /** 20 | * 手势状态 21 | */ 22 | int STATE_NORMAL = 0; 23 | int STATE_PREPARED = 1; 24 | int STATE_REFRESHING = 2; 25 | int STATE_COMPLETE = 3; 26 | 27 | void onReset(); 28 | 29 | /** 30 | * 处于可以刷新的状态,已经过了指定距离 31 | */ 32 | void onPrepare(); 33 | 34 | /** 35 | * 正在刷新 36 | */ 37 | void onRefreshing(); 38 | 39 | /** 40 | * 下拉移动 41 | */ 42 | void onMove(float offSet, float sumOffSet); 43 | 44 | /** 45 | * 下拉松开 46 | */ 47 | boolean onRelease(); 48 | 49 | /** 50 | * 下拉刷新完成 51 | */ 52 | void onComplete(); 53 | 54 | /** 55 | * 获取HeaderView 56 | */ 57 | View getHeaderView(); 58 | 59 | /** 60 | * 获取Header的显示高度 61 | */ 62 | int getVisibleHeight(); 63 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/ProgressStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator; 11 | 12 | /** 13 | * Created by Jack on 2015/10/19. 14 | */ 15 | public class ProgressStyle { 16 | public static final String SysProgress = "SysProgress"; 17 | public static final String BallBeatIndicator = "BallBeatIndicator"; 18 | public static final String BallClipRotateIndicator = "BallClipRotateIndicator"; 19 | public static final String BallClipRotateMultipleIndicator = "BallClipRotateMultipleIndicator"; 20 | public static final String BallClipRotatePulseIndicator = "BallClipRotatePulseIndicator"; 21 | public static final String BallGridBeatIndicator = "BallGridBeatIndicator"; 22 | public static final String BallGridPulseIndicator = "BallGridPulseIndicator"; 23 | public static final String BallPulseIndicator = "BallPulseIndicator"; 24 | public static final String BallPulseRiseIndicator = "BallPulseRiseIndicator"; 25 | public static final String BallPulseSyncIndicator = "BallPulseSyncIndicator"; 26 | public static final String BallRotateIndicator = "BallRotateIndicator"; 27 | public static final String BallScaleIndicator = "BallScaleIndicator"; 28 | public static final String BallScaleMultipleIndicator = "BallScaleMultipleIndicator"; 29 | public static final String BallScaleRippleIndicator = "BallScaleRippleIndicator"; 30 | public static final String BallScaleRippleMultipleIndicator = "BallScaleRippleMultipleIndicator"; 31 | public static final String BallSpinFadeLoaderIndicator = "BallSpinFadeLoaderIndicator"; 32 | public static final String BallTrianglePathIndicator = "BallTrianglePathIndicator"; 33 | public static final String BallZigZagDeflectIndicator = "BallZigZagDeflectIndicator"; 34 | public static final String BallZigZagIndicator = "BallZigZagIndicator"; 35 | public static final String CubeTransitionIndicator = "CubeTransitionIndicator"; 36 | public static final String LineScaleIndicator = "LineScaleIndicator"; 37 | public static final String LineScalePartyIndicator = "LineScalePartyIndicator"; 38 | public static final String LineScalePulseOutIndicator = "LineScalePulseOutIndicator"; 39 | public static final String LineScalePulseOutRapidIndicator = "LineScalePulseOutRapidIndicator"; 40 | public static final String LineSpinFadeLoaderIndicator = "LineSpinFadeLoaderIndicator"; 41 | public static final String PacmanIndicator = "PacmanIndicator"; 42 | public static final String SemiCircleSpinIndicator = "SemiCircleSpinIndicator"; 43 | public static final String SquareSpinIndicator = "SquareSpinIndicator"; 44 | public static final String TriangleSkewSpinIndicator = "TriangleSkewSpinIndicator"; 45 | } 46 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/SimpleViewSwitcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator; 11 | 12 | import android.content.Context; 13 | import android.util.AttributeSet; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | 17 | /** 18 | * Created by Jack on 2015/10/19. 19 | */ 20 | public class SimpleViewSwitcher extends ViewGroup { 21 | 22 | public SimpleViewSwitcher(Context context) { 23 | super(context); 24 | } 25 | 26 | public SimpleViewSwitcher(Context context, AttributeSet attrs) { 27 | this(context, attrs, 0); 28 | } 29 | 30 | public SimpleViewSwitcher(Context context, AttributeSet attrs, int defStyle) { 31 | super(context, attrs, defStyle); 32 | } 33 | 34 | @Override 35 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 36 | int childCount = this.getChildCount(); 37 | int maxHeight = 0; 38 | int maxWidth = 0; 39 | for (int i = 0; i < childCount; i++) { 40 | View child = this.getChildAt(i); 41 | this.measureChild(child, widthMeasureSpec, heightMeasureSpec); 42 | int cw = child.getMeasuredWidth(); 43 | // int ch = child.getMeasuredHeight(); 44 | maxWidth = child.getMeasuredWidth(); 45 | maxHeight = child.getMeasuredHeight(); 46 | } 47 | setMeasuredDimension(maxWidth, maxHeight); 48 | } 49 | 50 | @Override 51 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 52 | final int count = getChildCount(); 53 | for (int i = 0; i < count; i++) { 54 | final View child = getChildAt(i); 55 | if (child.getVisibility() != View.GONE) { 56 | child.layout(0, 0, r - l, b - t); 57 | 58 | } 59 | } 60 | } 61 | 62 | public void setView(View view) { 63 | if (this.getChildCount() != 0) { 64 | this.removeViewAt(0); 65 | } 66 | this.addView(view, 0); 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallBeatIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/19. 20 | */ 21 | public class BallBeatIndicator extends Indicator { 22 | 23 | public static final float SCALE = 1.0f; 24 | 25 | public static final int ALPHA = 255; 26 | 27 | private float[] scaleFloats = new float[]{SCALE, SCALE, SCALE}; 28 | 29 | int[] alphas = new int[]{ALPHA, ALPHA, ALPHA,}; 30 | 31 | @Override 32 | public void draw(Canvas canvas, Paint paint) { 33 | float circleSpacing = 4; 34 | float radius = (getWidth() - circleSpacing * 2) / 6; 35 | float x = getWidth() / 2 - (radius * 2 + circleSpacing); 36 | float y = getHeight() / 2; 37 | for (int i = 0; i < 3; i++) { 38 | canvas.save(); 39 | float translateX = x + (radius * 2) * i + circleSpacing * i; 40 | canvas.translate(translateX, y); 41 | canvas.scale(scaleFloats[i], scaleFloats[i]); 42 | paint.setAlpha(alphas[i]); 43 | canvas.drawCircle(0, 0, radius, paint); 44 | canvas.restore(); 45 | } 46 | } 47 | 48 | @Override 49 | public ArrayList onCreateAnimators() { 50 | ArrayList animators = new ArrayList<>(); 51 | int[] delays = new int[]{350, 0, 350}; 52 | for (int i = 0; i < 3; i++) { 53 | final int index = i; 54 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.75f, 1); 55 | scaleAnim.setDuration(700); 56 | scaleAnim.setRepeatCount(-1); 57 | scaleAnim.setStartDelay(delays[i]); 58 | addUpdateListener(scaleAnim, animation -> { 59 | scaleFloats[index] = (float) animation.getAnimatedValue(); 60 | postInvalidate(); 61 | }); 62 | 63 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 51, 255); 64 | alphaAnim.setDuration(700); 65 | alphaAnim.setRepeatCount(-1); 66 | alphaAnim.setStartDelay(delays[i]); 67 | addUpdateListener(alphaAnim, animation -> { 68 | alphas[index] = (int) animation.getAnimatedValue(); 69 | postInvalidate(); 70 | }); 71 | animators.add(scaleAnim); 72 | animators.add(alphaAnim); 73 | } 74 | return animators; 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallClipRotateIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/16. 21 | */ 22 | public class BallClipRotateIndicator extends Indicator { 23 | 24 | float scaleFloat = 1, degrees; 25 | 26 | @Override 27 | public void draw(Canvas canvas, Paint paint) { 28 | paint.setStyle(Paint.Style.STROKE); 29 | paint.setStrokeWidth(3); 30 | 31 | float circleSpacing = 12; 32 | float x = (getWidth()) / 2; 33 | float y = (getHeight()) / 2; 34 | canvas.translate(x, y); 35 | canvas.scale(scaleFloat, scaleFloat); 36 | canvas.rotate(degrees); 37 | RectF rectF = new RectF(-x + circleSpacing, -y + circleSpacing, 0 + x - circleSpacing, 0 + y - circleSpacing); 38 | canvas.drawArc(rectF, -45, 270, false, paint); 39 | } 40 | 41 | @Override 42 | public ArrayList onCreateAnimators() { 43 | ArrayList animators = new ArrayList<>(); 44 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.6f, 0.5f, 1); 45 | scaleAnim.setDuration(750); 46 | scaleAnim.setRepeatCount(-1); 47 | addUpdateListener(scaleAnim, animation -> { 48 | scaleFloat = (float) animation.getAnimatedValue(); 49 | postInvalidate(); 50 | }); 51 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360); 52 | rotateAnim.setDuration(750); 53 | rotateAnim.setRepeatCount(-1); 54 | addUpdateListener(rotateAnim, animation -> { 55 | degrees = (float) animation.getAnimatedValue(); 56 | postInvalidate(); 57 | }); 58 | animators.add(scaleAnim); 59 | animators.add(rotateAnim); 60 | return animators; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallClipRotateMultipleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/17. 21 | */ 22 | public class BallClipRotateMultipleIndicator extends Indicator { 23 | 24 | float scaleFloat = 1, degrees; 25 | 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | paint.setStrokeWidth(3); 30 | paint.setStyle(Paint.Style.STROKE); 31 | 32 | float circleSpacing = 12; 33 | float x = getWidth() / 2; 34 | float y = getHeight() / 2; 35 | 36 | canvas.save(); 37 | 38 | canvas.translate(x, y); 39 | canvas.scale(scaleFloat, scaleFloat); 40 | canvas.rotate(degrees); 41 | 42 | //draw two big arc 43 | float[] bStartAngles = new float[]{135, -45}; 44 | for (int i = 0; i < 2; i++) { 45 | RectF rectF = new RectF(-x + circleSpacing, -y + circleSpacing, x - circleSpacing, y - circleSpacing); 46 | canvas.drawArc(rectF, bStartAngles[i], 90, false, paint); 47 | } 48 | 49 | canvas.restore(); 50 | canvas.translate(x, y); 51 | canvas.scale(scaleFloat, scaleFloat); 52 | canvas.rotate(-degrees); 53 | //draw two small arc 54 | float[] sStartAngles = new float[]{225, 45}; 55 | for (int i = 0; i < 2; i++) { 56 | RectF rectF = new RectF(-x / 1.8f + circleSpacing, -y / 1.8f + circleSpacing, x / 1.8f - circleSpacing, y / 1.8f - circleSpacing); 57 | canvas.drawArc(rectF, sStartAngles[i], 90, false, paint); 58 | } 59 | } 60 | 61 | @Override 62 | public ArrayList onCreateAnimators() { 63 | ArrayList animators = new ArrayList<>(); 64 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.6f, 1); 65 | scaleAnim.setDuration(1000); 66 | scaleAnim.setRepeatCount(-1); 67 | addUpdateListener(scaleAnim, animation -> { 68 | scaleFloat = (float) animation.getAnimatedValue(); 69 | postInvalidate(); 70 | }); 71 | 72 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360); 73 | rotateAnim.setDuration(1000); 74 | rotateAnim.setRepeatCount(-1); 75 | addUpdateListener(rotateAnim, animation -> { 76 | degrees = (float) animation.getAnimatedValue(); 77 | postInvalidate(); 78 | }); 79 | animators.add(scaleAnim); 80 | animators.add(rotateAnim); 81 | return animators; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallClipRotatePulseIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/16. 21 | */ 22 | public class BallClipRotatePulseIndicator extends Indicator { 23 | 24 | float scaleFloat1, scaleFloat2, degrees; 25 | 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | float circleSpacing = 12; 30 | float x = getWidth() / 2; 31 | float y = getHeight() / 2; 32 | 33 | //draw fill circle 34 | canvas.save(); 35 | canvas.translate(x, y); 36 | canvas.scale(scaleFloat1, scaleFloat1); 37 | paint.setStyle(Paint.Style.FILL); 38 | canvas.drawCircle(0, 0, x / 2.5f, paint); 39 | 40 | canvas.restore(); 41 | 42 | canvas.translate(x, y); 43 | canvas.scale(scaleFloat2, scaleFloat2); 44 | canvas.rotate(degrees); 45 | 46 | paint.setStrokeWidth(3); 47 | paint.setStyle(Paint.Style.STROKE); 48 | 49 | //draw two arc 50 | float[] startAngles = new float[]{225, 45}; 51 | for (int i = 0; i < 2; i++) { 52 | RectF rectF = new RectF(-x + circleSpacing, -y + circleSpacing, x - circleSpacing, y - circleSpacing); 53 | canvas.drawArc(rectF, startAngles[i], 90, false, paint); 54 | } 55 | } 56 | 57 | @Override 58 | public ArrayList onCreateAnimators() { 59 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.3f, 1); 60 | scaleAnim.setDuration(1000); 61 | scaleAnim.setRepeatCount(-1); 62 | addUpdateListener(scaleAnim, animation -> { 63 | scaleFloat1 = (float) animation.getAnimatedValue(); 64 | postInvalidate(); 65 | }); 66 | 67 | ValueAnimator scaleAnim2 = ValueAnimator.ofFloat(1, 0.6f, 1); 68 | scaleAnim2.setDuration(1000); 69 | scaleAnim2.setRepeatCount(-1); 70 | addUpdateListener(scaleAnim2, animation -> { 71 | scaleFloat2 = (float) animation.getAnimatedValue(); 72 | postInvalidate(); 73 | }); 74 | 75 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360); 76 | rotateAnim.setDuration(1000); 77 | rotateAnim.setRepeatCount(-1); 78 | addUpdateListener(rotateAnim, animation -> { 79 | degrees = (float) animation.getAnimatedValue(); 80 | postInvalidate(); 81 | }); 82 | ArrayList animators = new ArrayList<>(); 83 | animators.add(scaleAnim); 84 | animators.add(scaleAnim2); 85 | animators.add(rotateAnim); 86 | return animators; 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallGridBeatIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/20. 20 | */ 21 | public class BallGridBeatIndicator extends Indicator { 22 | 23 | public static final int ALPHA = 255; 24 | 25 | int[] alphas = new int[]{ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA}; 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | float circleSpacing = 4; 30 | float radius = (getWidth() - circleSpacing * 4) / 6; 31 | float x = getWidth() / 2 - (radius * 2 + circleSpacing); 32 | float y = getWidth() / 2 - (radius * 2 + circleSpacing); 33 | 34 | for (int i = 0; i < 3; i++) { 35 | for (int j = 0; j < 3; j++) { 36 | canvas.save(); 37 | float translateX = x + (radius * 2) * j + circleSpacing * j; 38 | float translateY = y + (radius * 2) * i + circleSpacing * i; 39 | canvas.translate(translateX, translateY); 40 | paint.setAlpha(alphas[3 * i + j]); 41 | canvas.drawCircle(0, 0, radius, paint); 42 | canvas.restore(); 43 | } 44 | } 45 | } 46 | 47 | @Override 48 | public ArrayList onCreateAnimators() { 49 | ArrayList animators = new ArrayList<>(); 50 | 51 | int[] durations = {960, 930, 1190, 1130, 1340, 940, 1200, 820, 1190}; 52 | int[] delays = {360, 400, 680, 410, 710, -150, -120, 10, 320}; 53 | 54 | for (int i = 0; i < 9; i++) { 55 | final int index = i; 56 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 168, 255); 57 | alphaAnim.setDuration(durations[i]); 58 | alphaAnim.setRepeatCount(-1); 59 | alphaAnim.setStartDelay(delays[i]); 60 | addUpdateListener(alphaAnim, animation -> { 61 | alphas[index] = (int) animation.getAnimatedValue(); 62 | postInvalidate(); 63 | }); 64 | animators.add(alphaAnim); 65 | } 66 | return animators; 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallGridPulseIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/16. 20 | */ 21 | public class BallGridPulseIndicator extends Indicator { 22 | 23 | public static final int ALPHA = 255; 24 | 25 | public static final float SCALE = 1.0f; 26 | 27 | int[] alphas = new int[]{ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA}; 28 | 29 | float[] scaleFloats = new float[]{SCALE, SCALE, SCALE, SCALE, SCALE, SCALE, SCALE, SCALE, SCALE}; 30 | 31 | 32 | @Override 33 | public void draw(Canvas canvas, Paint paint) { 34 | float circleSpacing = 4; 35 | float radius = (getWidth() - circleSpacing * 4) / 6; 36 | float x = getWidth() / 2 - (radius * 2 + circleSpacing); 37 | float y = getWidth() / 2 - (radius * 2 + circleSpacing); 38 | 39 | for (int i = 0; i < 3; i++) { 40 | for (int j = 0; j < 3; j++) { 41 | canvas.save(); 42 | float translateX = x + (radius * 2) * j + circleSpacing * j; 43 | float translateY = y + (radius * 2) * i + circleSpacing * i; 44 | canvas.translate(translateX, translateY); 45 | canvas.scale(scaleFloats[3 * i + j], scaleFloats[3 * i + j]); 46 | paint.setAlpha(alphas[3 * i + j]); 47 | canvas.drawCircle(0, 0, radius, paint); 48 | canvas.restore(); 49 | } 50 | } 51 | } 52 | 53 | @Override 54 | public ArrayList onCreateAnimators() { 55 | ArrayList animators = new ArrayList<>(); 56 | int[] durations = {720, 1020, 1280, 1420, 1450, 1180, 870, 1450, 1060}; 57 | int[] delays = {-60, 250, -170, 480, 310, 30, 460, 780, 450}; 58 | 59 | for (int i = 0; i < 9; i++) { 60 | final int index = i; 61 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.5f, 1); 62 | scaleAnim.setDuration(durations[i]); 63 | scaleAnim.setRepeatCount(-1); 64 | scaleAnim.setStartDelay(delays[i]); 65 | addUpdateListener(scaleAnim, animation -> { 66 | scaleFloats[index] = (float) animation.getAnimatedValue(); 67 | postInvalidate(); 68 | }); 69 | 70 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 210, 122, 255); 71 | alphaAnim.setDuration(durations[i]); 72 | alphaAnim.setRepeatCount(-1); 73 | alphaAnim.setStartDelay(delays[i]); 74 | addUpdateListener(alphaAnim, animation -> { 75 | alphas[index] = (int) animation.getAnimatedValue(); 76 | postInvalidate(); 77 | }); 78 | animators.add(scaleAnim); 79 | animators.add(alphaAnim); 80 | } 81 | return animators; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallPulseIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/16. 20 | */ 21 | public class BallPulseIndicator extends Indicator { 22 | 23 | public static final float SCALE = 1.0f; 24 | 25 | //scale x ,y 26 | private float[] scaleFloats = new float[]{SCALE, SCALE, SCALE}; 27 | 28 | 29 | @Override 30 | public void draw(Canvas canvas, Paint paint) { 31 | float circleSpacing = 4; 32 | float radius = (Math.min(getWidth(), getHeight()) - circleSpacing * 2) / 6; 33 | float x = getWidth() / 2 - (radius * 2 + circleSpacing); 34 | float y = getHeight() / 2; 35 | for (int i = 0; i < 3; i++) { 36 | canvas.save(); 37 | float translateX = x + (radius * 2) * i + circleSpacing * i; 38 | canvas.translate(translateX, y); 39 | canvas.scale(scaleFloats[i], scaleFloats[i]); 40 | canvas.drawCircle(0, 0, radius, paint); 41 | canvas.restore(); 42 | } 43 | } 44 | 45 | @Override 46 | public ArrayList onCreateAnimators() { 47 | ArrayList animators = new ArrayList<>(); 48 | int[] delays = new int[]{120, 240, 360}; 49 | for (int i = 0; i < 3; i++) { 50 | final int index = i; 51 | 52 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.3f, 1); 53 | 54 | scaleAnim.setDuration(750); 55 | scaleAnim.setRepeatCount(-1); 56 | scaleAnim.setStartDelay(delays[i]); 57 | 58 | addUpdateListener(scaleAnim, animation -> { 59 | scaleFloats[index] = (float) animation.getAnimatedValue(); 60 | postInvalidate(); 61 | }); 62 | animators.add(scaleAnim); 63 | } 64 | return animators; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallPulseRiseIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Camera; 14 | import android.graphics.Canvas; 15 | import android.graphics.Matrix; 16 | import android.graphics.Paint; 17 | import android.view.animation.LinearInterpolator; 18 | 19 | import java.util.ArrayList; 20 | 21 | /** 22 | * Created by Jack on 2015/10/17. 23 | */ 24 | public class BallPulseRiseIndicator extends Indicator { 25 | 26 | private Camera mCamera; 27 | private Matrix mMatrix; 28 | 29 | private float degress; 30 | 31 | public BallPulseRiseIndicator() { 32 | mCamera = new Camera(); 33 | mMatrix = new Matrix(); 34 | } 35 | 36 | @Override 37 | public void draw(Canvas canvas, Paint paint) { 38 | 39 | mMatrix.reset(); 40 | mCamera.save(); 41 | mCamera.rotateX(degress); 42 | mCamera.getMatrix(mMatrix); 43 | mCamera.restore(); 44 | 45 | mMatrix.preTranslate(-centerX(), -centerY()); 46 | mMatrix.postTranslate(centerX(), centerY()); 47 | canvas.concat(mMatrix); 48 | 49 | float radius = getWidth() / 10; 50 | canvas.drawCircle(getWidth() / 4, radius * 2, radius, paint); 51 | canvas.drawCircle(getWidth() * 3 / 4, radius * 2, radius, paint); 52 | 53 | canvas.drawCircle(radius, getHeight() - 2 * radius, radius, paint); 54 | canvas.drawCircle(getWidth() / 2, getHeight() - 2 * radius, radius, paint); 55 | canvas.drawCircle(getWidth() - radius, getHeight() - 2 * radius, radius, paint); 56 | } 57 | 58 | @Override 59 | public ArrayList onCreateAnimators() { 60 | ArrayList animators = new ArrayList<>(); 61 | ValueAnimator animator = ValueAnimator.ofFloat(0, 360); 62 | addUpdateListener(animator, animation -> { 63 | degress = (float) animation.getAnimatedValue(); 64 | postInvalidate(); 65 | }); 66 | animator.setInterpolator(new LinearInterpolator()); 67 | animator.setRepeatCount(-1); 68 | animator.setDuration(1500); 69 | animators.add(animator); 70 | return animators; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallPulseSyncIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/19. 20 | */ 21 | public class BallPulseSyncIndicator extends Indicator { 22 | 23 | float[] translateYFloats = new float[3]; 24 | 25 | @Override 26 | public void draw(Canvas canvas, Paint paint) { 27 | float circleSpacing = 4; 28 | float radius = (getWidth() - circleSpacing * 2) / 6; 29 | float x = getWidth() / 2 - (radius * 2 + circleSpacing); 30 | for (int i = 0; i < 3; i++) { 31 | canvas.save(); 32 | float translateX = x + (radius * 2) * i + circleSpacing * i; 33 | canvas.translate(translateX, translateYFloats[i]); 34 | canvas.drawCircle(0, 0, radius, paint); 35 | canvas.restore(); 36 | } 37 | } 38 | 39 | @Override 40 | public ArrayList onCreateAnimators() { 41 | ArrayList animators = new ArrayList<>(); 42 | float circleSpacing = 4; 43 | float radius = (getWidth() - circleSpacing * 2) / 6; 44 | int[] delays = new int[]{70, 140, 210}; 45 | for (int i = 0; i < 3; i++) { 46 | final int index = i; 47 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(getHeight() / 2, getHeight() / 2 - radius * 2, getHeight() / 2); 48 | scaleAnim.setDuration(600); 49 | scaleAnim.setRepeatCount(-1); 50 | scaleAnim.setStartDelay(delays[i]); 51 | addUpdateListener(scaleAnim, animation -> { 52 | translateYFloats[index] = (float) animation.getAnimatedValue(); 53 | postInvalidate(); 54 | }); 55 | animators.add(scaleAnim); 56 | } 57 | return animators; 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallRotateIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Matrix; 15 | import android.graphics.Paint; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/17. 21 | */ 22 | public class BallRotateIndicator extends Indicator { 23 | 24 | float scaleFloat = 0.5f; 25 | 26 | float degress; 27 | 28 | private Matrix mMatrix; 29 | 30 | public BallRotateIndicator() { 31 | mMatrix = new Matrix(); 32 | } 33 | 34 | @Override 35 | public void draw(Canvas canvas, Paint paint) { 36 | float radius = getWidth() / 10; 37 | float x = getWidth() / 2; 38 | float y = getHeight() / 2; 39 | 40 | /*mMatrix.preTranslate(-centerX(), -centerY()); 41 | mMatrix.preRotate(degress,centerX(),centerY()); 42 | mMatrix.postTranslate(centerX(), centerY()); 43 | canvas.concat(mMatrix);*/ 44 | 45 | canvas.rotate(degress, centerX(), centerY()); 46 | 47 | canvas.save(); 48 | canvas.translate(x - radius * 2 - radius, y); 49 | canvas.scale(scaleFloat, scaleFloat); 50 | canvas.drawCircle(0, 0, radius, paint); 51 | canvas.restore(); 52 | 53 | canvas.save(); 54 | canvas.translate(x, y); 55 | canvas.scale(scaleFloat, scaleFloat); 56 | canvas.drawCircle(0, 0, radius, paint); 57 | canvas.restore(); 58 | 59 | canvas.save(); 60 | canvas.translate(x + radius * 2 + radius, y); 61 | canvas.scale(scaleFloat, scaleFloat); 62 | canvas.drawCircle(0, 0, radius, paint); 63 | canvas.restore(); 64 | } 65 | 66 | @Override 67 | public ArrayList onCreateAnimators() { 68 | ArrayList animators = new ArrayList<>(); 69 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(0.5f, 1, 0.5f); 70 | scaleAnim.setDuration(1000); 71 | scaleAnim.setRepeatCount(-1); 72 | addUpdateListener(scaleAnim, animation -> { 73 | scaleFloat = (float) animation.getAnimatedValue(); 74 | postInvalidate(); 75 | }); 76 | 77 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360); 78 | addUpdateListener(rotateAnim, animation -> { 79 | degress = (float) animation.getAnimatedValue(); 80 | postInvalidate(); 81 | }); 82 | rotateAnim.setDuration(1000); 83 | rotateAnim.setRepeatCount(-1); 84 | 85 | animators.add(scaleAnim); 86 | animators.add(rotateAnim); 87 | return animators; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallScaleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallScaleIndicator extends Indicator { 23 | 24 | float scale = 1; 25 | int alpha = 255; 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | float circleSpacing = 4; 30 | paint.setAlpha(alpha); 31 | canvas.scale(scale, scale, getWidth() / 2, getHeight() / 2); 32 | paint.setAlpha(alpha); 33 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - circleSpacing, paint); 34 | } 35 | 36 | @Override 37 | public ArrayList onCreateAnimators() { 38 | ArrayList animators = new ArrayList<>(); 39 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1); 40 | scaleAnim.setInterpolator(new LinearInterpolator()); 41 | scaleAnim.setDuration(1000); 42 | scaleAnim.setRepeatCount(-1); 43 | addUpdateListener(scaleAnim, animation -> { 44 | scale = (float) animation.getAnimatedValue(); 45 | postInvalidate(); 46 | }); 47 | 48 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 0); 49 | alphaAnim.setInterpolator(new LinearInterpolator()); 50 | alphaAnim.setDuration(1000); 51 | alphaAnim.setRepeatCount(-1); 52 | addUpdateListener(alphaAnim, animation -> { 53 | alpha = (int) animation.getAnimatedValue(); 54 | postInvalidate(); 55 | }); 56 | animators.add(scaleAnim); 57 | animators.add(alphaAnim); 58 | return animators; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallScaleMultipleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallScaleMultipleIndicator extends Indicator { 23 | 24 | float[] scaleFloats = new float[]{1, 1, 1}; 25 | int[] alphaInts = new int[]{255, 255, 255}; 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | float circleSpacing = 4; 30 | for (int i = 0; i < 3; i++) { 31 | paint.setAlpha(alphaInts[i]); 32 | canvas.scale(scaleFloats[i], scaleFloats[i], getWidth() / 2, getHeight() / 2); 33 | canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - circleSpacing, paint); 34 | } 35 | } 36 | 37 | @Override 38 | public ArrayList onCreateAnimators() { 39 | ArrayList animators = new ArrayList<>(); 40 | long[] delays = new long[]{0, 200, 400}; 41 | for (int i = 0; i < 3; i++) { 42 | final int index = i; 43 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1); 44 | scaleAnim.setInterpolator(new LinearInterpolator()); 45 | scaleAnim.setDuration(1000); 46 | scaleAnim.setRepeatCount(-1); 47 | addUpdateListener(scaleAnim, animation -> { 48 | scaleFloats[index] = (float) animation.getAnimatedValue(); 49 | postInvalidate(); 50 | }); 51 | scaleAnim.setStartDelay(delays[i]); 52 | 53 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 0); 54 | alphaAnim.setInterpolator(new LinearInterpolator()); 55 | alphaAnim.setDuration(1000); 56 | alphaAnim.setRepeatCount(-1); 57 | addUpdateListener(alphaAnim, animation -> { 58 | alphaInts[index] = (int) animation.getAnimatedValue(); 59 | postInvalidate(); 60 | }); 61 | scaleAnim.setStartDelay(delays[i]); 62 | 63 | animators.add(scaleAnim); 64 | animators.add(alphaAnim); 65 | } 66 | return animators; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallScaleRippleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallScaleRippleIndicator extends BallScaleIndicator { 23 | 24 | 25 | @Override 26 | public void draw(Canvas canvas, Paint paint) { 27 | paint.setStyle(Paint.Style.STROKE); 28 | paint.setStrokeWidth(3); 29 | super.draw(canvas, paint); 30 | } 31 | 32 | @Override 33 | public ArrayList onCreateAnimators() { 34 | ArrayList animators = new ArrayList<>(); 35 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1); 36 | scaleAnim.setInterpolator(new LinearInterpolator()); 37 | scaleAnim.setDuration(1000); 38 | scaleAnim.setRepeatCount(-1); 39 | addUpdateListener(scaleAnim, animation -> { 40 | scale = (float) animation.getAnimatedValue(); 41 | postInvalidate(); 42 | }); 43 | 44 | ValueAnimator alphaAnim = ValueAnimator.ofInt(0, 255); 45 | alphaAnim.setInterpolator(new LinearInterpolator()); 46 | alphaAnim.setDuration(1000); 47 | alphaAnim.setRepeatCount(-1); 48 | addUpdateListener(alphaAnim, animation -> { 49 | alpha = (int) animation.getAnimatedValue(); 50 | postInvalidate(); 51 | }); 52 | 53 | animators.add(scaleAnim); 54 | animators.add(alphaAnim); 55 | return animators; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallScaleRippleMultipleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallScaleRippleMultipleIndicator extends BallScaleMultipleIndicator { 23 | 24 | 25 | @Override 26 | public void draw(Canvas canvas, Paint paint) { 27 | paint.setStyle(Paint.Style.STROKE); 28 | paint.setStrokeWidth(3); 29 | super.draw(canvas, paint); 30 | } 31 | 32 | @Override 33 | public ArrayList onCreateAnimators() { 34 | ArrayList animators = new ArrayList<>(); 35 | long[] delays = new long[]{0, 200, 400}; 36 | for (int i = 0; i < 3; i++) { 37 | final int index = i; 38 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1); 39 | scaleAnim.setInterpolator(new LinearInterpolator()); 40 | scaleAnim.setDuration(1000); 41 | scaleAnim.setRepeatCount(-1); 42 | addUpdateListener(scaleAnim, animation -> { 43 | scaleFloats[index] = (float) animation.getAnimatedValue(); 44 | postInvalidate(); 45 | }); 46 | scaleAnim.setStartDelay(delays[i]); 47 | 48 | ValueAnimator alphaAnim = ValueAnimator.ofInt(0, 255); 49 | scaleAnim.setInterpolator(new LinearInterpolator()); 50 | alphaAnim.setDuration(1000); 51 | alphaAnim.setRepeatCount(-1); 52 | addUpdateListener(alphaAnim, animation -> { 53 | alphaInts[index] = (int) animation.getAnimatedValue(); 54 | postInvalidate(); 55 | }); 56 | scaleAnim.setStartDelay(delays[i]); 57 | 58 | animators.add(scaleAnim); 59 | animators.add(alphaAnim); 60 | } 61 | return animators; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallSpinFadeLoaderIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/20. 20 | */ 21 | public class BallSpinFadeLoaderIndicator extends Indicator { 22 | 23 | public static final float SCALE = 1.0f; 24 | 25 | public static final int ALPHA = 255; 26 | 27 | float[] scaleFloats = new float[]{SCALE, SCALE, SCALE, SCALE, SCALE, SCALE, SCALE, SCALE}; 28 | 29 | int[] alphas = new int[]{ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA}; 30 | 31 | 32 | @Override 33 | public void draw(Canvas canvas, Paint paint) { 34 | float radius = getWidth() / 10; 35 | for (int i = 0; i < 8; i++) { 36 | canvas.save(); 37 | Point point = circleAt(getWidth(), getHeight(), getWidth() / 2 - radius, i * (Math.PI / 4)); 38 | canvas.translate(point.x, point.y); 39 | canvas.scale(scaleFloats[i], scaleFloats[i]); 40 | paint.setAlpha(alphas[i]); 41 | canvas.drawCircle(0, 0, radius, paint); 42 | canvas.restore(); 43 | } 44 | } 45 | 46 | @Override 47 | public ArrayList onCreateAnimators() { 48 | ArrayList animators = new ArrayList<>(); 49 | int[] delays = {0, 120, 240, 360, 480, 600, 720, 780, 840}; 50 | for (int i = 0; i < 8; i++) { 51 | final int index = i; 52 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.4f, 1); 53 | scaleAnim.setDuration(1000); 54 | scaleAnim.setRepeatCount(-1); 55 | scaleAnim.setStartDelay(delays[i]); 56 | addUpdateListener(scaleAnim, animation -> { 57 | scaleFloats[index] = (float) animation.getAnimatedValue(); 58 | postInvalidate(); 59 | }); 60 | 61 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 77, 255); 62 | alphaAnim.setDuration(1000); 63 | alphaAnim.setRepeatCount(-1); 64 | alphaAnim.setStartDelay(delays[i]); 65 | addUpdateListener(alphaAnim, animation -> { 66 | alphas[index] = (int) animation.getAnimatedValue(); 67 | postInvalidate(); 68 | }); 69 | animators.add(scaleAnim); 70 | animators.add(alphaAnim); 71 | } 72 | return animators; 73 | } 74 | 75 | /** 76 | * 圆O的圆心为(a,b),半径为R,点A与到X轴的为角α. 77 | * 则点A的坐标为(a+R*cosα,b+R*sinα) 78 | */ 79 | Point circleAt(int width, int height, float radius, double angle) { 80 | float x = (float) (width / 2 + radius * (Math.cos(angle))); 81 | float y = (float) (height / 2 + radius * (Math.sin(angle))); 82 | return new Point(x, y); 83 | } 84 | 85 | final class Point { 86 | public float x; 87 | public float y; 88 | 89 | public Point(float x, float y) { 90 | this.x = x; 91 | this.y = y; 92 | } 93 | } 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallTrianglePathIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallTrianglePathIndicator extends Indicator { 23 | 24 | float[] translateX = new float[3], translateY = new float[3]; 25 | 26 | @Override 27 | public void draw(Canvas canvas, Paint paint) { 28 | paint.setStrokeWidth(3); 29 | paint.setStyle(Paint.Style.STROKE); 30 | for (int i = 0; i < 3; i++) { 31 | canvas.save(); 32 | canvas.translate(translateX[i], translateY[i]); 33 | canvas.drawCircle(0, 0, getWidth() / 10, paint); 34 | canvas.restore(); 35 | } 36 | } 37 | 38 | @Override 39 | public ArrayList onCreateAnimators() { 40 | ArrayList animators = new ArrayList<>(); 41 | float startX = getWidth() / 5; 42 | float startY = getWidth() / 5; 43 | for (int i = 0; i < 3; i++) { 44 | final int index = i; 45 | ValueAnimator translateXAnim = ValueAnimator.ofFloat(getWidth() / 2, getWidth() - startX, startX, getWidth() / 2); 46 | if (i == 1) { 47 | translateXAnim = ValueAnimator.ofFloat(getWidth() - startX, startX, getWidth() / 2, getWidth() - startX); 48 | } else if (i == 2) { 49 | translateXAnim = ValueAnimator.ofFloat(startX, getWidth() / 2, getWidth() - startX, startX); 50 | } 51 | ValueAnimator translateYAnim = ValueAnimator.ofFloat(startY, getHeight() - startY, getHeight() - startY, startY); 52 | if (i == 1) { 53 | translateYAnim = ValueAnimator.ofFloat(getHeight() - startY, getHeight() - startY, startY, getHeight() - startY); 54 | } else if (i == 2) { 55 | translateYAnim = ValueAnimator.ofFloat(getHeight() - startY, startY, getHeight() - startY, getHeight() - startY); 56 | } 57 | 58 | translateXAnim.setDuration(2000); 59 | translateXAnim.setInterpolator(new LinearInterpolator()); 60 | translateXAnim.setRepeatCount(-1); 61 | addUpdateListener(translateXAnim, animation -> { 62 | translateX[index] = (float) animation.getAnimatedValue(); 63 | postInvalidate(); 64 | }); 65 | 66 | translateYAnim.setDuration(2000); 67 | translateYAnim.setInterpolator(new LinearInterpolator()); 68 | translateYAnim.setRepeatCount(-1); 69 | addUpdateListener(translateYAnim, animation -> { 70 | translateY[index] = (float) animation.getAnimatedValue(); 71 | postInvalidate(); 72 | }); 73 | 74 | animators.add(translateXAnim); 75 | animators.add(translateYAnim); 76 | } 77 | return animators; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallZigZagDeflectIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | 13 | import android.animation.ValueAnimator; 14 | import android.view.animation.LinearInterpolator; 15 | 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * Created by Jack on 2015/10/19. 20 | */ 21 | public class BallZigZagDeflectIndicator extends BallZigZagIndicator { 22 | 23 | 24 | @Override 25 | public ArrayList onCreateAnimators() { 26 | ArrayList animators = new ArrayList<>(); 27 | float startX = getWidth() / 6; 28 | float startY = getWidth() / 6; 29 | for (int i = 0; i < 2; i++) { 30 | final int index = i; 31 | ValueAnimator translateXAnim = ValueAnimator.ofFloat(startX, getWidth() - startX, startX, getWidth() - startX, startX); 32 | if (i == 1) { 33 | translateXAnim = ValueAnimator.ofFloat(getWidth() - startX, startX, getWidth() - startX, startX, getWidth() - startX); 34 | } 35 | ValueAnimator translateYAnim = ValueAnimator.ofFloat(startY, startY, getHeight() - startY, getHeight() - startY, startY); 36 | if (i == 1) { 37 | translateYAnim = ValueAnimator.ofFloat(getHeight() - startY, getHeight() - startY, startY, startY, getHeight() - startY); 38 | } 39 | 40 | translateXAnim.setDuration(2000); 41 | translateXAnim.setInterpolator(new LinearInterpolator()); 42 | translateXAnim.setRepeatCount(-1); 43 | addUpdateListener(translateXAnim, animation -> { 44 | translateX[index] = (float) animation.getAnimatedValue(); 45 | postInvalidate(); 46 | }); 47 | 48 | translateYAnim.setDuration(2000); 49 | translateYAnim.setInterpolator(new LinearInterpolator()); 50 | translateYAnim.setRepeatCount(-1); 51 | addUpdateListener(translateYAnim, animation -> { 52 | translateY[index] = (float) animation.getAnimatedValue(); 53 | postInvalidate(); 54 | }); 55 | 56 | animators.add(translateXAnim); 57 | animators.add(translateYAnim); 58 | } 59 | return animators; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/BallZigZagIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class BallZigZagIndicator extends Indicator { 23 | 24 | float[] translateX = new float[2], translateY = new float[2]; 25 | 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | for (int i = 0; i < 2; i++) { 30 | canvas.save(); 31 | canvas.translate(translateX[i], translateY[i]); 32 | canvas.drawCircle(0, 0, getWidth() / 10, paint); 33 | canvas.restore(); 34 | } 35 | } 36 | 37 | @Override 38 | public ArrayList onCreateAnimators() { 39 | ArrayList animators = new ArrayList<>(); 40 | float startX = getWidth() / 6; 41 | float startY = getWidth() / 6; 42 | for (int i = 0; i < 2; i++) { 43 | final int index = i; 44 | ValueAnimator translateXAnim = ValueAnimator.ofFloat(startX, getWidth() - startX, getWidth() / 2, startX); 45 | if (i == 1) { 46 | translateXAnim = ValueAnimator.ofFloat(getWidth() - startX, startX, getWidth() / 2, getWidth() - startX); 47 | } 48 | ValueAnimator translateYAnim = ValueAnimator.ofFloat(startY, startY, getHeight() / 2, startY); 49 | if (i == 1) { 50 | translateYAnim = ValueAnimator.ofFloat(getHeight() - startY, getHeight() - startY, getHeight() / 2, getHeight() - startY); 51 | } 52 | 53 | translateXAnim.setDuration(1000); 54 | translateXAnim.setInterpolator(new LinearInterpolator()); 55 | translateXAnim.setRepeatCount(-1); 56 | addUpdateListener(translateXAnim, animation -> { 57 | translateX[index] = (float) animation.getAnimatedValue(); 58 | postInvalidate(); 59 | }); 60 | 61 | translateYAnim.setDuration(1000); 62 | translateYAnim.setInterpolator(new LinearInterpolator()); 63 | translateYAnim.setRepeatCount(-1); 64 | addUpdateListener(translateYAnim, animation -> { 65 | translateY[index] = (float) animation.getAnimatedValue(); 66 | postInvalidate(); 67 | }); 68 | animators.add(translateXAnim); 69 | animators.add(translateYAnim); 70 | } 71 | return animators; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/CubeTransitionIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | import android.view.animation.LinearInterpolator; 17 | 18 | import java.util.ArrayList; 19 | 20 | /** 21 | * Created by Jack on 2015/10/18. 22 | */ 23 | public class CubeTransitionIndicator extends Indicator { 24 | 25 | float[] translateX = new float[2], translateY = new float[2]; 26 | float degrees, scaleFloat = 1.0f; 27 | 28 | @Override 29 | public void draw(Canvas canvas, Paint paint) { 30 | float rWidth = getWidth() / 5; 31 | float rHeight = getHeight() / 5; 32 | for (int i = 0; i < 2; i++) { 33 | canvas.save(); 34 | canvas.translate(translateX[i], translateY[i]); 35 | canvas.rotate(degrees); 36 | canvas.scale(scaleFloat, scaleFloat); 37 | RectF rectF = new RectF(-rWidth / 2, -rHeight / 2, rWidth / 2, rHeight / 2); 38 | canvas.drawRect(rectF, paint); 39 | canvas.restore(); 40 | } 41 | } 42 | 43 | @Override 44 | public ArrayList onCreateAnimators() { 45 | ArrayList animators = new ArrayList<>(); 46 | float startX = getWidth() / 5; 47 | float startY = getHeight() / 5; 48 | for (int i = 0; i < 2; i++) { 49 | final int index = i; 50 | translateX[index] = startX; 51 | ValueAnimator translationXAnim = ValueAnimator.ofFloat(startX, getWidth() - startX, getWidth() - startX, startX, startX); 52 | if (i == 1) { 53 | translationXAnim = ValueAnimator.ofFloat(getWidth() - startX, startX, startX, getWidth() - startX, getWidth() - startX); 54 | } 55 | translationXAnim.setInterpolator(new LinearInterpolator()); 56 | translationXAnim.setDuration(1600); 57 | translationXAnim.setRepeatCount(-1); 58 | translationXAnim.addUpdateListener(animation -> { 59 | translateX[index] = (float) animation.getAnimatedValue(); 60 | postInvalidate(); 61 | }); 62 | translateY[index] = startY; 63 | ValueAnimator translationYAnim = ValueAnimator.ofFloat(startY, startY, getHeight() - startY, getHeight() - startY, startY); 64 | if (i == 1) { 65 | translationYAnim = ValueAnimator.ofFloat(getHeight() - startY, getHeight() - startY, startY, startY, getHeight() - startY); 66 | } 67 | translationYAnim.setDuration(1600); 68 | translationYAnim.setInterpolator(new LinearInterpolator()); 69 | translationYAnim.setRepeatCount(-1); 70 | addUpdateListener(translationYAnim, animation -> { 71 | translateY[index] = (float) animation.getAnimatedValue(); 72 | postInvalidate(); 73 | }); 74 | 75 | animators.add(translationXAnim); 76 | animators.add(translationYAnim); 77 | } 78 | 79 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.5f, 1, 0.5f, 1); 80 | scaleAnim.setDuration(1600); 81 | scaleAnim.setInterpolator(new LinearInterpolator()); 82 | scaleAnim.setRepeatCount(-1); 83 | addUpdateListener(scaleAnim, animation -> { 84 | scaleFloat = (float) animation.getAnimatedValue(); 85 | postInvalidate(); 86 | }); 87 | 88 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360, 1.5f * 360, 2 * 360); 89 | rotateAnim.setDuration(1600); 90 | rotateAnim.setInterpolator(new LinearInterpolator()); 91 | rotateAnim.setRepeatCount(-1); 92 | addUpdateListener(rotateAnim, animation -> { 93 | degrees = (float) animation.getAnimatedValue(); 94 | postInvalidate(); 95 | }); 96 | 97 | animators.add(scaleAnim); 98 | animators.add(rotateAnim); 99 | return animators; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/Indicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Color; 15 | import android.graphics.ColorFilter; 16 | import android.graphics.Paint; 17 | import android.graphics.PixelFormat; 18 | import android.graphics.Rect; 19 | import android.graphics.drawable.Animatable; 20 | import android.graphics.drawable.Drawable; 21 | 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | 25 | /** 26 | * Created by Jack Wang on 2016/8/5. 27 | */ 28 | 29 | public abstract class Indicator extends Drawable implements Animatable { 30 | 31 | private HashMap mUpdateListeners = new HashMap<>(); 32 | 33 | private ArrayList mAnimators; 34 | private int alpha = 255; 35 | private static final Rect ZERO_BOUNDS_RECT = new Rect(); 36 | protected Rect drawBounds = ZERO_BOUNDS_RECT; 37 | 38 | private boolean mHasAnimators; 39 | 40 | private Paint mPaint = new Paint(); 41 | 42 | public Indicator() { 43 | mPaint.setColor(Color.WHITE); 44 | mPaint.setStyle(Paint.Style.FILL); 45 | mPaint.setAntiAlias(true); 46 | } 47 | 48 | public int getColor() { 49 | return mPaint.getColor(); 50 | } 51 | 52 | public void setColor(int color) { 53 | mPaint.setColor(color); 54 | } 55 | 56 | @Override 57 | public void setAlpha(int alpha) { 58 | this.alpha = alpha; 59 | } 60 | 61 | @Override 62 | public int getAlpha() { 63 | return alpha; 64 | } 65 | 66 | @Override 67 | public int getOpacity() { 68 | return PixelFormat.OPAQUE; 69 | } 70 | 71 | @Override 72 | public void setColorFilter(ColorFilter colorFilter) { 73 | 74 | } 75 | 76 | @Override 77 | public void draw(Canvas canvas) { 78 | draw(canvas, mPaint); 79 | } 80 | 81 | public abstract void draw(Canvas canvas, Paint paint); 82 | 83 | public abstract ArrayList onCreateAnimators(); 84 | 85 | @Override 86 | public void start() { 87 | ensureAnimators(); 88 | 89 | if (mAnimators == null) { 90 | return; 91 | } 92 | 93 | // If the animators has not ended, do nothing. 94 | if (isStarted()) { 95 | return; 96 | } 97 | startAnimators(); 98 | invalidateSelf(); 99 | } 100 | 101 | private void startAnimators() { 102 | for (int i = 0; i < mAnimators.size(); i++) { 103 | ValueAnimator animator = mAnimators.get(i); 104 | 105 | //when the animator restart , add the updateListener again because they 106 | // was removed by animator stop . 107 | ValueAnimator.AnimatorUpdateListener updateListener = mUpdateListeners.get(animator); 108 | if (updateListener != null) { 109 | animator.addUpdateListener(updateListener); 110 | } 111 | 112 | animator.start(); 113 | } 114 | } 115 | 116 | private void stopAnimators() { 117 | if (mAnimators != null) { 118 | for (ValueAnimator animator : mAnimators) { 119 | if (animator != null && animator.isStarted()) { 120 | animator.removeAllUpdateListeners(); 121 | animator.end(); 122 | } 123 | } 124 | } 125 | } 126 | 127 | private void ensureAnimators() { 128 | if (!mHasAnimators) { 129 | mAnimators = onCreateAnimators(); 130 | mHasAnimators = true; 131 | } 132 | } 133 | 134 | @Override 135 | public void stop() { 136 | stopAnimators(); 137 | } 138 | 139 | private boolean isStarted() { 140 | for (ValueAnimator animator : mAnimators) { 141 | return animator.isStarted(); 142 | } 143 | return false; 144 | } 145 | 146 | @Override 147 | public boolean isRunning() { 148 | for (ValueAnimator animator : mAnimators) { 149 | return animator.isRunning(); 150 | } 151 | return false; 152 | } 153 | 154 | /** 155 | * Your should use this to add AnimatorUpdateListener when 156 | * create animator , otherwise , animator doesn't work when 157 | * the animation restart . 158 | */ 159 | public void addUpdateListener(ValueAnimator animator, ValueAnimator.AnimatorUpdateListener updateListener) { 160 | mUpdateListeners.put(animator, updateListener); 161 | } 162 | 163 | @Override 164 | protected void onBoundsChange(Rect bounds) { 165 | super.onBoundsChange(bounds); 166 | setDrawBounds(bounds); 167 | } 168 | 169 | public void setDrawBounds(Rect drawBounds) { 170 | setDrawBounds(drawBounds.left, drawBounds.top, drawBounds.right, drawBounds.bottom); 171 | } 172 | 173 | public void setDrawBounds(int left, int top, int right, int bottom) { 174 | this.drawBounds = new Rect(left, top, right, bottom); 175 | } 176 | 177 | public void postInvalidate() { 178 | invalidateSelf(); 179 | } 180 | 181 | public Rect getDrawBounds() { 182 | return drawBounds; 183 | } 184 | 185 | public int getWidth() { 186 | return drawBounds.width(); 187 | } 188 | 189 | public int getHeight() { 190 | return drawBounds.height(); 191 | } 192 | 193 | public int centerX() { 194 | return drawBounds.centerX(); 195 | } 196 | 197 | public int centerY() { 198 | return drawBounds.centerY(); 199 | } 200 | 201 | public float exactCenterX() { 202 | return drawBounds.exactCenterX(); 203 | } 204 | 205 | public float exactCenterY() { 206 | return drawBounds.exactCenterY(); 207 | } 208 | 209 | } 210 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/LineScaleIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class LineScaleIndicator extends Indicator { 23 | 24 | public static final float SCALE = 1.0f; 25 | 26 | float[] scaleYFloats = new float[]{SCALE, SCALE, SCALE, SCALE, SCALE,}; 27 | 28 | @Override 29 | public void draw(Canvas canvas, Paint paint) { 30 | float translateX = getWidth() / 11; 31 | float translateY = getHeight() / 2; 32 | for (int i = 0; i < 5; i++) { 33 | canvas.save(); 34 | canvas.translate((2 + i * 2) * translateX - translateX / 2, translateY); 35 | canvas.scale(SCALE, scaleYFloats[i]); 36 | RectF rectF = new RectF(-translateX / 2, -getHeight() / 2.5f, translateX / 2, getHeight() / 2.5f); 37 | canvas.drawRoundRect(rectF, 5, 5, paint); 38 | canvas.restore(); 39 | } 40 | } 41 | 42 | @Override 43 | public ArrayList onCreateAnimators() { 44 | ArrayList animators = new ArrayList<>(); 45 | long[] delays = new long[]{100, 200, 300, 400, 500}; 46 | for (int i = 0; i < 5; i++) { 47 | final int index = i; 48 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.4f, 1); 49 | scaleAnim.setDuration(1000); 50 | scaleAnim.setRepeatCount(-1); 51 | scaleAnim.setStartDelay(delays[i]); 52 | addUpdateListener(scaleAnim, animation -> { 53 | scaleYFloats[index] = (float) animation.getAnimatedValue(); 54 | postInvalidate(); 55 | }); 56 | animators.add(scaleAnim); 57 | } 58 | return animators; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/LineScalePartyIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/19. 21 | */ 22 | public class LineScalePartyIndicator extends Indicator { 23 | 24 | public static final float SCALE = 1.0f; 25 | 26 | float[] scaleFloats = new float[]{SCALE, SCALE, SCALE, SCALE, SCALE,}; 27 | 28 | @Override 29 | public void draw(Canvas canvas, Paint paint) { 30 | float translateX = getWidth() / 9; 31 | float translateY = getHeight() / 2; 32 | for (int i = 0; i < 4; i++) { 33 | canvas.save(); 34 | canvas.translate((2 + i * 2) * translateX - translateX / 2, translateY); 35 | canvas.scale(scaleFloats[i], scaleFloats[i]); 36 | RectF rectF = new RectF(-translateX / 2, -getHeight() / 2.5f, translateX / 2, getHeight() / 2.5f); 37 | canvas.drawRoundRect(rectF, 5, 5, paint); 38 | canvas.restore(); 39 | } 40 | } 41 | 42 | 43 | @Override 44 | public ArrayList onCreateAnimators() { 45 | ArrayList animators = new ArrayList<>(); 46 | long[] durations = new long[]{1260, 430, 1010, 730}; 47 | long[] delays = new long[]{770, 290, 280, 740}; 48 | for (int i = 0; i < 4; i++) { 49 | final int index = i; 50 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.4f, 1); 51 | scaleAnim.setDuration(durations[i]); 52 | scaleAnim.setRepeatCount(-1); 53 | scaleAnim.setStartDelay(delays[i]); 54 | addUpdateListener(scaleAnim, animation -> { 55 | scaleFloats[index] = (float) animation.getAnimatedValue(); 56 | postInvalidate(); 57 | }); 58 | animators.add(scaleAnim); 59 | } 60 | return animators; 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/LineScalePulseOutIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | 13 | import android.animation.ValueAnimator; 14 | 15 | import java.util.ArrayList; 16 | 17 | /** 18 | * Created by Jack on 2015/10/19. 19 | */ 20 | public class LineScalePulseOutIndicator extends LineScaleIndicator { 21 | 22 | @Override 23 | public ArrayList onCreateAnimators() { 24 | ArrayList animators = new ArrayList<>(); 25 | long[] delays = new long[]{500, 250, 0, 250, 500}; 26 | for (int i = 0; i < 5; i++) { 27 | final int index = i; 28 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.3f, 1); 29 | scaleAnim.setDuration(900); 30 | scaleAnim.setRepeatCount(-1); 31 | scaleAnim.setStartDelay(delays[i]); 32 | addUpdateListener(scaleAnim, animation -> { 33 | scaleYFloats[index] = (float) animation.getAnimatedValue(); 34 | postInvalidate(); 35 | }); 36 | animators.add(scaleAnim); 37 | } 38 | return animators; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/LineScalePulseOutRapidIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | 13 | import android.animation.ValueAnimator; 14 | 15 | import java.util.ArrayList; 16 | 17 | /** 18 | * Created by Jack on 2015/10/19. 19 | */ 20 | public class LineScalePulseOutRapidIndicator extends LineScaleIndicator { 21 | 22 | @Override 23 | public ArrayList onCreateAnimators() { 24 | ArrayList animators = new ArrayList<>(); 25 | long[] delays = new long[]{400, 200, 0, 200, 400}; 26 | for (int i = 0; i < 5; i++) { 27 | final int index = i; 28 | ValueAnimator scaleAnim = ValueAnimator.ofFloat(1, 0.4f, 1); 29 | scaleAnim.setDuration(1000); 30 | scaleAnim.setRepeatCount(-1); 31 | scaleAnim.setStartDelay(delays[i]); 32 | addUpdateListener(scaleAnim, animation -> { 33 | scaleYFloats[index] = (float) animation.getAnimatedValue(); 34 | postInvalidate(); 35 | }); 36 | animators.add(scaleAnim); 37 | } 38 | return animators; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/LineSpinFadeLoaderIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.graphics.Canvas; 13 | import android.graphics.Paint; 14 | import android.graphics.RectF; 15 | 16 | /** 17 | * Created by Jack on 2015/10/24. 18 | * Email:81813780@qq.com 19 | */ 20 | public class LineSpinFadeLoaderIndicator extends BallSpinFadeLoaderIndicator { 21 | 22 | 23 | @Override 24 | public void draw(Canvas canvas, Paint paint) { 25 | float radius = getWidth() / 10; 26 | for (int i = 0; i < 8; i++) { 27 | canvas.save(); 28 | Point point = circleAt(getWidth(), getHeight(), getWidth() / 2.5f - radius, i * (Math.PI / 4)); 29 | canvas.translate(point.x, point.y); 30 | canvas.scale(scaleFloats[i], scaleFloats[i]); 31 | canvas.rotate(i * 45); 32 | paint.setAlpha(alphas[i]); 33 | RectF rectF = new RectF(-radius, -radius / 1.5f, 1.5f * radius, radius / 1.5f); 34 | canvas.drawRoundRect(rectF, 5, 5, paint); 35 | canvas.restore(); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/PacmanIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | import android.view.animation.LinearInterpolator; 17 | 18 | import java.util.ArrayList; 19 | 20 | /** 21 | * Created by Jack on 2015/10/16. 22 | */ 23 | public class PacmanIndicator extends Indicator { 24 | 25 | private float translateX; 26 | 27 | private int alpha; 28 | 29 | private float degrees1, degrees2; 30 | 31 | @Override 32 | public void draw(Canvas canvas, Paint paint) { 33 | drawPacman(canvas, paint); 34 | drawCircle(canvas, paint); 35 | } 36 | 37 | private void drawPacman(Canvas canvas, Paint paint) { 38 | float x = getWidth() / 2; 39 | float y = getHeight() / 2; 40 | 41 | canvas.save(); 42 | 43 | canvas.translate(x, y); 44 | canvas.rotate(degrees1); 45 | paint.setAlpha(255); 46 | RectF rectF1 = new RectF(-x / 1.7f, -y / 1.7f, x / 1.7f, y / 1.7f); 47 | canvas.drawArc(rectF1, 0, 270, true, paint); 48 | 49 | canvas.restore(); 50 | 51 | canvas.save(); 52 | canvas.translate(x, y); 53 | canvas.rotate(degrees2); 54 | paint.setAlpha(255); 55 | RectF rectF2 = new RectF(-x / 1.7f, -y / 1.7f, x / 1.7f, y / 1.7f); 56 | canvas.drawArc(rectF2, 90, 270, true, paint); 57 | canvas.restore(); 58 | } 59 | 60 | 61 | private void drawCircle(Canvas canvas, Paint paint) { 62 | float radius = getWidth() / 11; 63 | paint.setAlpha(alpha); 64 | canvas.drawCircle(translateX, getHeight() / 2, radius, paint); 65 | } 66 | 67 | @Override 68 | public ArrayList onCreateAnimators() { 69 | ArrayList animators = new ArrayList<>(); 70 | float startT = getWidth() / 11; 71 | ValueAnimator translationAnim = ValueAnimator.ofFloat(getWidth() - startT, getWidth() / 2); 72 | translationAnim.setDuration(650); 73 | translationAnim.setInterpolator(new LinearInterpolator()); 74 | translationAnim.setRepeatCount(-1); 75 | addUpdateListener(translationAnim, animation -> { 76 | translateX = (float) animation.getAnimatedValue(); 77 | postInvalidate(); 78 | }); 79 | 80 | ValueAnimator alphaAnim = ValueAnimator.ofInt(255, 122); 81 | alphaAnim.setDuration(650); 82 | alphaAnim.setRepeatCount(-1); 83 | addUpdateListener(alphaAnim, animation -> { 84 | alpha = (int) animation.getAnimatedValue(); 85 | postInvalidate(); 86 | }); 87 | 88 | ValueAnimator rotateAnim1 = ValueAnimator.ofFloat(0, 45, 0); 89 | rotateAnim1.setDuration(650); 90 | rotateAnim1.setRepeatCount(-1); 91 | addUpdateListener(rotateAnim1, animation -> { 92 | degrees1 = (float) animation.getAnimatedValue(); 93 | postInvalidate(); 94 | }); 95 | 96 | ValueAnimator rotateAnim2 = ValueAnimator.ofFloat(0, -45, 0); 97 | rotateAnim2.setDuration(650); 98 | rotateAnim2.setRepeatCount(-1); 99 | addUpdateListener(rotateAnim2, animation -> { 100 | degrees2 = (float) animation.getAnimatedValue(); 101 | postInvalidate(); 102 | }); 103 | 104 | animators.add(translationAnim); 105 | animators.add(alphaAnim); 106 | animators.add(rotateAnim1); 107 | animators.add(rotateAnim2); 108 | return animators; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/SemiCircleSpinIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Canvas; 14 | import android.graphics.Paint; 15 | import android.graphics.RectF; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Jack on 2015/10/20. 21 | */ 22 | public class SemiCircleSpinIndicator extends Indicator { 23 | 24 | private float degress; 25 | 26 | @Override 27 | public void draw(Canvas canvas, Paint paint) { 28 | canvas.rotate(degress, centerX(), centerY()); 29 | RectF rectF = new RectF(0, 0, getWidth(), getHeight()); 30 | canvas.drawArc(rectF, -60, 120, false, paint); 31 | } 32 | 33 | @Override 34 | public ArrayList onCreateAnimators() { 35 | ArrayList animators = new ArrayList<>(); 36 | ValueAnimator rotateAnim = ValueAnimator.ofFloat(0, 180, 360); 37 | addUpdateListener(rotateAnim, animation -> { 38 | degress = (float) animation.getAnimatedValue(); 39 | postInvalidate(); 40 | }); 41 | rotateAnim.setDuration(600); 42 | rotateAnim.setRepeatCount(-1); 43 | animators.add(rotateAnim); 44 | return animators; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/SquareSpinIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Camera; 14 | import android.graphics.Canvas; 15 | import android.graphics.Matrix; 16 | import android.graphics.Paint; 17 | import android.graphics.RectF; 18 | import android.view.animation.LinearInterpolator; 19 | 20 | import java.util.ArrayList; 21 | 22 | /** 23 | * Created by Jack on 2015/10/16. 24 | */ 25 | public class SquareSpinIndicator extends Indicator { 26 | 27 | private float rotateX; 28 | private float rotateY; 29 | 30 | private Camera mCamera; 31 | private Matrix mMatrix; 32 | 33 | public SquareSpinIndicator() { 34 | mCamera = new Camera(); 35 | mMatrix = new Matrix(); 36 | } 37 | 38 | @Override 39 | public void draw(Canvas canvas, Paint paint) { 40 | 41 | mMatrix.reset(); 42 | mCamera.save(); 43 | mCamera.rotateX(rotateX); 44 | mCamera.rotateY(rotateY); 45 | mCamera.getMatrix(mMatrix); 46 | mCamera.restore(); 47 | 48 | mMatrix.preTranslate(-centerX(), -centerY()); 49 | mMatrix.postTranslate(centerX(), centerY()); 50 | canvas.concat(mMatrix); 51 | 52 | canvas.drawRect(new RectF(getWidth() / 5, getHeight() / 5, getWidth() * 4 / 5, getHeight() * 4 / 5), paint); 53 | } 54 | 55 | @Override 56 | public ArrayList onCreateAnimators() { 57 | ArrayList animators = new ArrayList<>(); 58 | ValueAnimator animator = ValueAnimator.ofFloat(0, 180, 180, 0, 0); 59 | addUpdateListener(animator, animation -> { 60 | rotateX = (float) animation.getAnimatedValue(); 61 | postInvalidate(); 62 | }); 63 | animator.setInterpolator(new LinearInterpolator()); 64 | animator.setRepeatCount(-1); 65 | animator.setDuration(2500); 66 | 67 | ValueAnimator animator1 = ValueAnimator.ofFloat(0, 0, 180, 180, 0); 68 | addUpdateListener(animator1, animation -> { 69 | rotateY = (float) animation.getAnimatedValue(); 70 | postInvalidate(); 71 | }); 72 | animator1.setInterpolator(new LinearInterpolator()); 73 | animator1.setRepeatCount(-1); 74 | animator1.setDuration(2500); 75 | 76 | animators.add(animator); 77 | animators.add(animator1); 78 | return animators; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/java/com/zcolin/gui/pullrecyclerview/progressindicator/indicators/TriangleSkewSpinIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | package com.zcolin.gui.pullrecyclerview.progressindicator.indicators; 11 | 12 | import android.animation.ValueAnimator; 13 | import android.graphics.Camera; 14 | import android.graphics.Canvas; 15 | import android.graphics.Matrix; 16 | import android.graphics.Paint; 17 | import android.graphics.Path; 18 | import android.view.animation.LinearInterpolator; 19 | 20 | import java.util.ArrayList; 21 | 22 | /** 23 | * Created by Jack on 2015/10/20. 24 | */ 25 | public class TriangleSkewSpinIndicator extends Indicator { 26 | 27 | private float rotateX; 28 | private float rotateY; 29 | 30 | private Camera mCamera; 31 | private Matrix mMatrix; 32 | 33 | public TriangleSkewSpinIndicator() { 34 | mCamera = new Camera(); 35 | mMatrix = new Matrix(); 36 | } 37 | 38 | @Override 39 | public void draw(Canvas canvas, Paint paint) { 40 | 41 | 42 | mMatrix.reset(); 43 | mCamera.save(); 44 | mCamera.rotateX(rotateX); 45 | mCamera.rotateY(rotateY); 46 | mCamera.getMatrix(mMatrix); 47 | mCamera.restore(); 48 | 49 | mMatrix.preTranslate(-centerX(), -centerY()); 50 | mMatrix.postTranslate(centerX(), centerY()); 51 | canvas.concat(mMatrix); 52 | 53 | Path path = new Path(); 54 | path.moveTo(getWidth() / 5, getHeight() * 4 / 5); 55 | path.lineTo(getWidth() * 4 / 5, getHeight() * 4 / 5); 56 | path.lineTo(getWidth() / 2, getHeight() / 5); 57 | path.close(); 58 | canvas.drawPath(path, paint); 59 | } 60 | 61 | @Override 62 | public ArrayList onCreateAnimators() { 63 | ArrayList animators = new ArrayList<>(); 64 | ValueAnimator animator = ValueAnimator.ofFloat(0, 180, 180, 0, 0); 65 | addUpdateListener(animator, animation -> { 66 | rotateX = (float) animation.getAnimatedValue(); 67 | postInvalidate(); 68 | }); 69 | animator.setInterpolator(new LinearInterpolator()); 70 | animator.setRepeatCount(-1); 71 | animator.setDuration(2500); 72 | 73 | ValueAnimator animator1 = ValueAnimator.ofFloat(0, 0, 180, 180, 0); 74 | addUpdateListener(animator1, animation -> { 75 | rotateY = (float) animation.getAnimatedValue(); 76 | postInvalidate(); 77 | }); 78 | animator1.setInterpolator(new LinearInterpolator()); 79 | animator1.setRepeatCount(-1); 80 | animator1.setDuration(2500); 81 | 82 | animators.add(animator); 83 | animators.add(animator1); 84 | return animators; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/drawable-xhdpi/gui_ic_pullrecyclerview_loading_rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/libPullRecyclerView/src/main/res/drawable-xhdpi/gui_ic_pullrecyclerview_loading_rotate.png -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/drawable-xhdpi/gui_ic_pullrecyclerview_pulltorefresh_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/libPullRecyclerView/src/main/res/drawable-xhdpi/gui_ic_pullrecyclerview_pulltorefresh_arrow.png -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/layout/gui_pullrecyclerview_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 23 | 24 | 31 | 32 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/layout/gui_pullrecyclerview_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 31 | 32 | 37 | 38 | 43 | 44 | 49 | 50 | 55 | 56 | 57 | 58 | 67 | 68 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/values/gui_zrecycler_view_attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/values/gui_zrecycler_view_ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /libPullRecyclerView/src/main/res/values/gui_zrecycler_view_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 20 | 21 | 28 | 29 | 36 | 37 | -------------------------------------------------------------------------------- /screenshot/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/screenshot/1.gif -------------------------------------------------------------------------------- /screenshot/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/PullRecyclerView/ec3a31489769d8c0f3935a928f4aef03fc5eab16/screenshot/2.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * ********************************************************* 3 | * author colin 4 | * company telchina 5 | * email wanglin2046@126.com 6 | * date 18-1-9 下午3:05 7 | * ******************************************************** 8 | */ 9 | 10 | 11 | 12 | 13 | 14 | include ':app', ':libPullRecyclerView' --------------------------------------------------------------------------------