├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── CBPullRefresh
├── .gitignore
├── CBPullRefresh.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── zhl
│ │ └── CBPullRefresh
│ │ ├── CBPullRefreshListView.java
│ │ ├── CBRefreshFooter.java
│ │ ├── CBRefreshHeader.java
│ │ ├── CBRefreshHeaderView.java
│ │ ├── CBRefreshState.java
│ │ ├── CBRefreshTopSearchView.java
│ │ ├── SwipeMenu
│ │ ├── SwipeMenu.java
│ │ ├── SwipeMenuAdapter.java
│ │ ├── SwipeMenuCreator.java
│ │ ├── SwipeMenuItem.java
│ │ ├── SwipeMenuLayout.java
│ │ └── SwipeMenuView.java
│ │ ├── titanic
│ │ ├── Titanic.java
│ │ └── TitanicTextView.java
│ │ └── utils
│ │ ├── Blur.java
│ │ ├── BlurUtil.java
│ │ ├── TimeType.java
│ │ └── Utils.java
│ └── res
│ ├── drawable-hdpi
│ ├── top_search_bar.png
│ └── top_search_bar_night.png
│ ├── drawable-nodpi
│ └── wave.png
│ ├── drawable-xhdpi
│ ├── icon_header_refresh.png
│ ├── top_pull_refresh_arrow.png
│ └── top_search_bar.png
│ ├── drawable
│ └── footer_bg_selector.xml
│ ├── layout
│ ├── cblistview_footer.xml
│ ├── cblistview_header.xml
│ └── cbpullrefrsh_topsearch.xml
│ ├── menu
│ └── menu_main.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ └── strings.xml
├── CBPullRefreshListView.iml
├── GIF1.gif
├── GIF2.gif
├── GIF3.gif
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zhl
│ │ └── cbpullrefreshlistview
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── zhl
│ │ └── cbpullrefreshlistview
│ │ ├── BaseActivity.java
│ │ ├── CustomRefreshHeaderActivity.java
│ │ ├── CustomRefreshHeaderRippleActivity.java
│ │ ├── DragBackLayout.java
│ │ ├── DragbackActivity.java
│ │ ├── MainActivity.java
│ │ ├── MyCustomRrefreshHeader.java
│ │ └── MyCustomRrefreshHeaderRippleColor.java
│ └── res
│ ├── drawable-hdpi
│ ├── app_logo_icon.png
│ └── item_icon_girl.png
│ ├── drawable-xhdpi
│ ├── app_logo_icon.png
│ ├── icon_collection.png
│ ├── icon_delete.png
│ ├── icon_header_refresh.png
│ ├── item_icon_girl.png
│ ├── item_icon_girl2.png
│ ├── item_icon_girl3.png
│ └── top_header_bg.jpg
│ ├── drawable
│ └── swipeback_shadow.xml
│ ├── layout
│ ├── activity_custom_header_layout.xml
│ ├── activity_custom_header_layout_ripple.xml
│ ├── activity_main.xml
│ ├── base.xml
│ ├── item_listview.xml
│ ├── item_listview2.xml
│ ├── item_listview3.xml
│ ├── my_custom_header.xml
│ ├── my_custom_header_ripplecolor.xml
│ └── mylistview_footer.xml
│ ├── menu
│ └── menu_main.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── custom_ripple.gif
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | CBPullRefreshListView
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CBPullRefresh/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/CBPullRefresh/CBPullRefresh.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/CBPullRefresh/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | group='com.github.yilylong'
5 | android {
6 | compileSdkVersion 25
7 | buildToolsVersion "25.0.0"
8 |
9 | defaultConfig {
10 | minSdkVersion 14
11 | targetSdkVersion 23
12 | versionCode 1
13 | versionName "1.0.0"
14 | renderscriptTargetApi 20
15 | renderscriptSupportModeEnabled true
16 | ndk {
17 | abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
18 | }
19 | }
20 | lintOptions {
21 | abortOnError false
22 | }
23 | buildTypes {
24 | release {
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 | }
30 |
31 | dependencies {
32 | compile fileTree(dir: 'libs', include: ['*.jar'])
33 | compile 'com.android.support:appcompat-v7:25.0.0'
34 | compile 'com.android.support:support-v4:25.0.0'
35 | }
36 |
37 |
38 |
--------------------------------------------------------------------------------
/CBPullRefresh/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:\WORK\Android\AndroidSDK/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 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBPullRefreshListView.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.support.v4.view.GestureDetectorCompat;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.GestureDetector;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.ViewConfiguration;
13 | import android.view.ViewTreeObserver.OnGlobalLayoutListener;
14 | import android.view.animation.DecelerateInterpolator;
15 | import android.view.animation.Interpolator;
16 | import android.widget.AbsListView;
17 | import android.widget.AbsListView.OnScrollListener;
18 | import android.widget.AdapterView;
19 | import android.widget.ListAdapter;
20 | import android.widget.ListView;
21 | import android.widget.Scroller;
22 |
23 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenu;
24 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuAdapter;
25 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuCreator;
26 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuLayout;
27 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuView;
28 | import com.zhl.CBPullRefresh.utils.Utils;
29 |
30 | import java.text.SimpleDateFormat;
31 | import java.util.Date;
32 |
33 |
34 | public class CBPullRefreshListView extends ListView implements OnScrollListener {
35 | private static final int TOUCH_STATE_NONE = 0;
36 | private static final int TOUCH_STATE_X = 1;
37 | private static final int TOUCH_STATE_Y = 2;
38 | private float mLastY = -1; // save event y
39 | private Scroller mScroller; // used for scroll back
40 | private OnScrollListener mScrollListener; // user's scroll listener
41 | // the interface to trigger refresh and load more.
42 | private OnPullRefreshListener mPullRefreshListener;
43 | private int headersCount;
44 | // -- header view
45 | private CBRefreshHeaderView mHeaderView;
46 | // -- footer view
47 | private CBRefreshHeaderView mFooterView;
48 | private int mHeaderViewHeight; // header view's height
49 | private boolean mEnablePullRefresh = true;
50 |
51 | private boolean mPullRefreshing = false; // is refreashing.
52 | private boolean mEnablePullLoad;
53 | private boolean mPullLoading;// isLoading
54 | private boolean mIsFooterReady = false;
55 | // total list items, used to detect is at the bottom of listview.
56 | private int mTotalItemCount = 0;
57 | // for mScroller, scroll back from header or footer.
58 | private int mScrollBack;
59 | private final static int SCROLLBACK_HEADER = 0;
60 | private final static int SCROLLBACK_FOOTER = 1;
61 | private final static int SCROLL_DURATION = 200; // scroll back duration
62 | private final static int PULL_LOAD_MORE_DELTA = 150; // when pull up >= 150px
63 | private final static float OFFSET_RADIO = 2.3f; // support iOS like pull
64 | // feature.
65 | private boolean showTopSearchBar = false;
66 | private CBRefreshHeaderView topSearchView;
67 | private int topSearchBarHeight = 0;
68 | private OnSearchClickListener searchClickListener;
69 | private OnMenuItemClickListener mMenuItemClickListener;
70 | private SwipeMenuLayout mTouchView;
71 | private long refreshTime;
72 | private SwipeMenuCreator mMenuCreator;
73 | private Interpolator mSwipeInterpolator;
74 | private int mTouchPosition;
75 | private int mTouchState = TOUCH_STATE_NONE;
76 | private float mDownX;
77 | private float mDownY;
78 | private float disX, disY;
79 | private int MAX_Y = 5;
80 | private int MAX_X = 3;
81 | private OnSwipeListener mOnSwipeListener;
82 | private Context context;
83 | private boolean swipeEnable = false;
84 | private int touchSlop;
85 | private int MIN_FLING;
86 | private int MAX_VELOCITYX;
87 | private GestureDetectorCompat mGestureDetector;
88 | private GestureDetector.OnGestureListener mGestureListener;
89 | private boolean isFling;
90 |
91 | /**
92 | * @param context
93 | */
94 | public CBPullRefreshListView(Context context) {
95 | super(context);
96 | initWithContext(context);
97 | }
98 |
99 | public CBPullRefreshListView(Context context, AttributeSet attrs) {
100 | super(context, attrs);
101 | initWithContext(context);
102 | }
103 |
104 | public CBPullRefreshListView(Context context, AttributeSet attrs, int defStyle) {
105 | super(context, attrs, defStyle);
106 | initWithContext(context);
107 | }
108 |
109 | private void initWithContext(Context context) {
110 | this.context = context;
111 | touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
112 | MIN_FLING = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
113 | MAX_VELOCITYX = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
114 | mScroller = new Scroller(context, new DecelerateInterpolator());
115 | super.setOnScrollListener(this);
116 | // init header view
117 | mHeaderView = new CBRefreshHeader(context);
118 | addHeaderView(mHeaderView);
119 |
120 | // init header height
121 | initHeaderHeight();
122 |
123 | topSearchView = new CBRefreshTopSearchView(context);
124 | topSearchView.setOnClickListener(new OnClickListener() {
125 | @Override
126 | public void onClick(View v) {
127 | if (searchClickListener != null) {
128 | searchClickListener.onSearchBarClick();
129 | }
130 | }
131 | });
132 | addHeaderView(topSearchView);
133 | initTopsearchViewHeight();
134 |
135 | // init footer view
136 | mFooterView = new CBRefreshFooter(context);
137 | mFooterView.footerViewHide();
138 | mFooterView.setOnClickListener(null);
139 | // headerview and footer divider
140 | setHeaderDividersEnabled(false);
141 | mGestureListener = new GestureDetector.SimpleOnGestureListener() {
142 | @Override
143 | public boolean onDown(MotionEvent e) {
144 | isFling = false;
145 | return true;
146 | }
147 |
148 | @Override
149 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
150 | if(e1==null){
151 | return false;
152 | }
153 | if ((e1.getX() - e2.getX()) > MIN_FLING && velocityX < MAX_VELOCITYX) {
154 | isFling = true;
155 | }
156 | return super.onFling(e1, e2, velocityX, velocityY);
157 | }
158 | };
159 | mGestureDetector = new GestureDetectorCompat(getContext(), mGestureListener);
160 | }
161 |
162 | @Override
163 | public void addHeaderView(View v, Object data, boolean isSelectable) {
164 | super.addHeaderView(v, data, isSelectable);
165 | headersCount++;
166 | }
167 |
168 | private void initTopsearchViewHeight() {
169 | topSearchView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
170 | @Override
171 | public void onGlobalLayout() {
172 | topSearchBarHeight = topSearchView.getRealHeaderContentHeight();
173 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
174 | getViewTreeObserver().removeOnGlobalLayoutListener(this);
175 | } else {
176 | getViewTreeObserver().removeGlobalOnLayoutListener(this);
177 | }
178 | }
179 | });
180 | }
181 |
182 | private void initHeaderHeight() {
183 | mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
184 | @Override
185 | public void onGlobalLayout() {
186 | mHeaderViewHeight = mHeaderView.getRealHeaderContentHeight();
187 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
188 | getViewTreeObserver().removeOnGlobalLayoutListener(this);
189 | } else {
190 | getViewTreeObserver().removeGlobalOnLayoutListener(this);
191 | }
192 | }
193 | });
194 | }
195 |
196 | @Override
197 | public void setAdapter(ListAdapter adapter) {
198 | // ensure footer view is the last child view
199 | if (mIsFooterReady == false) {
200 | mIsFooterReady = true;
201 | addFooterView(mFooterView);
202 | setFooterDividersEnabled(false);
203 | }
204 | setHeaderDividersEnabled(false);
205 | setRefreshTime(null);
206 | // super.setAdapter(adapter);
207 | super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
208 | @Override
209 | public void createMenu(SwipeMenu menu) {
210 | if (mMenuCreator != null) {
211 | mMenuCreator.create(menu);
212 | }
213 | }
214 |
215 | @Override
216 | public void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {
217 | if (mMenuItemClickListener != null) {
218 | mMenuItemClickListener.onMenuItemClick(view.getPosition(), menu, index);
219 | }
220 | if (mTouchView != null) {
221 | mTouchView.smoothCloseMenu();
222 | }
223 | }
224 | });
225 | }
226 |
227 | /**
228 | * enable or disable pull down refresh feature.
229 | *
230 | * @param enable
231 | */
232 | public void setPullRefreshEnable(boolean enable) {
233 | mEnablePullRefresh = enable;
234 | mHeaderView.setPullRefreshEnable(mEnablePullRefresh);
235 | }
236 |
237 | public void setStyleChange(int state) {
238 | mHeaderView.onStyleChange(state);
239 | mFooterView.onStyleChange(state);
240 | }
241 |
242 | /**
243 | * enable or disable pull up load more feature.
244 | *
245 | * @param enable
246 | */
247 | public void setPullLoadMoreEnable(boolean enable) {
248 | mEnablePullLoad = enable;
249 | if (!mEnablePullLoad) {
250 | mFooterView.footerViewHide();
251 | mFooterView.setOnClickListener(null);
252 | } else {
253 | mPullLoading = false;
254 | mFooterView.footerViewShow();
255 | mFooterView.setState(CBRefreshState.STATE_PULL_UP_TO_LOADMORE);
256 | mFooterView.pullUpToLoadmore();
257 | mFooterView.setOnClickListener(new OnClickListener() {
258 | @Override
259 | public void onClick(View v) {
260 | startLoadMore();
261 | }
262 | });
263 | }
264 | }
265 |
266 | /**
267 | * set Swipe enable
268 | *
269 | * @param swipeEnable
270 | */
271 | public void setSwipeEnable(boolean swipeEnable) {
272 | this.swipeEnable = swipeEnable;
273 | }
274 |
275 | /**
276 | * stop refresh, reset header view.
277 | */
278 | public void stopRefresh() {
279 | if (mPullRefreshing == true) {
280 | mPullRefreshing = false;
281 | resetHeaderHeight();
282 | resetTopSearchBarHeight();
283 | mHeaderView.setState(CBRefreshState.STATE_PULL_TO_REFRESH);
284 | }
285 | }
286 |
287 |
288 | /**
289 | * stop load more, reset footer view.
290 | */
291 | public void stopLoadMore() {
292 | if (mPullLoading == true) {
293 | mPullLoading = false;
294 | mFooterView.pullUpToLoadmore();
295 | mFooterView.setState(CBRefreshState.STATE_PULL_UP_TO_LOADMORE);
296 | }
297 | }
298 |
299 | /**
300 | * set last refresh time
301 | *
302 | * @param time
303 | */
304 | @SuppressLint("SimpleDateFormat")
305 | public void setRefreshTime(String time) {
306 | if (null == time) {
307 | Date now = new Date();
308 | SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
309 | mHeaderView.setRefreshTime(dateFormat.format(now));
310 | } else {
311 | mHeaderView.setRefreshTime(time);
312 | }
313 | }
314 |
315 | /**
316 | * set refreshTIme
317 | *
318 | * @param time
319 | */
320 | public void setRefreshTime(long time) {
321 | if (time <= 0) {
322 | setRefreshTime(null);
323 | } else {
324 | refreshTime = time;
325 | setRefreshTime(Utils.getTimeDifferent(context, time));
326 | }
327 | }
328 |
329 | private void invokeOnScrolling() {
330 | if (mScrollListener instanceof OnXScrollListener) {
331 | OnXScrollListener l = (OnXScrollListener) mScrollListener;
332 | l.onXScrolling(this);
333 | }
334 | }
335 |
336 | private void updateHeaderHeight(float delta) {
337 | mHeaderView.setVisiableHeight((int) delta + mHeaderView.getVisiableHeight());
338 | if (mEnablePullRefresh && !mPullRefreshing) {
339 | if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
340 | mHeaderView.releaseToRefresh();
341 | mHeaderView.setState(CBRefreshState.STATE_RELEASE_TO_REFRESH);
342 | } else {
343 | mHeaderView.pullToRefresh();
344 | mHeaderView.setState(CBRefreshState.STATE_PULL_TO_REFRESH);
345 | }
346 | }
347 | setSelection(0); // scroll to top each time
348 | }
349 |
350 | /**
351 | * reset header view's height.
352 | */
353 | private void resetHeaderHeight() {
354 | int height = mHeaderView.getVisiableHeight();
355 | if (height == 0) // not visible.
356 | return;
357 | // refreshing and header isn't shown fully. do nothing.
358 | if (mPullRefreshing && height <= mHeaderViewHeight) {
359 | return;
360 | }
361 | int finalHeight = 0; // default: scroll back to dismiss header.
362 | // is refreshing, just scroll back to show all the header.
363 | if (mPullRefreshing && height > mHeaderViewHeight) {
364 | finalHeight = mHeaderViewHeight;
365 | }
366 | mScrollBack = SCROLLBACK_HEADER;
367 | mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION);
368 | // trigger computeScroll
369 | invalidate();
370 | }
371 |
372 | private void updateFooterHeight(float delta) {
373 | if (!mEnablePullLoad) {
374 | return;
375 | }
376 | int height = mFooterView.getLoadMorePullUpDistance() + (int) delta;
377 | if (mEnablePullLoad && !mPullLoading) {
378 | if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load more.
379 | mFooterView.releaseToLoadmore();
380 | mFooterView.setState(CBRefreshState.STATE_RELEASE_TO_LOADMORE);
381 | } else {
382 | mFooterView.pullUpToLoadmore();
383 | mFooterView.setState(CBRefreshState.STATE_PULL_UP_TO_LOADMORE);
384 | }
385 | }
386 | mFooterView.setLoadMorePullUpDistance(height);
387 |
388 | // setSelection(mTotalItemCount - 1); // scroll to bottom
389 | }
390 |
391 | private void resetFooterHeight() {
392 | int bottomMargin = mFooterView.getLoadMorePullUpDistance();
393 | if (bottomMargin > 0) {
394 | mScrollBack = SCROLLBACK_FOOTER;
395 | mScroller.startScroll(0, bottomMargin, 0, -bottomMargin, SCROLL_DURATION);
396 | invalidate();
397 | }
398 | }
399 |
400 | private void startLoadMore() {
401 | mPullLoading = true;
402 | mFooterView.onLoading();
403 | mFooterView.setState(CBRefreshState.STATE_REFRESHING);
404 | if (mPullRefreshListener != null) {
405 | mPullRefreshListener.onLoadMore();
406 | }
407 | }
408 |
409 | @Override
410 | public boolean onTouchEvent(MotionEvent ev) {
411 | mGestureDetector.onTouchEvent(ev);
412 | if (mLastY == -1) {
413 | mLastY = ev.getRawY();
414 | }
415 |
416 | switch (ev.getAction()) {
417 | case MotionEvent.ACTION_DOWN:
418 | Log.d("MyTag", "按下-x=" + ev.getX());
419 | mLastY = ev.getRawY();
420 | mDownX = ev.getX();
421 | mDownY = ev.getY();
422 | int oldPos = mTouchPosition;
423 | mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
424 | View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
425 | if (swipeEnable && mTouchView != null && (mTouchView.isOpen() || mTouchView.isActive()) && oldPos != mTouchPosition) {
426 | mTouchView.smoothCloseMenu();
427 | mTouchView = null;
428 | mTouchState = TOUCH_STATE_NONE;
429 | }
430 | if (view instanceof SwipeMenuLayout) {
431 | mTouchView = (SwipeMenuLayout) view;
432 | }
433 | break;
434 | case MotionEvent.ACTION_MOVE:
435 | Log.d("MyTag", "移动downx=" + mDownX);
436 | final float deltaY = ev.getRawY() - mLastY;
437 | mLastY = ev.getRawY();
438 | disX = ev.getX() - mDownX;
439 | disY = ev.getY() - mDownY;
440 |
441 | if (Math.abs(disX) > touchSlop && Math.abs(disX) > Math.abs(disY)) {// 左右滑动
442 | mTouchState = TOUCH_STATE_X;
443 | if (swipeEnable && mTouchView != null) {
444 | Log.d("MyTag", "侧滑菜单移动=" + disX);
445 | mTouchView.swipeMenuSlide(-(int) disX);
446 | if (mTouchView.isActive()) {
447 | return true;
448 | }
449 | }
450 | } else if (Math.abs(disY) > touchSlop && Math.abs(disY) > Math.abs(disX)) {// 上下滑动
451 | if ((swipeEnable && mTouchView != null && mTouchView.isOpen()) || (swipeEnable && mTouchView != null && mTouchView.isActive())) {
452 | mTouchView.smoothCloseMenu();
453 | mTouchView = null;
454 | mTouchState = TOUCH_STATE_NONE;
455 | }
456 | mTouchState = TOUCH_STATE_Y;
457 | if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
458 | if (showTopSearchBar && topSearchView.getVisiableHeight() < topSearchBarHeight) {
459 | updateTopSearchBarHeight(deltaY);
460 | } else {
461 | updateHeaderHeight(deltaY / OFFSET_RADIO);
462 | mHeaderView.onDragSlide((float) mHeaderView.getVisiableHeight() + Math.abs(deltaY / OFFSET_RADIO));
463 | invokeOnScrolling();
464 | }
465 |
466 | } else if (getLastVisiblePosition() == mTotalItemCount - 1 && (mFooterView.getLoadMorePullUpDistance() > 0 || deltaY < 0)) {// 上拉
467 | // last item, already pulled up or want to pull up.
468 | updateFooterHeight(-deltaY / OFFSET_RADIO);
469 | mFooterView.onDragSlide((float) mFooterView.getLoadMorePullUpDistance() + (-deltaY / OFFSET_RADIO));
470 | }
471 | }
472 | break;
473 | default:
474 | Log.d("MyTag", "抬起");
475 | mLastY = -1; // reset
476 | switch (mTouchState) {
477 | case TOUCH_STATE_X:
478 | if (swipeEnable && mTouchView != null) {
479 | mTouchView.swipeMenuFling(isFling, -(int) disX);
480 | if (mTouchView.isActive()) {
481 | return true;
482 | }
483 | }
484 | break;
485 | case TOUCH_STATE_Y:
486 | if (getFirstVisiblePosition() == 0) {
487 | // invoke refresh
488 | if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
489 | mPullRefreshing = true;
490 | mHeaderView.onRefreshing();
491 | mHeaderView.setState(CBRefreshState.STATE_REFRESHING);
492 | if (mPullRefreshListener != null) {
493 | mPullRefreshListener.onRefresh();
494 | mPullRefreshListener.onUpdateRefreshTime(System.currentTimeMillis());
495 | }
496 | setRefreshTime(System.currentTimeMillis());
497 | }
498 | resetHeaderHeight();
499 | } else if (getLastVisiblePosition() == mTotalItemCount - 1) {
500 | // invoke load more.
501 | if (mEnablePullLoad && mFooterView.getLoadMorePullUpDistance() > PULL_LOAD_MORE_DELTA) {
502 | startLoadMore();
503 | }
504 | resetFooterHeight();
505 | } else {
506 | resetTopSearchBarHeight();
507 | }
508 | break;
509 | }
510 | mTouchState = TOUCH_STATE_NONE;
511 | break;
512 | }
513 | return super.onTouchEvent(ev);
514 | }
515 |
516 |
517 | private void resetTopSearchBarHeight() {
518 | if (showTopSearchBar && topSearchView != null) {
519 | topSearchView.setVisiableHeight(0);
520 | }
521 | }
522 |
523 | public void setTopSearchBarHeight() {
524 | if (topSearchView != null) {
525 | topSearchView.setVisiableHeight(0);
526 | }
527 | }
528 |
529 | private void updateTopSearchBarHeight(float deltaY) {
530 | if (deltaY > 20) {
531 | topSearchView.setVisiableHeight(topSearchBarHeight);
532 | }
533 | }
534 |
535 | @Override
536 | public void computeScroll() {
537 | if (mScroller.computeScrollOffset()) {
538 | if (mScrollBack == SCROLLBACK_HEADER) {
539 | mHeaderView.setVisiableHeight(mScroller.getCurrY());
540 | mHeaderView.onDragSlide(mScroller.getCurrY());
541 | } else {
542 | mFooterView.setLoadMorePullUpDistance(mScroller.getCurrY());
543 | mFooterView.onDragSlide(mScroller.getCurrY());
544 | }
545 | postInvalidate();
546 | invokeOnScrolling();
547 | }
548 | super.computeScroll();
549 | }
550 |
551 | @Override
552 | public void setOnScrollListener(OnScrollListener l) {
553 | mScrollListener = l;
554 | }
555 |
556 | @Override
557 | public void onScrollStateChanged(AbsListView view, int scrollState) {
558 | if (mScrollListener != null) {
559 | mScrollListener.onScrollStateChanged(view, scrollState);
560 | }
561 | }
562 |
563 | @Override
564 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
565 | // send to user's listener
566 | mTotalItemCount = totalItemCount;
567 | if (mScrollListener != null) {
568 | mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
569 | }
570 | }
571 |
572 |
573 | /**
574 | * set the refresh header icon
575 | *
576 | * @param resName
577 | */
578 | public void setHeaderRefreshIcon(int resName) {
579 | if (mHeaderView != null) {
580 | mHeaderView.setHeaderIcon(resName);
581 | }
582 | }
583 |
584 | /**
585 | * set footer view background
586 | *
587 | * @param resName
588 | */
589 | public void setFooterBg(int resName) {
590 | if (mFooterView != null) {
591 | ((CBRefreshFooter) mFooterView).setFooterBg(resName);
592 | }
593 | }
594 |
595 | /**
596 | * set topsearchbar show or not
597 | *
598 | * @param show
599 | */
600 | public void showTopSearchBar(boolean show) {
601 | this.showTopSearchBar = show;
602 | }
603 |
604 | public void setOnPullRefreshListener(OnPullRefreshListener l) {
605 | mPullRefreshListener = l;
606 | }
607 |
608 | public void setOnItemClickListener(final OnItemClickListener listener) {
609 | this.setOnItemClickListener(new AbsListView.OnItemClickListener() {
610 | @Override
611 | public void onItemClick(AdapterView> parent, View view,
612 | int position, long id) {
613 | if (listener != null) {
614 | //must subtract the headers count
615 | listener.onItemClick(parent, view, position - headersCount, id);
616 | }
617 | }
618 | });
619 | }
620 |
621 | public void setOnSearchBarClickListener(OnSearchClickListener searchClickListener) {
622 | this.searchClickListener = searchClickListener;
623 | }
624 |
625 | /**
626 | * you can listen ListView.OnScrollListener or this one. it will invoke
627 | * onXScrolling when header/footer scroll back.
628 | */
629 | public interface OnXScrollListener extends OnScrollListener {
630 | public void onXScrolling(View view);
631 | }
632 |
633 | public void setTopSearchDrawable(int resid) {
634 | topSearchView.setHeaderIcon(resid);
635 | }
636 |
637 | public void setRefreshHeader(T header) {
638 | if (header == null) {
639 | return;
640 | }
641 | removeHeaderView(mHeaderView);
642 | headersCount--;
643 | removeHeaderView(topSearchView);
644 | headersCount--;
645 | mHeaderView = header;
646 | addHeaderView(mHeaderView);
647 | addHeaderView(topSearchView);
648 | initHeaderHeight();
649 | initTopsearchViewHeight();
650 | }
651 |
652 | public void setLoadMoreFooter(T footer) {
653 | if (footer == null) {
654 | return;
655 | }
656 | this.removeFooterView(mFooterView);
657 | this.mFooterView = footer;
658 | addFooterView(mFooterView);
659 | mFooterView.footerViewHide();
660 | mFooterView.setOnClickListener(null);
661 | }
662 |
663 | public void setTopSearchBar(T searchBar) {
664 | if (searchBar == null) {
665 | return;
666 | }
667 | this.removeFooterView(topSearchView);
668 | headersCount--;
669 | this.topSearchView = searchBar;
670 | addHeaderView(topSearchView);
671 | initTopsearchViewHeight();
672 | }
673 |
674 | /**
675 | * 返回当前触摸的item view
676 | *
677 | * @return
678 | */
679 | public SwipeMenuLayout getTouchView() {
680 | return mTouchView;
681 | }
682 |
683 | /**
684 | * swipe item is open?
685 | *
686 | * @return
687 | */
688 | public boolean isSwipeMenuOpen() {
689 | return mTouchView == null ? false : mTouchView.isOpen() || mTouchView.isActive();
690 | }
691 |
692 | public void setMenuCreator(SwipeMenuCreator menuCreator) {
693 | this.mMenuCreator = menuCreator;
694 | }
695 |
696 | public void setSwipeMenuInterpolator(Interpolator interpolator) {
697 | this.mSwipeInterpolator = interpolator;
698 | }
699 |
700 | public void setOnMenuItemClickListener(OnMenuItemClickListener itemClickListener) {
701 | this.mMenuItemClickListener = itemClickListener;
702 | }
703 |
704 | /**
705 | * the refresh listener
706 | */
707 | public interface OnPullRefreshListener {
708 | public void onRefresh();
709 |
710 | public void onLoadMore();
711 |
712 | public void onUpdateRefreshTime(long time);
713 | }
714 |
715 | public interface OnItemClickListener {
716 | public void onItemClick(AdapterView> parent, View view,
717 | int position, long id);
718 | }
719 |
720 | public interface OnSearchClickListener {
721 | public void onSearchBarClick();
722 | }
723 |
724 | public static interface OnMenuItemClickListener {
725 | void onMenuItemClick(int position, SwipeMenu menu, int index);
726 | }
727 |
728 | public static interface OnSwipeListener {
729 | void onSwipeStart(int position);
730 |
731 | void onSwipeEnd(int position);
732 | }
733 | }
734 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBRefreshFooter.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.LinearLayout;
8 | import android.widget.TextView;
9 |
10 |
11 |
12 | public class CBRefreshFooter extends CBRefreshHeaderView {
13 |
14 | private Context mContext;
15 | private View mContentView;
16 | private View mProgressBar;
17 | private TextView mHintView;
18 | private int state;
19 |
20 | public CBRefreshFooter(Context context) {
21 | super(context);
22 | initView(context);
23 | }
24 |
25 | public CBRefreshFooter(Context context, AttributeSet attrs) {
26 | super(context, attrs);
27 | initView(context);
28 | }
29 |
30 | @Override
31 | public void setState(int state) {
32 | this.state = state;
33 | }
34 |
35 | private void initView(Context context) {
36 | mContext = context;
37 | LinearLayout moreView = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.cblistview_footer, null);
38 | addView(moreView);
39 | moreView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
40 |
41 | mContentView = moreView.findViewById(R.id.cbrefresh_footer_content);
42 | mProgressBar = moreView.findViewById(R.id.cbrefresh_footer_progressbar);
43 | mHintView = (TextView) moreView.findViewById(R.id.cbrefresh_footer_hint_textview);
44 | }
45 |
46 | /**
47 | * set the footer bg
48 | *
49 | * @param resName
50 | */
51 | public void setFooterBg(int resName) {
52 | mContentView.setBackgroundResource(resName);
53 | }
54 |
55 | @Override
56 | public void pullUpToLoadmore() {
57 | mProgressBar.setVisibility(View.GONE);
58 | mHintView.setVisibility(View.VISIBLE);
59 | mHintView.setText(getString(R.string.refresh_footer_tip_pullup_loadmore));
60 | }
61 |
62 | @Override
63 | public void releaseToLoadmore() {
64 | mProgressBar.setVisibility(View.GONE);
65 | mHintView.setVisibility(View.VISIBLE);
66 | mHintView.setText(getString(R.string.refresh_footer_tip_release_loadmore));
67 | }
68 |
69 | @Override
70 | public void onLoading() {
71 | mProgressBar.setVisibility(View.VISIBLE);
72 | mHintView.setVisibility(View.VISIBLE);
73 | mHintView.setText(getString(R.string.refresh_footer_tip_loading));
74 | }
75 |
76 | @Override
77 | public void onStyleChange(int state) {
78 | super.onStyleChange(state);
79 | }
80 |
81 | @Override
82 | public int getLoadMorePullUpDistance() {
83 | LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
84 | return lp.bottomMargin;
85 | }
86 |
87 | @Override
88 | public void setLoadMorePullUpDistance(int deltaY) {
89 | if (deltaY < 0)
90 | return;
91 | LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
92 | lp.bottomMargin = deltaY;
93 | mContentView.setLayoutParams(lp);
94 | }
95 |
96 | @Override
97 | public void footerViewShow() {
98 | LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
99 | lp.height = LayoutParams.WRAP_CONTENT;
100 | mContentView.setLayoutParams(lp);
101 | }
102 |
103 | @Override
104 | public void footerViewHide() {
105 | LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
106 | lp.height = 0;
107 | mContentView.setLayoutParams(lp);
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBRefreshHeader.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.Gravity;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.animation.Animation;
9 | import android.view.animation.RotateAnimation;
10 | import android.widget.ImageView;
11 | import android.widget.LinearLayout;
12 | import android.widget.ProgressBar;
13 | import android.widget.RelativeLayout;
14 | import android.widget.TextView;
15 |
16 | import com.zhl.CBPullRefresh.titanic.Titanic;
17 | import com.zhl.CBPullRefresh.titanic.TitanicTextView;
18 |
19 |
20 | public class CBRefreshHeader extends CBRefreshHeaderView {
21 | private LinearLayout mContainer;
22 | private RelativeLayout mHeaderViewContent;
23 | private ImageView mArrowImageView;
24 | private ProgressBar mProgressBar;
25 | private TextView mHintTextView;
26 | private TextView mHeaderTimeView;
27 | // the curent state
28 | private int mState = STATE_PULL_TO_REFRESH;
29 | private Animation mRotateUpAnim;
30 | private Animation mRotateDownAnim;
31 | private final int ROTATE_ANIM_DURATION = 200;
32 | private TitanicTextView headrAnimView;
33 | private Titanic titanic;
34 |
35 |
36 | public CBRefreshHeader(Context context) {
37 | this(context, null);
38 | }
39 |
40 | /**
41 | * @param context
42 | * @param attrs
43 | */
44 | public CBRefreshHeader(Context context, AttributeSet attrs) {
45 | super(context, attrs);
46 | initView(context);
47 | }
48 |
49 | private void initView(Context context) {
50 | // in the first set the Header height=0
51 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
52 | mContainer = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.cblistview_header, null);
53 | mHeaderViewContent = (RelativeLayout) mContainer.findViewById(R.id.cbrefresh_header_content);
54 | mHeaderTimeView = (TextView) mContainer.findViewById(R.id.cbrefresh_header_time);
55 | addView(mContainer, lp);
56 | setGravity(Gravity.BOTTOM);
57 |
58 | mArrowImageView = (ImageView) findViewById(R.id.cbrefresh_header_arrow);
59 | mHintTextView = (TextView) findViewById(R.id.cbrefresh_header_hint_textview);
60 | mProgressBar = (ProgressBar) findViewById(R.id.cbrefresh_header_progressbar);
61 | headrAnimView = (TitanicTextView) findViewById(R.id.cbrefresh_header_anim);
62 | titanic = new Titanic();
63 | mRotateUpAnim = new RotateAnimation(0.0f, -180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
64 | mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
65 | mRotateUpAnim.setFillAfter(true);
66 | mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
67 | mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
68 | mRotateDownAnim.setFillAfter(true);
69 | }
70 |
71 | @Override
72 | public void setState(int state) {
73 | this.mState = state;
74 | }
75 |
76 | /**
77 | * @param resName
78 | */
79 | @Override
80 | public void setHeaderIcon(int resName) {
81 | mArrowImageView.setBackgroundResource(resName);
82 | }
83 |
84 | @Override
85 | public void pullToRefresh() {
86 | mHintTextView.setText(getString(R.string.refresh_header_tip_pull2refresh));
87 | mArrowImageView.setVisibility(View.VISIBLE);
88 | mProgressBar.setVisibility(View.INVISIBLE);
89 | if (mState == STATE_RELEASE_TO_REFRESH) {
90 | mArrowImageView.startAnimation(mRotateDownAnim);
91 | }
92 | if (mState == STATE_REFRESHING) {
93 | mArrowImageView.clearAnimation();
94 | }
95 | }
96 |
97 | @Override
98 | public void releaseToRefresh() {
99 | mHintTextView.setText(getString(R.string.refresh_header_tip_release2refresh));
100 | if (mState != STATE_RELEASE_TO_REFRESH) {
101 | mArrowImageView.clearAnimation();
102 | mArrowImageView.startAnimation(mRotateUpAnim);
103 | }
104 | }
105 |
106 | @Override
107 | public void onRefreshing() {
108 | mHintTextView.setText(getString(R.string.refresh_header_tip_refreshing));
109 | mArrowImageView.clearAnimation();
110 | mArrowImageView.setVisibility(View.INVISIBLE);
111 | mProgressBar.setVisibility(View.VISIBLE);
112 | }
113 |
114 | @Override
115 | public void onStyleChange(int state) {
116 | super.onStyleChange(state);
117 | }
118 |
119 | @Override
120 | public void setVisiableHeight(int height) {
121 | if (height < 0)
122 | height = 0;
123 | LayoutParams lp = (LayoutParams) mContainer.getLayoutParams();
124 | lp.height = height;
125 | mContainer.setLayoutParams(lp);
126 | }
127 |
128 | @Override
129 | public int getVisiableHeight() {
130 | return mContainer.getHeight();
131 | }
132 |
133 | @Override
134 | public int getRealHeaderContentHeight() {
135 | // beacuse container height =0 at the first ,so return mHeaderViewContent height
136 | if (mHeaderViewContent != null) {
137 | return mHeaderViewContent.getHeight();
138 | }
139 | return 0;
140 | }
141 |
142 | @Override
143 | public void setPullRefreshEnable(boolean enable) {
144 | if (!enable) { // disable, hide the content
145 | mHeaderViewContent.setVisibility(View.INVISIBLE);
146 | } else {
147 | mHeaderViewContent.setVisibility(View.VISIBLE);
148 | }
149 | }
150 |
151 | @Override
152 | public void setRefreshTime(String refreshTime) {
153 | mHeaderTimeView.setText(refreshTime);
154 | }
155 | }
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBRefreshHeaderView.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.LinearLayout;
6 |
7 | public class CBRefreshHeaderView extends LinearLayout implements CBRefreshState {
8 | private Context context;
9 | public CBRefreshHeaderView(Context context) {
10 | this(context, null);
11 | }
12 |
13 | public CBRefreshHeaderView(Context context, AttributeSet attrs) {
14 | this(context, attrs, -1);
15 | }
16 |
17 | public CBRefreshHeaderView(Context context, AttributeSet attrs,
18 | int defStyleAttr) {
19 | super(context, attrs, defStyleAttr);
20 | this.context = context;
21 | }
22 |
23 | /**
24 | * set the current state
25 | * @param state
26 | */
27 | @Override
28 | public void setState(int state) {
29 |
30 | }
31 |
32 | /**
33 | * pull to refresh listener
34 | */
35 | @Override
36 | public void pullToRefresh() {
37 |
38 | }
39 |
40 | /**
41 | * relase to fresh listener
42 | */
43 | @Override
44 | public void releaseToRefresh() {
45 |
46 | }
47 |
48 |
49 | /**
50 | * pull up to loadmore
51 | */
52 | @Override
53 | public void pullUpToLoadmore() {
54 |
55 | }
56 |
57 | /**
58 | * relase to loadmore
59 | */
60 | @Override
61 | public void releaseToLoadmore() {
62 |
63 | }
64 |
65 | /**
66 | * onrefreshing
67 | */
68 | @Override
69 | public void onRefreshing() {
70 |
71 | }
72 |
73 | /**
74 | * onloading
75 | */
76 | @Override
77 | public void onLoading() {
78 |
79 | }
80 |
81 | /**
82 | * set the header height
83 | * @param height
84 | */
85 | @Override
86 | public void setVisiableHeight(int height) {
87 |
88 | }
89 |
90 | /**
91 | * get the header visiable height
92 | * @return
93 | */
94 | @Override
95 | public int getVisiableHeight() {
96 | return 0;
97 | }
98 |
99 | /**
100 | * on draging
101 | * @param deltaY
102 | */
103 | @Override
104 | public void onDragSlide(float deltaY) {
105 |
106 | }
107 | /**
108 | * get the pull up(footer) height
109 | */
110 | @Override
111 | public int getLoadMorePullUpDistance() {
112 | return 0;
113 | }
114 | /**
115 | * set the pull up(footer) heith
116 | */
117 | @Override
118 | public void setLoadMorePullUpDistance(int deltaY) {
119 |
120 | }
121 | /**
122 | * show footerview
123 | */
124 | @Override
125 | public void footerViewShow() {
126 |
127 | }
128 | /**
129 | * hidden footer view
130 | */
131 | @Override
132 | public void footerViewHide() {
133 |
134 | }
135 | /**
136 | * get the header's real height
137 | */
138 | @Override
139 | public int getRealHeaderContentHeight() {
140 | return 0;
141 | }
142 | /**
143 | * set pull refresh enable
144 | */
145 | @Override
146 | public void setPullRefreshEnable(boolean enable) {
147 |
148 | }
149 | /**
150 | * set loadmore enable
151 | */
152 | @Override
153 | public void setLoadMoreEnable(boolean enable) {
154 |
155 | }
156 |
157 | /**
158 | * set the refresh time
159 | * @param refreshTime
160 | */
161 | @Override
162 | public void setRefreshTime(String refreshTime) {
163 |
164 | }
165 |
166 | /**
167 | * set the header icon
168 | * @param resId
169 | */
170 | @Override
171 | public void setHeaderIcon(int resId) {
172 |
173 | }
174 |
175 | /**
176 | * on style change
177 | * @param state
178 | */
179 | @Override
180 | public void onStyleChange(int state) {
181 |
182 | }
183 |
184 | protected String getString(int redID){
185 | return context.getString(redID);
186 | }
187 |
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBRefreshState.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | /**
4 | * 描述:刷新状态的接口
5 | * Created by zhaohl on 2016-3-22.
6 | */
7 | public interface CBRefreshState {
8 | /**
9 | * state pull to refresh
10 | */
11 | public final static int STATE_PULL_TO_REFRESH = 0;
12 | /**
13 | * state relase to refresh
14 | */
15 | public final static int STATE_RELEASE_TO_REFRESH = 1;
16 | /**
17 | * state on refreshing
18 | */
19 | public final static int STATE_REFRESHING = 2;
20 | /**
21 | * state pull to loadmore
22 | */
23 | public final static int STATE_PULL_UP_TO_LOADMORE = 3;
24 | /**
25 | * state relase to loadmore
26 | */
27 | public final static int STATE_RELEASE_TO_LOADMORE = 4;
28 |
29 | /**
30 | * set the state
31 | */
32 | public void setState(int state);
33 | public void pullToRefresh();
34 |
35 | public void releaseToRefresh();
36 |
37 | public void pullUpToLoadmore();
38 |
39 | public void releaseToLoadmore();
40 |
41 | public void onRefreshing();
42 |
43 | public void onLoading();
44 |
45 | public void setVisiableHeight(int height);
46 |
47 | public int getVisiableHeight();
48 |
49 | public void onDragSlide(float deltaY);
50 |
51 | public int getLoadMorePullUpDistance();
52 |
53 | public void setLoadMorePullUpDistance(int deltaY);
54 |
55 | public void footerViewShow();
56 |
57 | public void footerViewHide();
58 |
59 | public int getRealHeaderContentHeight();
60 |
61 | public void setPullRefreshEnable(boolean enable);
62 |
63 | public void setLoadMoreEnable(boolean enable);
64 |
65 | public void setRefreshTime(String refreshTime);
66 |
67 | public void setHeaderIcon(int resId);
68 |
69 | public void onStyleChange(int state);
70 | }
71 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/CBRefreshTopSearchView.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.widget.ImageView;
7 | import android.widget.LinearLayout;
8 |
9 |
10 | public class CBRefreshTopSearchView extends CBRefreshHeaderView {
11 | private LinearLayout container;
12 | private ImageView searchImg;
13 |
14 | public CBRefreshTopSearchView(Context context) {
15 | super(context);
16 | initView(context);
17 | }
18 |
19 | /**
20 | * @param context
21 | * @param attrs
22 | */
23 | public CBRefreshTopSearchView(Context context, AttributeSet attrs) {
24 | super(context, attrs);
25 | initView(context);
26 | }
27 |
28 | private void initView(Context context) {
29 | // in the first set the header's height = 0
30 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
31 | container = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.cbpullrefrsh_topsearch, null);
32 | searchImg = (ImageView) container.findViewById(R.id.pull2reresh_top_search);
33 | addView(container, lp);
34 | }
35 |
36 |
37 | @Override
38 | public void setVisiableHeight(int height) {
39 | if (height < 0)
40 | height = 0;
41 | LayoutParams lp = (LayoutParams) container.getLayoutParams();
42 | lp.height = height;
43 | container.setLayoutParams(lp);
44 | }
45 |
46 | public int getVisiableHeight() {
47 | return container.getHeight();
48 | }
49 |
50 | @Override
51 | public int getRealHeaderContentHeight() {
52 | return searchImg.getHeight();
53 | }
54 | }
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenu.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class SwipeMenu {
9 |
10 | private Context mContext;
11 | private List mItems;
12 | private int mViewType;
13 |
14 | public SwipeMenu(Context context) {
15 | mContext = context;
16 | mItems = new ArrayList();
17 | }
18 |
19 | public Context getContext() {
20 | return mContext;
21 | }
22 |
23 | public void addMenuItem(SwipeMenuItem item) {
24 | mItems.add(item);
25 | }
26 |
27 | public void removeMenuItem(SwipeMenuItem item) {
28 | mItems.remove(item);
29 | }
30 |
31 | public List getMenuItems() {
32 | return mItems;
33 | }
34 |
35 | public SwipeMenuItem getMenuItem(int index) {
36 | return mItems.get(index);
37 | }
38 |
39 | public int getViewType() {
40 | return mViewType;
41 | }
42 |
43 | public void setViewType(int viewType) {
44 | this.mViewType = viewType;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenuAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | import android.content.Context;
4 | import android.database.DataSetObserver;
5 | import android.graphics.Color;
6 | import android.graphics.drawable.ColorDrawable;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.view.animation.LinearInterpolator;
10 | import android.widget.ListAdapter;
11 | import android.widget.WrapperListAdapter;
12 |
13 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
14 |
15 |
16 | public class SwipeMenuAdapter implements WrapperListAdapter, SwipeMenuView.OnSwipeItemClickListener {
17 |
18 | private ListAdapter mAdapter;
19 | private Context mContext;
20 | private CBPullRefreshListView.OnMenuItemClickListener onMenuItemClickListener;
21 |
22 | public SwipeMenuAdapter(Context context, ListAdapter adapter) {
23 | mAdapter = adapter;
24 | mContext = context;
25 | }
26 |
27 | @Override
28 | public int getCount() {
29 | return mAdapter.getCount();
30 | }
31 |
32 | @Override
33 | public Object getItem(int position) {
34 | return mAdapter.getItem(position);
35 | }
36 |
37 | @Override
38 | public long getItemId(int position) {
39 | return mAdapter.getItemId(position);
40 | }
41 |
42 | @Override
43 | public View getView(int position, View convertView, ViewGroup parent) {
44 | SwipeMenuLayout layout = null;
45 | if (convertView == null) {
46 | View contentView = mAdapter.getView(position, convertView, parent);
47 | SwipeMenu menu = new SwipeMenu(mContext);
48 | menu.setViewType(mAdapter.getItemViewType(position));
49 | createMenu(menu);
50 | SwipeMenuView menuView = new SwipeMenuView(menu);
51 | menuView.setOnSwipeItemClickListener(this);
52 | // CBPullRefreshListView listView = (CBPullRefreshListView) parent;
53 | layout = new SwipeMenuLayout(contentView, menuView, new LinearInterpolator(),
54 | new LinearInterpolator());
55 | layout.setPosition(position);
56 | } else {
57 | layout = (SwipeMenuLayout) convertView;
58 | layout.closeMenu();
59 | layout.setPosition(position);
60 | mAdapter.getView(position, layout.getContentView(), parent);
61 | }
62 | return layout;
63 | }
64 |
65 | public void createMenu(SwipeMenu menu) {
66 | // Test Code
67 | SwipeMenuItem item = new SwipeMenuItem(mContext);
68 | item.setTitle("Item 1");
69 | item.setBackground(new ColorDrawable(Color.GRAY));
70 | item.setWidth(300);
71 | menu.addMenuItem(item);
72 |
73 | item = new SwipeMenuItem(mContext);
74 | item.setTitle("Item 2");
75 | item.setBackground(new ColorDrawable(Color.RED));
76 | item.setWidth(300);
77 | menu.addMenuItem(item);
78 | }
79 |
80 | @Override
81 | public void onItemClick(SwipeMenuView view, SwipeMenu menu, int index) {
82 | if (onMenuItemClickListener != null) {
83 | onMenuItemClickListener.onMenuItemClick(view.getPosition(), menu, index);
84 | }
85 | }
86 |
87 | public void setOnMenuItemClickListener(CBPullRefreshListView.OnMenuItemClickListener onMenuItemClickListener) {
88 | this.onMenuItemClickListener = onMenuItemClickListener;
89 | }
90 |
91 | @Override
92 | public void registerDataSetObserver(DataSetObserver observer) {
93 | mAdapter.registerDataSetObserver(observer);
94 | }
95 |
96 | @Override
97 | public void unregisterDataSetObserver(DataSetObserver observer) {
98 | mAdapter.unregisterDataSetObserver(observer);
99 | }
100 |
101 | @Override
102 | public boolean areAllItemsEnabled() {
103 | return mAdapter.areAllItemsEnabled();
104 | }
105 |
106 | @Override
107 | public boolean isEnabled(int position) {
108 | return mAdapter.isEnabled(position);
109 | }
110 |
111 | @Override
112 | public boolean hasStableIds() {
113 | return mAdapter.hasStableIds();
114 | }
115 |
116 | @Override
117 | public int getItemViewType(int position) {
118 | return mAdapter.getItemViewType(position);
119 | }
120 |
121 | @Override
122 | public int getViewTypeCount() {
123 | return mAdapter.getViewTypeCount();
124 | }
125 |
126 | @Override
127 | public boolean isEmpty() {
128 | return mAdapter.isEmpty();
129 | }
130 |
131 | @Override
132 | public ListAdapter getWrappedAdapter() {
133 | return mAdapter;
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenuCreator.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | public interface SwipeMenuCreator {
4 |
5 | void create(SwipeMenu menu);
6 | }
7 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenuItem.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 |
6 | public class SwipeMenuItem {
7 |
8 | private int id;
9 | private Context mContext;
10 | private String title;
11 | private Drawable icon;
12 | private Drawable background;
13 | private int titleColor;
14 | private int titleSize;
15 | private int width;
16 |
17 | public SwipeMenuItem(Context context) {
18 | mContext = context;
19 | }
20 |
21 | public int getId() {
22 | return id;
23 | }
24 |
25 | public void setId(int id) {
26 | this.id = id;
27 | }
28 |
29 | public int getTitleColor() {
30 | return titleColor;
31 | }
32 |
33 | public int getTitleSize() {
34 | return titleSize;
35 | }
36 |
37 | public void setTitleSize(int titleSize) {
38 | this.titleSize = titleSize;
39 | }
40 |
41 | public void setTitleColor(int titleColor) {
42 | this.titleColor = titleColor;
43 | }
44 |
45 | public String getTitle() {
46 | return title;
47 | }
48 |
49 | public void setTitle(String title) {
50 | this.title = title;
51 | }
52 |
53 | public void setTitle(int resId) {
54 | setTitle(mContext.getString(resId));
55 | }
56 |
57 | public Drawable getIcon() {
58 | return icon;
59 | }
60 |
61 | public void setIcon(Drawable icon) {
62 | this.icon = icon;
63 | }
64 |
65 | public void setIcon(int resId) {
66 | this.icon = mContext.getResources().getDrawable(resId);
67 | }
68 |
69 | public Drawable getBackground() {
70 | return background;
71 | }
72 |
73 | public void setBackground(Drawable background) {
74 | this.background = background;
75 | }
76 |
77 | public void setBackground(int resId) {
78 | this.background = mContext.getResources().getDrawable(resId);
79 | }
80 |
81 | public int getWidth() {
82 | return width;
83 | }
84 |
85 | public void setWidth(int width) {
86 | this.width = width;
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenuLayout.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.GestureDetectorCompat;
5 | import android.support.v4.widget.ScrollerCompat;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.util.TypedValue;
9 | import android.view.GestureDetector;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.animation.Interpolator;
13 | import android.widget.AbsListView;
14 | import android.widget.FrameLayout;
15 | import android.widget.Scroller;
16 |
17 | public class SwipeMenuLayout extends FrameLayout {
18 |
19 | private static final int CONTENT_VIEW_ID = 1;
20 | private static final int MENU_VIEW_ID = 2;
21 |
22 | private static final int STATE_CLOSE = 0;
23 | private static final int STATE_OPEN = 1;
24 |
25 | private View mContentView;
26 | private SwipeMenuView mMenuView;
27 | private int mDownX;
28 | private int state = STATE_CLOSE;
29 | private GestureDetectorCompat mGestureDetector;
30 | private GestureDetector.OnGestureListener mGestureListener;
31 | private boolean isFling;
32 | private int MIN_FLING = dp2px(15);
33 | private int MAX_VELOCITYX = -dp2px(500);
34 | private ScrollerCompat mOpenScroller;
35 | private ScrollerCompat mCloseScroller;
36 | private int mBaseX;
37 | private int position;
38 | private Interpolator mCloseInterpolator;
39 | private Interpolator mOpenInterpolator;
40 |
41 | public SwipeMenuLayout(View contentView, SwipeMenuView menuView) {
42 | this(contentView, menuView, null, null);
43 | }
44 |
45 | public SwipeMenuLayout(View contentView, SwipeMenuView menuView, Interpolator closeInterpolator,
46 | Interpolator openInterpolator) {
47 | super(contentView.getContext());
48 | mCloseInterpolator = closeInterpolator;
49 | mOpenInterpolator = openInterpolator;
50 | mContentView = contentView;
51 | mMenuView = menuView;
52 | mMenuView.setLayout(this);
53 | init();
54 | }
55 |
56 | private SwipeMenuLayout(Context context, AttributeSet attrs) {
57 | super(context, attrs);
58 | }
59 |
60 | private SwipeMenuLayout(Context context) {
61 | super(context);
62 | }
63 |
64 | public int getPosition() {
65 | return position;
66 | }
67 |
68 | public void setPosition(int position) {
69 | this.position = position;
70 | mMenuView.setPosition(position);
71 | }
72 |
73 | private void init() {
74 | setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
75 | mGestureListener = new GestureDetector.SimpleOnGestureListener() {
76 | @Override
77 | public boolean onDown(MotionEvent e) {
78 | isFling = false;
79 | return true;
80 | }
81 |
82 | @Override
83 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
84 | // TODO
85 | if ((e1.getX() - e2.getX()) > MIN_FLING && velocityX < MAX_VELOCITYX) {
86 | isFling = true;
87 | }
88 | // Log.i("byz", MAX_VELOCITYX + ", velocityX = " + velocityX);
89 | return super.onFling(e1, e2, velocityX, velocityY);
90 | }
91 | };
92 | mGestureDetector = new GestureDetectorCompat(getContext(), mGestureListener);
93 |
94 | if (mCloseInterpolator != null) {
95 | mCloseScroller = ScrollerCompat.create(getContext(), mCloseInterpolator);
96 | } else {
97 | mCloseScroller = ScrollerCompat.create(getContext());
98 | }
99 | if (mOpenInterpolator != null) {
100 | mOpenScroller = ScrollerCompat.create(getContext(), mOpenInterpolator);
101 | } else {
102 | mOpenScroller = ScrollerCompat.create(getContext());
103 | }
104 |
105 | LayoutParams contentParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
106 | mContentView.setLayoutParams(contentParams);
107 | if (mContentView.getId() < 1) {
108 | mContentView.setId(CONTENT_VIEW_ID);
109 | }
110 |
111 | mMenuView.setId(MENU_VIEW_ID);
112 | mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
113 |
114 | addView(mContentView);
115 | addView(mMenuView);
116 |
117 | }
118 |
119 | @Override
120 | protected void onAttachedToWindow() {
121 | super.onAttachedToWindow();
122 | }
123 |
124 | @Override
125 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
126 | super.onSizeChanged(w, h, oldw, oldh);
127 | }
128 |
129 | public boolean onSwipe(MotionEvent event) {
130 | mGestureDetector.onTouchEvent(event);
131 | switch (event.getAction()) {
132 | case MotionEvent.ACTION_DOWN:
133 | mDownX = (int) event.getX();
134 | isFling = false;
135 | break;
136 | case MotionEvent.ACTION_MOVE:
137 | // Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
138 | int dis = (int) (mDownX - event.getX());
139 | if (state == STATE_OPEN) {
140 | dis += mMenuView.getWidth();
141 | }
142 | swipe(dis);
143 | break;
144 | case MotionEvent.ACTION_UP:
145 | if (isFling || (mDownX - event.getX()) > (mMenuView.getWidth() / 2)) {
146 | // open
147 | smoothOpenMenu();
148 | } else {
149 | // close
150 | smoothCloseMenu();
151 | return false;
152 | }
153 | break;
154 | }
155 | return false;
156 | }
157 |
158 | /**
159 | * 滑动侧滑菜单
160 | * @param dis
161 | */
162 | public void swipeMenuSlide(int dis){
163 | if (state == STATE_OPEN) {
164 | dis += mMenuView.getWidth();
165 | }
166 | swipe(dis);
167 | }
168 |
169 | /**
170 | * 手指快速滑动的时候是打开还是关闭侧滑菜单
171 | * @param isFling
172 | * @param dix
173 | */
174 | public void swipeMenuFling(boolean isFling,int dix){
175 | if (isFling || dix > (mMenuView.getWidth() / 2)) {
176 | // open
177 | smoothOpenMenu();
178 | } else {
179 | // close
180 | smoothCloseMenu();
181 | }
182 | }
183 |
184 |
185 | public boolean isOpen() {
186 | return state == STATE_OPEN;
187 | }
188 |
189 | public boolean isActive() {
190 | if (mContentView != null) {
191 | return mContentView.getLeft() != 0;
192 | }
193 | return false;
194 | }
195 |
196 | @Override
197 | public boolean onTouchEvent(MotionEvent event) {
198 | return super.onTouchEvent(event);
199 | }
200 |
201 | private void swipe(int dis) {
202 | if (dis > mMenuView.getWidth()) {
203 | dis = mMenuView.getWidth();
204 | }
205 | if (dis < 0) {
206 | dis = 0;
207 | }
208 | mContentView.layout(-dis, mContentView.getTop(), mContentView.getWidth() - dis, getMeasuredHeight());
209 | mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),
210 | mContentView.getWidth() + mMenuView.getWidth() - dis, getMeasuredHeight());
211 | }
212 |
213 | @Override
214 | public void computeScroll() {
215 | if (state == STATE_OPEN) {
216 | if (mOpenScroller.computeScrollOffset()) {
217 | swipe(mOpenScroller.getCurrX());
218 | postInvalidate();
219 | }
220 | } else {
221 | if (mCloseScroller.computeScrollOffset()) {
222 | swipe(mBaseX - mCloseScroller.getCurrX());
223 | postInvalidate();
224 | }
225 | }
226 | }
227 |
228 | public void smoothCloseMenu() {
229 | state = STATE_CLOSE;
230 | mBaseX = -mContentView.getLeft();
231 | mCloseScroller.startScroll(0, 0, mBaseX, 0, 350);
232 | postInvalidate();
233 | }
234 |
235 | public void smoothOpenMenu() {
236 | state = STATE_OPEN;
237 | mOpenScroller.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
238 | postInvalidate();
239 | }
240 |
241 | public void closeMenu() {
242 | if (mCloseScroller.computeScrollOffset()) {
243 | mCloseScroller.abortAnimation();
244 | }
245 | if (state == STATE_OPEN) {
246 | state = STATE_CLOSE;
247 | swipe(0);
248 | }
249 | }
250 |
251 | public void openMenu() {
252 | if (state == STATE_CLOSE) {
253 | state = STATE_OPEN;
254 | swipe(mMenuView.getWidth());
255 | }
256 | }
257 |
258 | public View getContentView() {
259 | return mContentView;
260 | }
261 |
262 | public SwipeMenuView getMenuView() {
263 | return mMenuView;
264 | }
265 |
266 | private int dp2px(int dp) {
267 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources()
268 | .getDisplayMetrics());
269 | }
270 |
271 | @Override
272 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
273 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
274 | mMenuView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
275 | MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
276 | }
277 |
278 | @Override
279 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
280 | mContentView.layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
281 | mMenuView.layout(getMeasuredWidth(), 0, getMeasuredWidth() + mMenuView.getMeasuredWidth(),
282 | getMeasuredHeight());
283 | }
284 |
285 | public void setMenuHeight(int measuredHeight) {
286 | Log.i("byz", "pos = " + position + ", height = " + measuredHeight);
287 | LayoutParams params = (LayoutParams) mMenuView.getLayoutParams();
288 | if (params.height != measuredHeight) {
289 | params.height = measuredHeight;
290 | mMenuView.setLayoutParams(mMenuView.getLayoutParams());
291 | }
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/SwipeMenu/SwipeMenuView.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.SwipeMenu;
2 |
3 | import android.text.TextUtils;
4 | import android.view.Gravity;
5 | import android.view.View;
6 | import android.view.View.OnClickListener;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 | import android.widget.TextView;
10 |
11 | import java.util.List;
12 |
13 | public class SwipeMenuView extends LinearLayout implements OnClickListener {
14 |
15 | // private CBPullRefreshListView mListView;
16 | private SwipeMenuLayout mLayout;
17 | private SwipeMenu mMenu;
18 | private OnSwipeItemClickListener onItemClickListener;
19 | private int position;
20 |
21 | public int getPosition() {
22 | return position;
23 | }
24 |
25 | public void setPosition(int position) {
26 | this.position = position;
27 | }
28 |
29 | public SwipeMenuView(SwipeMenu menu) {
30 | super(menu.getContext());
31 | mMenu = menu;
32 | List items = menu.getMenuItems();
33 | int id = 0;
34 | for (SwipeMenuItem item : items) {
35 | addItem(item, id++);
36 | }
37 | }
38 |
39 | private void addItem(SwipeMenuItem item, int id) {
40 | LayoutParams params = new LayoutParams(item.getWidth(), LayoutParams.MATCH_PARENT);
41 | LinearLayout parent = new LinearLayout(getContext());
42 | parent.setId(id);
43 | parent.setGravity(Gravity.CENTER);
44 | parent.setOrientation(LinearLayout.VERTICAL);
45 | parent.setLayoutParams(params);
46 | parent.setBackgroundDrawable(item.getBackground());
47 | parent.setOnClickListener(this);
48 | if (item.getIcon() != null) {
49 | parent.addView(createIcon(item));
50 | }
51 | if (!TextUtils.isEmpty(item.getTitle())) {
52 | parent.addView(createTitle(item));
53 | }
54 | addView(parent);
55 | }
56 |
57 | private ImageView createIcon(SwipeMenuItem item) {
58 | ImageView iv = new ImageView(getContext());
59 | iv.setImageDrawable(item.getIcon());
60 | return iv;
61 | }
62 |
63 | private TextView createTitle(SwipeMenuItem item) {
64 | TextView tv = new TextView(getContext());
65 | tv.setText(item.getTitle());
66 | tv.setGravity(Gravity.CENTER);
67 | tv.setTextSize(item.getTitleSize());
68 | tv.setTextColor(item.getTitleColor());
69 | return tv;
70 | }
71 |
72 | @Override
73 | public void onClick(View v) {
74 | if (onItemClickListener != null && mLayout.isOpen()) {
75 | onItemClickListener.onItemClick(this, mMenu, v.getId());
76 | }
77 | }
78 |
79 | public OnSwipeItemClickListener getOnSwipeItemClickListener() {
80 | return onItemClickListener;
81 | }
82 |
83 | public void setOnSwipeItemClickListener(OnSwipeItemClickListener onItemClickListener) {
84 | this.onItemClickListener = onItemClickListener;
85 | }
86 |
87 | public void setLayout(SwipeMenuLayout mLayout) {
88 | this.mLayout = mLayout;
89 | }
90 |
91 | public static interface OnSwipeItemClickListener {
92 | void onItemClick(SwipeMenuView view, SwipeMenu menu, int index);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/titanic/Titanic.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.titanic;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ObjectAnimator;
6 | import android.animation.ValueAnimator;
7 | import android.annotation.SuppressLint;
8 | import android.os.Build;
9 | import android.view.animation.LinearInterpolator;
10 |
11 |
12 | public class Titanic {
13 |
14 | private AnimatorSet animatorSet;
15 | private Animator.AnimatorListener animatorListener;
16 |
17 | public Animator.AnimatorListener getAnimatorListener() {
18 | return animatorListener;
19 | }
20 |
21 | public void setAnimatorListener(Animator.AnimatorListener animatorListener) {
22 | this.animatorListener = animatorListener;
23 | }
24 |
25 | public void start(final TitanicTextView textView) {
26 |
27 | final Runnable animate = new Runnable() {
28 | @Override
29 | public void run() {
30 |
31 | textView.setSinking(true);
32 |
33 | // horizontal animation. 200 = wave.png width
34 | ObjectAnimator maskXAnimator = ObjectAnimator.ofFloat(textView, "maskX", 0, 200);
35 | maskXAnimator.setRepeatCount(ValueAnimator.INFINITE);
36 | maskXAnimator.setDuration(1000);
37 | maskXAnimator.setStartDelay(0);
38 |
39 | int h = textView.getHeight();
40 |
41 | // vertical animation
42 | // maskY = 0 -> wave vertically centered
43 | // repeat mode REVERSE to go back and forth
44 | ObjectAnimator maskYAnimator = ObjectAnimator.ofFloat(textView, "maskY", h/2, -h/2);
45 | maskYAnimator.setRepeatCount(ValueAnimator.INFINITE);
46 | maskYAnimator.setRepeatMode(ValueAnimator.REVERSE);
47 | maskYAnimator.setDuration(8000);
48 | maskYAnimator.setStartDelay(0);
49 |
50 | // now play both animations together
51 | animatorSet = new AnimatorSet();
52 | animatorSet.playTogether(maskXAnimator, maskYAnimator);
53 | animatorSet.setInterpolator(new LinearInterpolator());
54 | animatorSet.addListener(new Animator.AnimatorListener() {
55 | @Override
56 | public void onAnimationStart(Animator animation) {
57 | }
58 |
59 | @SuppressLint("NewApi")
60 | @Override
61 | public void onAnimationEnd(Animator animation) {
62 | textView.setSinking(false);
63 |
64 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
65 | textView.postInvalidate();
66 | } else {
67 | textView.postInvalidateOnAnimation();
68 | }
69 |
70 | animatorSet = null;
71 | }
72 |
73 | @Override
74 | public void onAnimationCancel(Animator animation) {
75 |
76 | }
77 |
78 | @Override
79 | public void onAnimationRepeat(Animator animation) {
80 |
81 | }
82 | });
83 |
84 |
85 | if (animatorListener != null) {
86 | animatorSet.addListener(animatorListener);
87 | }
88 |
89 | animatorSet.start();
90 | }
91 | };
92 |
93 | if (!textView.isSetUp()) {
94 | textView.setAnimationSetupCallback(new TitanicTextView.AnimationSetupCallback() {
95 | @Override
96 | public void onSetupAnimation(final TitanicTextView target) {
97 | animate.run();
98 | }
99 | });
100 | } else {
101 | animate.run();
102 | }
103 | }
104 |
105 | public void cancel() {
106 | if (animatorSet != null) {
107 | animatorSet.cancel();
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/titanic/TitanicTextView.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.titanic;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.ColorStateList;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapShader;
8 | import android.graphics.Canvas;
9 | import android.graphics.Matrix;
10 | import android.graphics.Shader;
11 | import android.graphics.drawable.Drawable;
12 | import android.util.AttributeSet;
13 | import android.widget.TextView;
14 |
15 | import com.zhl.CBPullRefresh.R;
16 |
17 |
18 | public class TitanicTextView extends TextView {
19 |
20 | public interface AnimationSetupCallback {
21 | public void onSetupAnimation(TitanicTextView titanicTextView);
22 | }
23 |
24 | // callback fired at first onSizeChanged
25 | private AnimationSetupCallback animationSetupCallback;
26 | // wave shader coordinates
27 | private float maskX, maskY;
28 | // if true, the shader will display the wave
29 | private boolean sinking;
30 | // true after the first onSizeChanged
31 | private boolean setUp;
32 |
33 | // shader containing a repeated wave
34 | private BitmapShader shader;
35 | // shader matrix
36 | private Matrix shaderMatrix;
37 | // wave drawable
38 | private Drawable wave;
39 | // (getHeight() - waveHeight) / 2
40 | private float offsetY;
41 |
42 | public TitanicTextView(Context context) {
43 | super(context);
44 | init();
45 | }
46 |
47 | public TitanicTextView(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | init();
50 | }
51 |
52 | public TitanicTextView(Context context, AttributeSet attrs, int defStyle) {
53 | super(context, attrs, defStyle);
54 | init();
55 | }
56 |
57 | private void init() {
58 | shaderMatrix = new Matrix();
59 | }
60 |
61 | public AnimationSetupCallback getAnimationSetupCallback() {
62 | return animationSetupCallback;
63 | }
64 |
65 | public void setAnimationSetupCallback(AnimationSetupCallback animationSetupCallback) {
66 | this.animationSetupCallback = animationSetupCallback;
67 | }
68 |
69 | public float getMaskX() {
70 | return maskX;
71 | }
72 |
73 | public void setMaskX(float maskX) {
74 | this.maskX = maskX;
75 | invalidate();
76 | }
77 |
78 | public float getMaskY() {
79 | return maskY;
80 | }
81 |
82 | public void setMaskY(float maskY) {
83 | this.maskY = maskY;
84 | invalidate();
85 | }
86 |
87 | public boolean isSinking() {
88 | return sinking;
89 | }
90 |
91 | public void setSinking(boolean sinking) {
92 | this.sinking = sinking;
93 | }
94 |
95 | public boolean isSetUp() {
96 | return setUp;
97 | }
98 |
99 | @Override
100 | public void setTextColor(int color) {
101 | super.setTextColor(color);
102 | createShader();
103 | }
104 |
105 | @Override
106 | public void setTextColor(ColorStateList colors) {
107 | super.setTextColor(colors);
108 | createShader();
109 | }
110 |
111 | @Override
112 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
113 | super.onSizeChanged(w, h, oldw, oldh);
114 |
115 | createShader();
116 |
117 | if (!setUp) {
118 | setUp = true;
119 | if (animationSetupCallback != null) {
120 | animationSetupCallback.onSetupAnimation(TitanicTextView.this);
121 | }
122 | }
123 | }
124 |
125 | /**
126 | * Create the shader
127 | * draw the wave with current color for a background
128 | * repeat the bitmap horizontally, and clamp colors vertically
129 | */
130 | private void createShader() {
131 |
132 | if (wave == null) {
133 | wave = getResources().getDrawable(R.drawable.wave);
134 | }
135 |
136 | int waveW = wave.getIntrinsicWidth();
137 | int waveH = wave.getIntrinsicHeight();
138 |
139 | Bitmap b = Bitmap.createBitmap(waveW, waveH, Bitmap.Config.ARGB_8888);
140 | Canvas c = new Canvas(b);
141 |
142 | c.drawColor(getCurrentTextColor());
143 |
144 | wave.setBounds(0, 0, waveW, waveH);
145 | wave.draw(c);
146 |
147 | shader = new BitmapShader(b, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
148 | getPaint().setShader(shader);
149 |
150 | offsetY = (getHeight() - waveH) / 2;
151 | }
152 |
153 | @Override
154 | protected void onDraw(Canvas canvas) {
155 |
156 | // modify text paint shader according to sinking state
157 | if (sinking && shader != null) {
158 |
159 | // first call after sinking, assign it to our paint
160 | if (getPaint().getShader() == null) {
161 | getPaint().setShader(shader);
162 | }
163 |
164 | // translate shader accordingly to maskX maskY positions
165 | // maskY is affected by the offset to vertically center the wave
166 | shaderMatrix.setTranslate(maskX, maskY + offsetY);
167 |
168 | // assign matrix to invalidate the shader
169 | shader.setLocalMatrix(shaderMatrix);
170 | } else {
171 | getPaint().setShader(null);
172 | }
173 |
174 | super.onDraw(canvas);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/utils/Blur.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.utils;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.support.v8.renderscript.Allocation;
6 | import android.support.v8.renderscript.Element;
7 | import android.support.v8.renderscript.RenderScript;
8 | import android.support.v8.renderscript.ScriptIntrinsicBlur;
9 |
10 | /**
11 | * Blur.java
12 | *
13 | * @author Manabu-GT on 6/12/14.
14 | */
15 | public class Blur {
16 |
17 | private static final int DEFAULT_BLUR_RADIUS = 10;
18 |
19 | public static Bitmap apply(Context context, Bitmap sentBitmap) {
20 | return apply(context, sentBitmap, DEFAULT_BLUR_RADIUS);
21 | }
22 |
23 | public static Bitmap apply(Context context, Bitmap sentBitmap, int radius) {
24 | Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
25 | final RenderScript rs = RenderScript.create(context);
26 | final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
27 | Allocation.USAGE_SCRIPT);
28 | final Allocation output = Allocation.createTyped(rs, input.getType());
29 | final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
30 | script.setRadius(radius);
31 | script.setInput(input);
32 | script.forEach(output);
33 | output.copyTo(bitmap);
34 |
35 | // clean up renderscript resources
36 | rs.destroy();
37 | input.destroy();
38 | output.destroy();
39 | script.destroy();
40 |
41 | return bitmap;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/utils/BlurUtil.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.utils;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.annotation.TargetApi;
6 | import android.graphics.Bitmap;
7 | import android.graphics.Canvas;
8 | import android.os.Build;
9 | import android.os.Handler;
10 | import android.view.View;
11 | import android.view.ViewPropertyAnimator;
12 | import android.view.animation.AlphaAnimation;
13 | import android.view.animation.Animation;
14 |
15 | /**
16 | * BlurUtil.java
17 | *
18 | * @author Manabu-GT on 6/12/14.
19 | */
20 | public class BlurUtil {
21 |
22 | public static Bitmap drawViewToBitmap(View view, int width, int height, int downSampling) {
23 | return drawViewToBitmap(view, width, height, 0f, 0f, downSampling);
24 | }
25 |
26 | public static Bitmap drawViewToBitmap(View view, int width, int height, float translateX,
27 | float translateY, int downSampling) {
28 | float scale = 1f / downSampling;
29 | int bmpWidth = (int) (width * scale - translateX / downSampling);
30 | int bmpHeight = (int) (height * scale - translateY / downSampling);
31 | Bitmap dest = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
32 | Canvas c = new Canvas(dest);
33 | c.translate(-translateX / downSampling, -translateY / downSampling);
34 | if (downSampling > 1) {
35 | c.scale(scale, scale);
36 | }
37 | view.draw(c);
38 | return dest;
39 | }
40 |
41 | public static boolean isPostHoneycomb() {
42 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1;
43 | }
44 |
45 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
46 | public static void setAlpha(View view, float alpha) {
47 | if (isPostHoneycomb()) {
48 | view.setAlpha(alpha);
49 | } else {
50 | AlphaAnimation alphaAnimation = new AlphaAnimation(alpha, alpha);
51 | // make it instant
52 | alphaAnimation.setDuration(0);
53 | alphaAnimation.setFillAfter(true);
54 | view.startAnimation(alphaAnimation);
55 | }
56 | }
57 |
58 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
59 | public static void animateAlpha(final View view, float fromAlpha, float toAlpha, int duration, final Runnable endAction) {
60 | if (isPostHoneycomb()) {
61 | ViewPropertyAnimator animator = view.animate().alpha(toAlpha).setDuration(duration);
62 | if (endAction != null) {
63 | animator.setListener(new AnimatorListenerAdapter() {
64 | public void onAnimationEnd(Animator animation) {
65 | endAction.run();
66 | }
67 | });
68 | }
69 | } else {
70 | AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha);
71 | alphaAnimation.setDuration(duration);
72 | alphaAnimation.setFillAfter(true);
73 | if (endAction != null) {
74 | alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
75 | @Override
76 | public void onAnimationEnd(Animation animation) {
77 | // fixes the crash bug while removing views
78 | Handler handler = new Handler();
79 | handler.post(endAction);
80 | }
81 | @Override
82 | public void onAnimationStart(Animation animation) { }
83 | @Override
84 | public void onAnimationRepeat(Animation animation) { }
85 | });
86 | }
87 | view.startAnimation(alphaAnimation);
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/utils/TimeType.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.utils;
2 |
3 | public enum TimeType {
4 | /**
5 | * yyyy-MM-dd hh:mm:ss
6 | */
7 | DEFAULT,
8 |
9 | /**
10 | * yyyyMMdd hhmmss
11 | */
12 | DEFAULT_CHINESS,
13 |
14 | /**
15 | * MM-dd HH:mm
16 | */
17 | DEFAULT_SHORT,
18 |
19 | /**
20 | * MMddhhmm
21 | */
22 | DEFAULT_CHINESS_SHORT,
23 |
24 | FROMNOW,
25 |
26 | DEFAULT_YEAR;
27 | }
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/java/com/zhl/CBPullRefresh/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.zhl.CBPullRefresh.utils;
2 |
3 | import android.content.Context;
4 |
5 | import com.zhl.CBPullRefresh.R;
6 |
7 | import java.text.SimpleDateFormat;
8 | import java.util.Date;
9 | import java.util.Locale;
10 |
11 | /**
12 | * Created by zhaohl on 2016-3-24.
13 | */
14 | public class Utils {
15 | public static String getTimeDifferent(Context context,long time) {
16 | String updateTime = "";
17 | Date currentTime = new Date(System.currentTimeMillis());
18 | Date inputTime = new Date(time);
19 | long interval = currentTime.getTime() - inputTime.getTime();
20 | long days = interval / 86400000;
21 | long hours = (interval - days * 86400000) / 3600000;
22 | long minutes = (interval - days * 86400000 - hours * 3600000) / 60000;
23 | if (days >= 1) {
24 | updateTime = getPublishTime(context,TimeType.DEFAULT_YEAR, inputTime.getTime());
25 | } else if (hours >= 1) {
26 | updateTime = hours +context.getString(R.string.util_hours_ago) ;
27 | } else {
28 | if (minutes <= 10) {
29 | updateTime = context.getString(R.string.util_a_moment_ago);
30 | } else if (minutes > 10 && minutes <= 20) {
31 | updateTime = context.getString(R.string.util_10_moment_ago);
32 | } else if (minutes > 20 && minutes <= 30) {
33 | updateTime = context.getString(R.string.util_20_moment_ago);
34 | } else if (minutes > 30 && minutes < 60) {
35 | updateTime = context.getString(R.string.util_30_moment_ago);
36 | }
37 | }
38 | return updateTime;
39 | }
40 |
41 | public static String getPublishTime(Context context ,TimeType type, long time) {
42 | if (time == 0)
43 | return "";
44 | Date date = new Date(time);
45 | SimpleDateFormat dateFormat;
46 | String timeStr = null;
47 | switch (type) {
48 | case DEFAULT:
49 | dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
50 | timeStr = dateFormat.format(date);
51 | break;
52 | case DEFAULT_CHINESS:
53 | dateFormat = new SimpleDateFormat(context.getString(R.string.util_format_yyyymmdd_hhmmss), Locale.CHINA);
54 | timeStr = dateFormat.format(date);
55 | break;
56 | case DEFAULT_SHORT:
57 | dateFormat = new SimpleDateFormat("MM-dd HH:mm", Locale.CHINA);
58 | timeStr = dateFormat.format(date);
59 | break;
60 | case DEFAULT_CHINESS_SHORT:
61 | dateFormat = new SimpleDateFormat(context.getString(R.string.util_format_mmdd_hhmm), Locale.CHINA);
62 | timeStr = dateFormat.format(date);
63 | break;
64 | case FROMNOW:
65 | timeStr = getTimeFromNow(context,time);
66 | break;
67 | case DEFAULT_YEAR:
68 | dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
69 | timeStr = dateFormat.format(date);
70 | break;
71 | }
72 | return timeStr;
73 | }
74 |
75 | public static String getTimeFromNow(Context context,long time) {
76 | String updateTime = "";
77 | long currentTime = System.currentTimeMillis();
78 | long interval = currentTime - time;
79 | long minutes = interval / 60000;
80 | if (minutes < 60) {
81 | minutes = minutes == 0 ? 1 : minutes;
82 | updateTime = minutes + context.getString(R.string.util_miniutes_ago);
83 | } else {
84 | minutes = minutes / 60;
85 | minutes = minutes == 0 ? 1 : minutes;
86 | if (minutes < 24) {
87 | updateTime = minutes + context.getString(R.string.util_hours_ago);
88 | } else {
89 | minutes = minutes / 24;
90 | minutes = minutes == 0 ? 1 : minutes;
91 | updateTime = minutes + context.getString(R.string.util_day_ago);
92 | }
93 | }
94 | return updateTime;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-hdpi/top_search_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-hdpi/top_search_bar.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-hdpi/top_search_bar_night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-hdpi/top_search_bar_night.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-nodpi/wave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-nodpi/wave.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-xhdpi/icon_header_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-xhdpi/icon_header_refresh.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-xhdpi/top_pull_refresh_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-xhdpi/top_pull_refresh_arrow.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable-xhdpi/top_search_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/CBPullRefresh/src/main/res/drawable-xhdpi/top_search_bar.png
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/drawable/footer_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/layout/cblistview_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
25 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/layout/cblistview_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
26 |
27 |
35 |
36 |
44 |
45 |
49 |
50 |
57 |
58 |
64 |
65 |
66 |
67 |
75 |
76 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/layout/cbpullrefrsh_topsearch.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #ECEDED
5 | #3fbecc
6 | #f1494c
7 | #efefef
8 | #f1f1f1
9 | #a6a7a6
10 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/CBPullRefresh/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PullRefreshLibrary
3 |
4 | Hello world!
5 | Settings
6 | 下拉刷新
7 | 松开刷新数据
8 | 正在刷新...
9 | 正在加载...
10 | 上拉加载更多
11 | 松开载入更多
12 | 小时前
13 | 刚刚
14 | 10分钟前
15 | 20分钟前
16 | 30分钟前
17 | yyyy年MM月dd日 HH时mm分ss秒
18 | MM月dd日 HH时mm分
19 | 分钟前
20 | 日前
21 |
22 |
--------------------------------------------------------------------------------
/CBPullRefreshListView.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/GIF1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/GIF1.gif
--------------------------------------------------------------------------------
/GIF2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/GIF2.gif
--------------------------------------------------------------------------------
/GIF3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/GIF3.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://jitpack.io/#yilylong/CBPullRefreshListView)
2 | ## CBPullRefreshListView
3 |
4 | RecyclerView版本 [DragableRecyclerView](https://github.com/yilylong/DragableRecyclerView)
5 |
6 | 下拉刷新很常见,listview带侧滑功能的也很常见。github上将两者结合的也很多比如:[SwipeMenuListView](https://github.com/baoyongzhang/SwipeMenuListView)是带有侧滑功能的lisetview但是无法下拉刷新。而[Android-PullToRefresh-SwipeMenuListView-Sample](https://github.com/licaomeng/Android-PullToRefresh-SwipeMenuListView-Sample)是将几个功能完整结合。看了下他们的实现,是在以前的XListView基础上整合。但listview里面的下拉刷新和上拉加载的动作与刷新头耦合比较严重。如果想自定义自己的刷新头样式稍微麻烦点。于是就想把下拉刷新的功能和刷新头的展示样式抽离分开。listview只管将一些下拉上拉的事件传递出来。刷新头通过实现这些状态方法去做自己想要的刷新样式就可以了。
7 | 
8 | 
9 | 
10 | 
11 |
12 | 引入
13 | --
14 |
15 | Step 1. Add the JitPack repository to your build file
16 | -
17 |
18 | allprojects {
19 | repositories {
20 | ...
21 | maven { url 'https://jitpack.io' }
22 | }
23 | }
24 |
25 | Step 2. Add the dependency
26 | -
27 | dependencies {
28 | compile 'com.github.yilylong:CBPullRefreshListView:1.0.0'
29 | }
30 |
31 |
32 |
33 |
34 | 自定义刷新头
35 | ---
36 | 继承CBRefreshHeaderView 实现几个状态下的回调的方法比如:
37 |
38 | /**
39 | * 设置当前状态
40 | * @param state
41 | */
42 | @Override
43 | public void setState(int state) {
44 |
45 | }
46 | /**
47 | * 下拉刷新的回调
48 | */
49 | @Override
50 | public void pullToRefresh() {
51 |
52 | }
53 | /**
54 | * 释放刷新的回调
55 | */
56 | @Override
57 | public void releaseToRefresh() {
58 |
59 | }
60 | /**
61 | * 正在刷新
62 | */
63 | @Override
64 | public void onRefreshing() {
65 |
66 | }
67 | /**
68 | * 设置头部或底部的可见高度
69 | * @param height
70 | */
71 | @Override
72 | public void setVisiableHeight(int height) {
73 |
74 | }
75 | /**
76 | * 获取可见高度
77 | * @return
78 | */
79 | @Override
80 | public int getVisiableHeight() {
81 | return 0;
82 | }
83 | /**
84 | * 正在拖动
85 | * @param deltaY
86 | */
87 | @Override
88 | public void onDragSlide(float deltaY) {
89 |
90 | }
91 |
92 | 在这些方法中去改变刷新头不同状态下的表现形式。(下拉刷新是通过改变头部高度实现的)可以参考CBRefreshHeader MyCustomRrefreshHeader 有哪些状态回调可以查看 CBRefreshState
93 |
94 | CBPullRefreshListView一些其他方法:
95 | ---
96 | 设置自定义的刷新头
97 | -
98 | mListView.setRefreshHeader(myRefreshHeader);
99 |
100 | 设置是否显示顶部的搜索栏(可自定义)
101 | -
102 | mListView.showTobSearchBar(true);
103 | mListView.setTopSearchBar(myTopSearchBar);
104 |
105 | 设置swipe开关
106 | -
107 |
108 | mListView.setSwipeEnable(false)
109 |
110 | 设置下拉刷新的监听接口
111 | -
112 | mListView.setOnPullRefreshListener(new CBPullRefreshListView.OnPullRefreshListener() {
113 | @Override
114 | public void onRefresh() {
115 | mListView.postDelayed(new Runnable() {
116 | @Override
117 | public void run() {
118 | mListView.stopRefresh();
119 | }
120 | }, 3000);
121 | }
122 |
123 | @Override
124 | public void onLoadMore() {
125 | mListView.postDelayed(new Runnable() {
126 | @Override
127 | public void run() {
128 | mListView.stopLoadMore();
129 | }
130 | }, 3000);
131 | }
132 |
133 | @Override
134 | public void onUpdateRefreshTime(long time) {
135 |
136 | }
137 |
138 | });
139 |
140 | 设置侧滑菜单项目
141 | -
142 |
143 | SwipeMenuCreator creator = new SwipeMenuCreator() {
144 |
145 | @Override
146 | public void create(SwipeMenu menu) {
147 |
148 | SwipeMenuItem collectionItem = new SwipeMenuItem(getApplicationContext());
149 | collectionItem.setBackground(R.color.green);
150 | collectionItem.setWidth(dp2px(CustomRefreshHeaderActivity.this, 90));
151 | collectionItem.setTitle("收藏");
152 | collectionItem.setTitleSize(18);
153 | collectionItem.setTitleColor(Color.WHITE);
154 | collectionItem.setIcon(R.drawable.icon_collection);
155 | menu.addMenuItem(collectionItem);
156 |
157 | SwipeMenuItem deleteItem = new SwipeMenuItem(getApplicationContext());
158 | deleteItem.setBackground(R.color.red);
159 | deleteItem.setWidth(dp2px(CustomRefreshHeaderActivity.this, 90));
160 | deleteItem.setTitle("删除");
161 | deleteItem.setIcon(R.drawable.icon_delete);
162 | deleteItem.setTitleSize(18);
163 | deleteItem.setTitleColor(Color.WHITE);
164 | menu.addMenuItem(deleteItem);
165 | }
166 | };
167 | mListView.setMenuCreator(creator);
168 |
169 | 设置侧滑菜单项的点击添加和listview的item点击监听
170 |
171 | mListView.setOnMenuItemClickListener(new CBPullRefreshListView.OnMenuItemClickListener() {
172 | @Override
173 | public void onMenuItemClick(int position, SwipeMenu menu, int index) {
174 | Toast.makeText(CustomRefreshHeaderActivity.this, "点击了item swipe 菜单的第" + index, Toast.LENGTH_SHORT).show();
175 | }
176 | });
177 | mListView.setOnItemClickListener(new CBPullRefreshListView.OnItemClickListener() {
178 | @Override
179 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
180 | Toast.makeText(CustomRefreshHeaderActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
181 | }
182 | });
183 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.zhl.cbpullrefreshlistview"
9 | minSdkVersion 15
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | renderscriptTargetApi 20
14 | renderscriptSupportModeEnabled true
15 | ndk {
16 | abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
17 | }
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | compile 'com.android.support:appcompat-v7:25.0.0'
30 | compile project(':CBPullRefresh')
31 | compile 'com.wang.avi:library:1.0.5'
32 | compile 'com.nineoldandroids:library:2.4.0'
33 | compile 'com.rodolfonavalon:ShapeRippleLibrary:0.2.0'
34 | }
35 |
--------------------------------------------------------------------------------
/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:\WORK\Android\AndroidSDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/zhl/cbpullrefreshlistview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.FragmentActivity;
5 | import android.view.LayoutInflater;
6 |
7 | public class BaseActivity extends FragmentActivity{
8 | protected DragBackLayout dragBacklayout;
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | dragBacklayout = (DragBackLayout) LayoutInflater.from(this).inflate(R.layout.base, null);
12 | dragBacklayout.attachToActivity(this);
13 | }
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/CustomRefreshHeaderActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.util.TypedValue;
9 | import android.view.Menu;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.AdapterView;
14 | import android.widget.BaseAdapter;
15 | import android.widget.ImageView;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
20 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenu;
21 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuCreator;
22 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuItem;
23 |
24 | import java.util.ArrayList;
25 |
26 | public class CustomRefreshHeaderActivity extends AppCompatActivity {
27 | private TestAdapter mAdatper;
28 | private ArrayList DataList = new ArrayList();
29 | private CBPullRefreshListView mListView;
30 | private ImageView blurView,blurContentView;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_custom_header_layout);
36 | initData();
37 | initView();
38 | }
39 |
40 | private void initView() {
41 | blurView = (ImageView) findViewById(R.id.blur_view);
42 | blurContentView = (ImageView) findViewById(R.id.blur_orign);
43 | mListView = (CBPullRefreshListView) findViewById(R.id.listview);
44 | MyCustomRrefreshHeader myRefreshHeader = new MyCustomRrefreshHeader(this);
45 | myRefreshHeader.setBlurView(blurContentView,blurView);
46 | mListView.setRefreshHeader(myRefreshHeader);
47 | mListView.setAdapter(mAdatper = new TestAdapter());
48 | mListView.setPullRefreshEnable(true);
49 | mListView.setPullLoadMoreEnable(true);
50 | mListView.setSwipeEnable(true);
51 | // mListView.showTobSearchBar(true);
52 | mListView.setOnPullRefreshListener(new CBPullRefreshListView.OnPullRefreshListener() {
53 | @Override
54 | public void onRefresh() {
55 | mListView.postDelayed(new Runnable() {
56 | @Override
57 | public void run() {
58 | mListView.stopRefresh();
59 | }
60 | }, 3000);
61 | }
62 |
63 | @Override
64 | public void onLoadMore() {
65 | mListView.postDelayed(new Runnable() {
66 | @Override
67 | public void run() {
68 | mListView.stopLoadMore();
69 | }
70 | }, 3000);
71 | }
72 |
73 | @Override
74 | public void onUpdateRefreshTime(long time) {
75 |
76 | }
77 |
78 | });
79 | SwipeMenuCreator creator = new SwipeMenuCreator() {
80 |
81 | @Override
82 | public void create(SwipeMenu menu) {
83 |
84 | SwipeMenuItem collectionItem = new SwipeMenuItem(getApplicationContext());
85 | collectionItem.setBackground(R.color.green);
86 | collectionItem.setWidth(dp2px(CustomRefreshHeaderActivity.this, 90));
87 | collectionItem.setTitle("收藏");
88 | collectionItem.setTitleSize(18);
89 | collectionItem.setTitleColor(Color.WHITE);
90 | // collectionItem.setIcon(R.drawable.icon_collection);
91 | menu.addMenuItem(collectionItem);
92 |
93 | SwipeMenuItem deleteItem = new SwipeMenuItem(getApplicationContext());
94 | deleteItem.setBackground(R.color.red);
95 | deleteItem.setWidth(dp2px(CustomRefreshHeaderActivity.this, 90));
96 | deleteItem.setTitle("删除");
97 | // deleteItem.setIcon(R.drawable.icon_delete);
98 | deleteItem.setTitleSize(18);
99 | deleteItem.setTitleColor(Color.WHITE);
100 | menu.addMenuItem(deleteItem);
101 | }
102 | };
103 | // set creator
104 | mListView.setMenuCreator(creator);
105 | mListView.setOnMenuItemClickListener(new CBPullRefreshListView.OnMenuItemClickListener() {
106 | @Override
107 | public void onMenuItemClick(int position, SwipeMenu menu, int index) {
108 | Toast.makeText(CustomRefreshHeaderActivity.this, "点击了item swipe 菜单的第" + index, Toast.LENGTH_SHORT).show();
109 | }
110 | });
111 | mListView.setOnItemClickListener(new CBPullRefreshListView.OnItemClickListener() {
112 | @Override
113 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
114 | Toast.makeText(CustomRefreshHeaderActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
115 | }
116 | });
117 | }
118 |
119 | private void initData() {
120 | for (int i = 0; i < 30; i++) {
121 | DataList.add(new String("this is a cbpullrefreshlistview test" + i));
122 | }
123 | }
124 |
125 |
126 | @Override
127 | public boolean onCreateOptionsMenu(Menu menu) {
128 | getMenuInflater().inflate(R.menu.menu_main, menu);
129 | return true;
130 | }
131 |
132 | @Override
133 | public boolean onOptionsItemSelected(MenuItem item) {
134 | switch (item.getItemId()){
135 | case R.id.action_settings:
136 | Intent intent = new Intent(this,DragbackActivity.class);
137 | startActivity(intent);
138 | break;
139 | }
140 | return super.onOptionsItemSelected(item);
141 | }
142 |
143 | class TestAdapter extends BaseAdapter {
144 |
145 |
146 | @Override
147 | public int getCount() {
148 | return DataList == null ? 0 : DataList.size();
149 | }
150 |
151 | @Override
152 | public Object getItem(int position) {
153 | return DataList.get(position);
154 | }
155 |
156 | @Override
157 | public long getItemId(int position) {
158 | return 0;
159 | }
160 |
161 | @Override
162 | public View getView(int position, View convertView, ViewGroup parent) {
163 | ViewHolder viewHolder = null;
164 | if (convertView == null) {
165 | viewHolder = new ViewHolder();
166 | convertView = getLayoutInflater().inflate(R.layout.item_listview3, parent, false);
167 | viewHolder.title = (TextView) convertView.findViewById(R.id.item_title);
168 | convertView.setTag(viewHolder);
169 | } else {
170 | viewHolder = (ViewHolder) convertView.getTag();
171 | }
172 | viewHolder.title.setText(DataList.get(position));
173 | return convertView;
174 | }
175 | }
176 |
177 | class ViewHolder {
178 | TextView title;
179 | }
180 |
181 | public int dp2px(Context context,int dp) {
182 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/CustomRefreshHeaderRippleActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.util.TypedValue;
9 | import android.view.Menu;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.AdapterView;
14 | import android.widget.BaseAdapter;
15 | import android.widget.ImageView;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
20 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenu;
21 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuCreator;
22 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuItem;
23 |
24 | import java.util.ArrayList;
25 |
26 | public class CustomRefreshHeaderRippleActivity extends AppCompatActivity {
27 | private TestAdapter mAdatper;
28 | private ArrayList DataList = new ArrayList();
29 | private CBPullRefreshListView mListView;
30 | private ImageView blurView,blurContentView;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_custom_header_layout_ripple);
36 | initData();
37 | initView();
38 | }
39 |
40 | private void initView() {
41 | blurView = (ImageView) findViewById(R.id.blur_view);
42 | blurContentView = (ImageView) findViewById(R.id.blur_orign);
43 | mListView = (CBPullRefreshListView) findViewById(R.id.listview);
44 | MyCustomRrefreshHeaderRippleColor myRefreshHeader = new MyCustomRrefreshHeaderRippleColor(this);
45 | mListView.setRefreshHeader(myRefreshHeader);
46 | mListView.setAdapter(mAdatper = new TestAdapter());
47 | mListView.setSwipeEnable(true);
48 | mListView.setPullRefreshEnable(true);
49 | mListView.setPullLoadMoreEnable(true);
50 | // mListView.showTobSearchBar(true);
51 | mListView.setOnPullRefreshListener(new CBPullRefreshListView.OnPullRefreshListener() {
52 | @Override
53 | public void onRefresh() {
54 | mListView.postDelayed(new Runnable() {
55 | @Override
56 | public void run() {
57 | mListView.stopRefresh();
58 | }
59 | }, 10000);
60 | }
61 |
62 | @Override
63 | public void onLoadMore() {
64 | mListView.postDelayed(new Runnable() {
65 | @Override
66 | public void run() {
67 | mListView.stopLoadMore();
68 | }
69 | }, 10000);
70 | }
71 |
72 | @Override
73 | public void onUpdateRefreshTime(long time) {
74 |
75 | }
76 |
77 | });
78 | SwipeMenuCreator creator = new SwipeMenuCreator() {
79 |
80 | @Override
81 | public void create(SwipeMenu menu) {
82 |
83 | SwipeMenuItem collectionItem = new SwipeMenuItem(getApplicationContext());
84 | collectionItem.setBackground(R.color.green);
85 | collectionItem.setWidth(dp2px(CustomRefreshHeaderRippleActivity.this, 90));
86 | collectionItem.setTitle("收藏");
87 | collectionItem.setTitleSize(18);
88 | collectionItem.setTitleColor(Color.WHITE);
89 | // collectionItem.setIcon(R.drawable.icon_collection);
90 | menu.addMenuItem(collectionItem);
91 |
92 | SwipeMenuItem deleteItem = new SwipeMenuItem(getApplicationContext());
93 | deleteItem.setBackground(R.color.red);
94 | deleteItem.setWidth(dp2px(CustomRefreshHeaderRippleActivity.this, 90));
95 | deleteItem.setTitle("删除");
96 | // deleteItem.setIcon(R.drawable.icon_delete);
97 | deleteItem.setTitleSize(18);
98 | deleteItem.setTitleColor(Color.WHITE);
99 | menu.addMenuItem(deleteItem);
100 | }
101 | };
102 | // set creator
103 | mListView.setMenuCreator(creator);
104 | mListView.setOnMenuItemClickListener(new CBPullRefreshListView.OnMenuItemClickListener() {
105 | @Override
106 | public void onMenuItemClick(int position, SwipeMenu menu, int index) {
107 | Toast.makeText(CustomRefreshHeaderRippleActivity.this, "点击了item swipe 菜单的第" + index, Toast.LENGTH_SHORT).show();
108 | }
109 | });
110 | mListView.setOnItemClickListener(new CBPullRefreshListView.OnItemClickListener() {
111 | @Override
112 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
113 | Toast.makeText(CustomRefreshHeaderRippleActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
114 | }
115 | });
116 | }
117 |
118 | private void initData() {
119 | for (int i = 0; i < 30; i++) {
120 | DataList.add(new String("this is a cbpullrefreshlistview test" + i));
121 | }
122 | }
123 |
124 |
125 | @Override
126 | public boolean onCreateOptionsMenu(Menu menu) {
127 | getMenuInflater().inflate(R.menu.menu_main, menu);
128 | return true;
129 | }
130 |
131 | @Override
132 | public boolean onOptionsItemSelected(MenuItem item) {
133 | switch (item.getItemId()){
134 | case R.id.action_settings:
135 | Intent intent = new Intent(this,DragbackActivity.class);
136 | startActivity(intent);
137 | break;
138 | }
139 | return super.onOptionsItemSelected(item);
140 | }
141 |
142 | class TestAdapter extends BaseAdapter {
143 |
144 |
145 | @Override
146 | public int getCount() {
147 | return DataList == null ? 0 : DataList.size();
148 | }
149 |
150 | @Override
151 | public Object getItem(int position) {
152 | return DataList.get(position);
153 | }
154 |
155 | @Override
156 | public long getItemId(int position) {
157 | return 0;
158 | }
159 |
160 | @Override
161 | public View getView(int position, View convertView, ViewGroup parent) {
162 | ViewHolder viewHolder = null;
163 | if (convertView == null) {
164 | viewHolder = new ViewHolder();
165 | convertView = getLayoutInflater().inflate(R.layout.item_listview3, parent, false);
166 | viewHolder.title = (TextView) convertView.findViewById(R.id.item_title);
167 | convertView.setTag(viewHolder);
168 | } else {
169 | viewHolder = (ViewHolder) convertView.getTag();
170 | }
171 | viewHolder.title.setText(DataList.get(position));
172 | return convertView;
173 | }
174 | }
175 |
176 | class ViewHolder {
177 | TextView title;
178 | }
179 |
180 | public int dp2px(Context context,int dp) {
181 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/DragBackLayout.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Canvas;
7 | import android.graphics.Rect;
8 | import android.graphics.drawable.Drawable;
9 | import android.support.v4.view.ViewPager;
10 | import android.util.AttributeSet;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewConfiguration;
14 | import android.view.ViewGroup;
15 | import android.widget.FrameLayout;
16 | import android.widget.GridView;
17 | import android.widget.Scroller;
18 |
19 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
20 |
21 | import java.util.LinkedList;
22 | import java.util.List;
23 |
24 | // import android.util.Log;
25 |
26 | public class DragBackLayout extends FrameLayout {
27 | // private static final String TAG = DragBackLayout.class.getSimpleName();
28 | private View mContentView;
29 | private int mTouchSlop;
30 | private int downX;
31 | private int downY;
32 | private int tempX;
33 | private Scroller mScroller;
34 | private int viewWidth;
35 | private boolean isSilding;
36 | private boolean isFinish;
37 | private boolean canDragBack = true;
38 | private Drawable mShadowDrawable;
39 | private Activity mActivity;
40 | private List mViewPagers = new LinkedList();
41 | private List mGridViews = new LinkedList();
42 | private List mCbPullRefreshListViews = new LinkedList();
43 |
44 | public DragBackLayout(Context context, AttributeSet attrs) {
45 | this(context, attrs, 0);
46 | }
47 |
48 | public DragBackLayout(Context context, AttributeSet attrs, int defStyle) {
49 | super(context, attrs, defStyle);
50 |
51 | mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
52 | mScroller = new Scroller(context);
53 |
54 | mShadowDrawable = getResources().getDrawable(R.drawable.swipeback_shadow);
55 | }
56 |
57 | public void attachToActivity(Activity activity) {
58 | mActivity = activity;
59 | TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{android.R.attr.windowBackground});
60 | int background = a.getResourceId(0, 0);
61 | a.recycle();
62 |
63 | ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
64 | ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
65 | decorChild.setBackgroundResource(background);
66 | decor.removeView(decorChild);
67 | addView(decorChild);
68 | setContentView(decorChild);
69 | decor.addView(this);
70 | }
71 |
72 | private void setContentView(View decorChild) {
73 | mContentView = (View) decorChild.getParent();
74 | }
75 |
76 | public void setCanDragBack(boolean canDragBack) {
77 | this.canDragBack = canDragBack;
78 | }
79 |
80 | /**
81 | * 事件拦截操作
82 | */
83 | @Override
84 | public boolean onInterceptTouchEvent(MotionEvent ev) {
85 | if (!canDragBack) {
86 | return super.onInterceptTouchEvent(ev);
87 | }
88 |
89 | // 处理ViewPager冲突问题
90 | ViewPager mViewPager = getTouchViewPager(mViewPagers, ev);
91 | // Log.i(TAG, "mViewPager = " + mViewPager);
92 |
93 | if (mViewPager != null && mViewPager.getCurrentItem() != 0) {
94 | return super.onInterceptTouchEvent(ev);
95 | }
96 |
97 | // 处理与cbpullrefreshlistview 的事件冲突
98 | CBPullRefreshListView cbPullRefreshListView = getTouchCBpullrefreshListView(mCbPullRefreshListViews,ev);
99 | if(cbPullRefreshListView!=null&&cbPullRefreshListView.isSwipeMenuOpen()){
100 | return super.onInterceptTouchEvent(ev);
101 | }
102 |
103 | // 暂时不处理gridview
104 | // GridView mGridView = getTouchGridView(mGridViews, ev);
105 | // Log.i(TAG, "mGridView = " + mGridView);
106 | // if (mGridView != null) {
107 | // return super.onInterceptTouchEvent(ev);
108 | // }
109 |
110 | switch (ev.getAction()) {
111 | case MotionEvent.ACTION_DOWN:
112 | downX = tempX = (int) ev.getRawX();
113 | downY = (int) ev.getRawY();
114 | break;
115 | case MotionEvent.ACTION_MOVE:
116 | int moveX = (int) ev.getRawX();
117 | // 满足此条件屏蔽SildingFinishLayout里面子类的touch事件
118 | if (moveX - downX > mTouchSlop && Math.abs((int) ev.getRawY() - downY) < mTouchSlop) {
119 | return true;
120 | }
121 | break;
122 | }
123 |
124 | return super.onInterceptTouchEvent(ev);
125 | }
126 |
127 | @Override
128 | public boolean onTouchEvent(MotionEvent event) {
129 | switch (event.getAction()) {
130 | case MotionEvent.ACTION_MOVE:
131 | int moveX = (int) event.getRawX();
132 | int deltaX = tempX - moveX;
133 | tempX = moveX;
134 | if (moveX - downX > mTouchSlop && Math.abs((int) event.getRawY() - downY) < mTouchSlop) {
135 | isSilding = true;
136 | }
137 |
138 | if (moveX - downX >= 0 && isSilding) {
139 | mContentView.scrollBy(deltaX, 0);
140 | }
141 | break;
142 | case MotionEvent.ACTION_UP:
143 | isSilding = false;
144 | if (mContentView.getScrollX() <= -viewWidth / 2) {
145 | isFinish = true;
146 | scrollRight();
147 | } else {
148 | scrollOrigin();
149 | isFinish = false;
150 | }
151 | break;
152 | }
153 |
154 | return true;
155 | }
156 |
157 | /**
158 | * 获取SwipeBackLayout里面的ViewPager的集合
159 | *
160 | * @param mViewPagers
161 | * @param parent
162 | */
163 | private void getAllViewPager(List mViewPagers, ViewGroup parent) {
164 | int childCount = parent.getChildCount();
165 | for (int i = 0; i < childCount; i++) {
166 | View child = parent.getChildAt(i);
167 | if (child instanceof ViewPager) {
168 | mViewPagers.add((ViewPager) child);
169 | } else if (child instanceof ViewGroup) {
170 | getAllViewPager(mViewPagers, (ViewGroup) child);
171 | }
172 | }
173 | }
174 |
175 | private void getAllGridView(List mGridViews, ViewGroup parent) {
176 | int childCount = parent.getChildCount();
177 | for (int i = 0; i < childCount; i++) {
178 | View child = parent.getChildAt(i);
179 | if (child instanceof GridView) {
180 | mGridViews.add((GridView) child);
181 | } else if (child instanceof ViewGroup) {
182 | getAllGridView(mGridViews, (ViewGroup) child);
183 | }
184 | }
185 | }
186 |
187 | private void getCBpullRefreshListView(ViewGroup parent) {
188 | int childCount = parent.getChildCount();
189 | for (int i = 0; i < childCount; i++) {
190 | View child = parent.getChildAt(i);
191 | if (child instanceof CBPullRefreshListView) {
192 | mCbPullRefreshListViews.add((CBPullRefreshListView) child);
193 | } else if (child instanceof ViewGroup) {
194 | getCBpullRefreshListView((ViewGroup) child);
195 | }
196 | }
197 | }
198 |
199 | private CBPullRefreshListView getTouchCBpullrefreshListView(List cbPullRefreshListViews, MotionEvent ev) {
200 | if (cbPullRefreshListViews == null || cbPullRefreshListViews.size() == 0) {
201 | return null;
202 | }
203 | Rect rect = new Rect();
204 | for (CBPullRefreshListView listview : cbPullRefreshListViews) {
205 | listview.getHitRect(rect);
206 | if (rect.contains((int) ev.getX(), (int) ev.getY())) {
207 | return listview;
208 | }
209 | }
210 | return null;
211 | }
212 |
213 | /**
214 | * 返回我们touch的ViewPager
215 | *
216 | * @param mViewPagers
217 | * @param ev
218 | * @return
219 | */
220 | private ViewPager getTouchViewPager(List mViewPagers, MotionEvent ev) {
221 | if (mViewPagers == null || mViewPagers.size() == 0) {
222 | return null;
223 | }
224 | Rect mRect = new Rect();
225 | for (ViewPager v : mViewPagers) {
226 | v.getHitRect(mRect);
227 |
228 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) {
229 | return v;
230 | }
231 | }
232 | return null;
233 | }
234 |
235 | private GridView getTouchGridView(List mGridViews, MotionEvent ev) {
236 | if (mGridViews == null || mGridViews.size() == 0) {
237 | return null;
238 | }
239 | Rect mRect = new Rect();
240 | for (GridView v : mGridViews) {
241 | v.getHitRect(mRect);
242 |
243 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) {
244 | return v;
245 | }
246 | }
247 | return null;
248 | }
249 |
250 | @Override
251 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
252 | super.onLayout(changed, l, t, r, b);
253 | if (changed) {
254 | viewWidth = this.getWidth();
255 |
256 | getAllViewPager(mViewPagers, this);
257 | // Log.i(TAG, "ViewPager size = " + mViewPagers.size());
258 |
259 | getAllGridView(mGridViews, this);
260 | getCBpullRefreshListView(this);
261 | }
262 | }
263 |
264 | @Override
265 | protected void dispatchDraw(Canvas canvas) {
266 | super.dispatchDraw(canvas);
267 | if (mShadowDrawable != null && mContentView != null) {
268 |
269 | int left = mContentView.getLeft() - mShadowDrawable.getIntrinsicWidth();
270 | int right = left + mShadowDrawable.getIntrinsicWidth();
271 | int top = mContentView.getTop();
272 | int bottom = mContentView.getBottom();
273 |
274 | mShadowDrawable.setBounds(left, top, right, bottom);
275 | mShadowDrawable.draw(canvas);
276 | }
277 |
278 | }
279 |
280 | /**
281 | * 滚动出界面
282 | */
283 | private void scrollRight() {
284 | final int delta = (viewWidth + mContentView.getScrollX());
285 | // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item
286 | mScroller.startScroll(mContentView.getScrollX(), 0, -delta + 1, 0, Math.abs(delta));
287 | postInvalidate();
288 | }
289 |
290 | /**
291 | * 滚动到起始位置
292 | */
293 | private void scrollOrigin() {
294 | int delta = mContentView.getScrollX();
295 | mScroller.startScroll(mContentView.getScrollX(), 0, -delta, 0, Math.abs(delta));
296 | postInvalidate();
297 | }
298 |
299 | @Override
300 | public void computeScroll() {
301 | // 调用startScroll的时候scroller.computeScrollOffset()返回true,
302 | if (mScroller.computeScrollOffset()) {
303 | mContentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
304 | postInvalidate();
305 |
306 | if (mScroller.isFinished() && isFinish) {
307 | mActivity.finish();
308 | /*
309 | if (mActivity.getClass().equals(Content.class)) {
310 | Intent intent = new Intent(mActivity, Main.class);
311 | mActivity.startActivity(intent);
312 | }*/
313 | }
314 | }
315 | }
316 |
317 | }
318 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/DragbackActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.util.TypedValue;
7 | import android.view.Menu;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.AdapterView;
11 | import android.widget.BaseAdapter;
12 | import android.widget.TextView;
13 | import android.widget.Toast;
14 |
15 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
16 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenu;
17 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuCreator;
18 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuItem;
19 |
20 | import java.util.ArrayList;
21 |
22 | /**
23 | * 描述:
24 | * Created by zhaohl on 2016-4-5.
25 | */
26 | public class DragbackActivity extends BaseActivity {
27 | private TestAdapter mAdatper;
28 | private ArrayList DataList = new ArrayList();
29 | private CBPullRefreshListView mListView;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_main);
35 | initData();
36 | initView();
37 | }
38 |
39 | private void initView() {
40 | mListView = (CBPullRefreshListView) findViewById(R.id.listview);
41 | // mListView.setRefreshHeader(new CBRefreshHeader(this));
42 | mListView.setAdapter(mAdatper = new TestAdapter());
43 | mListView.setPullRefreshEnable(true);
44 | mListView.setPullLoadMoreEnable(true);
45 | // mListView.showTobSearchBar(true);
46 | mListView.setOnPullRefreshListener(new CBPullRefreshListView.OnPullRefreshListener() {
47 | @Override
48 | public void onRefresh() {
49 | mListView.postDelayed(new Runnable() {
50 | @Override
51 | public void run() {
52 | mListView.stopRefresh();
53 | }
54 | }, 3000);
55 | }
56 |
57 | @Override
58 | public void onLoadMore() {
59 | mListView.postDelayed(new Runnable() {
60 | @Override
61 | public void run() {
62 | mListView.stopLoadMore();
63 | }
64 | }, 3000);
65 | }
66 |
67 | @Override
68 | public void onUpdateRefreshTime(long time) {
69 |
70 | }
71 |
72 | });
73 | SwipeMenuCreator creator = new SwipeMenuCreator() {
74 |
75 | @Override
76 | public void create(SwipeMenu menu) {
77 |
78 | SwipeMenuItem collectionItem = new SwipeMenuItem(getApplicationContext());
79 | collectionItem.setBackground(R.color.green);
80 | collectionItem.setWidth(dp2px(DragbackActivity.this, 90));
81 | collectionItem.setTitle("收藏");
82 | collectionItem.setTitleSize(18);
83 | collectionItem.setTitleColor(Color.WHITE);
84 | collectionItem.setIcon(R.drawable.icon_collection);
85 | menu.addMenuItem(collectionItem);
86 |
87 | SwipeMenuItem deleteItem = new SwipeMenuItem(getApplicationContext());
88 | deleteItem.setBackground(R.color.red);
89 | deleteItem.setWidth(dp2px(DragbackActivity.this, 90));
90 | deleteItem.setTitle("删除");
91 | deleteItem.setIcon(R.drawable.icon_delete);
92 | deleteItem.setTitleSize(18);
93 | deleteItem.setTitleColor(Color.WHITE);
94 | menu.addMenuItem(deleteItem);
95 | }
96 | };
97 | // set creator
98 | mListView.setMenuCreator(creator);
99 | mListView.setOnMenuItemClickListener(new CBPullRefreshListView.OnMenuItemClickListener() {
100 | @Override
101 | public void onMenuItemClick(int position, SwipeMenu menu, int index) {
102 | Toast.makeText(DragbackActivity.this, "点击了item swipe 菜单的第" + index, Toast.LENGTH_SHORT).show();
103 | }
104 | });
105 | mListView.setOnItemClickListener(new CBPullRefreshListView.OnItemClickListener() {
106 | @Override
107 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
108 | Toast.makeText(DragbackActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
109 | }
110 | });
111 | }
112 |
113 | private void initData() {
114 | for (int i = 0; i < 30; i++) {
115 | DataList.add(new String("this is a cbpullrefreshlistview test" + i));
116 | }
117 | }
118 |
119 |
120 | @Override
121 | public boolean onCreateOptionsMenu(Menu menu) {
122 | getMenuInflater().inflate(R.menu.menu_main, menu);
123 | return true;
124 | }
125 |
126 | class TestAdapter extends BaseAdapter {
127 |
128 |
129 | @Override
130 | public int getCount() {
131 | return DataList == null ? 0 : DataList.size();
132 | }
133 |
134 | @Override
135 | public Object getItem(int position) {
136 | return DataList.get(position);
137 | }
138 |
139 | @Override
140 | public long getItemId(int position) {
141 | return 0;
142 | }
143 |
144 | @Override
145 | public View getView(int position, View convertView, ViewGroup parent) {
146 | ViewHolder viewHolder = null;
147 | if (convertView == null) {
148 | viewHolder = new ViewHolder();
149 | convertView = getLayoutInflater().inflate(R.layout.item_listview2, parent, false);
150 | viewHolder.title = (TextView) convertView.findViewById(R.id.item_title);
151 | convertView.setTag(viewHolder);
152 | } else {
153 | viewHolder = (ViewHolder) convertView.getTag();
154 | }
155 | viewHolder.title.setText(DataList.get(position));
156 | return convertView;
157 | }
158 | }
159 |
160 | class ViewHolder {
161 | TextView title;
162 | }
163 |
164 | public int dp2px(Context context,int dp) {
165 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.util.TypedValue;
9 | import android.view.Menu;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.AdapterView;
14 | import android.widget.BaseAdapter;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import com.zhl.CBPullRefresh.CBPullRefreshListView;
19 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenu;
20 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuCreator;
21 | import com.zhl.CBPullRefresh.SwipeMenu.SwipeMenuItem;
22 |
23 | import java.util.ArrayList;
24 |
25 | public class MainActivity extends AppCompatActivity {
26 | private TestAdapter mAdatper;
27 | private ArrayList DataList = new ArrayList();
28 | private CBPullRefreshListView mListView;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_main);
34 | initData();
35 | initView();
36 | }
37 |
38 | private void initView() {
39 | mListView = (CBPullRefreshListView) findViewById(R.id.listview);
40 | // mListView.setRefreshHeader(new CBRefreshHeader(this));
41 | mListView.setAdapter(mAdatper = new TestAdapter());
42 | mListView.setPullRefreshEnable(true);
43 | mListView.setPullLoadMoreEnable(true);
44 | mListView.setSwipeEnable(true);
45 | mListView.showTopSearchBar(true);
46 | mListView.setOnSearchBarClickListener(new CBPullRefreshListView.OnSearchClickListener() {
47 | @Override
48 | public void onSearchBarClick() {
49 | Toast.makeText(MainActivity.this, "点击了搜索栏", Toast.LENGTH_SHORT).show();
50 | }
51 | });
52 | mListView.setOnPullRefreshListener(new CBPullRefreshListView.OnPullRefreshListener() {
53 | @Override
54 | public void onRefresh() {
55 | mListView.postDelayed(new Runnable() {
56 | @Override
57 | public void run() {
58 | mListView.stopRefresh();
59 | }
60 | }, 3000);
61 | }
62 |
63 | @Override
64 | public void onLoadMore() {
65 | mListView.postDelayed(new Runnable() {
66 | @Override
67 | public void run() {
68 | mListView.stopLoadMore();
69 | }
70 | }, 3000);
71 | }
72 |
73 | @Override
74 | public void onUpdateRefreshTime(long time) {
75 |
76 | }
77 |
78 | });
79 | SwipeMenuCreator creator = new SwipeMenuCreator() {
80 |
81 | @Override
82 | public void create(SwipeMenu menu) {
83 |
84 | SwipeMenuItem collectionItem = new SwipeMenuItem(getApplicationContext());
85 | collectionItem.setBackground(R.color.green);
86 | collectionItem.setWidth(dp2px(MainActivity.this, 90));
87 | collectionItem.setTitle("收藏");
88 | collectionItem.setTitleSize(18);
89 | collectionItem.setTitleColor(Color.WHITE);
90 | collectionItem.setIcon(R.drawable.icon_collection);
91 | menu.addMenuItem(collectionItem);
92 |
93 | SwipeMenuItem deleteItem = new SwipeMenuItem(getApplicationContext());
94 | deleteItem.setBackground(R.color.red);
95 | deleteItem.setWidth(dp2px(MainActivity.this, 90));
96 | deleteItem.setTitle("删除");
97 | deleteItem.setIcon(R.drawable.icon_delete);
98 | deleteItem.setTitleSize(18);
99 | deleteItem.setTitleColor(Color.WHITE);
100 | menu.addMenuItem(deleteItem);
101 | }
102 | };
103 | // set creator
104 | mListView.setMenuCreator(creator);
105 | mListView.setOnMenuItemClickListener(new CBPullRefreshListView.OnMenuItemClickListener() {
106 | @Override
107 | public void onMenuItemClick(int position, SwipeMenu menu, int index) {
108 | Toast.makeText(MainActivity.this, "点击了item swipe 菜单的第" + index, Toast.LENGTH_SHORT).show();
109 | }
110 | });
111 | mListView.setOnItemClickListener(new CBPullRefreshListView.OnItemClickListener() {
112 | @Override
113 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
114 | Toast.makeText(MainActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
115 | }
116 | });
117 | }
118 |
119 | private void initData() {
120 | for (int i = 0; i < 30; i++) {
121 | DataList.add(new String("this is a cbpullrefreshlistview test" + i));
122 | }
123 | }
124 |
125 |
126 | @Override
127 | public boolean onCreateOptionsMenu(Menu menu) {
128 | getMenuInflater().inflate(R.menu.menu_main, menu);
129 | return true;
130 | }
131 |
132 | @Override
133 | public boolean onOptionsItemSelected(MenuItem item) {
134 | switch (item.getItemId()){
135 | case R.id.action_settings:
136 | Intent intent = new Intent(this,DragbackActivity.class);
137 | startActivity(intent);
138 | break;
139 | case R.id.action_custom_header:
140 | Intent intent2 = new Intent(this,CustomRefreshHeaderActivity.class);
141 | startActivity(intent2);
142 | break;
143 | case R.id.action_custom_header2:
144 | Intent intent3 = new Intent(this,CustomRefreshHeaderRippleActivity.class);
145 | startActivity(intent3);
146 | break;
147 | }
148 | return super.onOptionsItemSelected(item);
149 | }
150 |
151 | class TestAdapter extends BaseAdapter {
152 |
153 |
154 | @Override
155 | public int getCount() {
156 | return DataList == null ? 0 : DataList.size();
157 | }
158 |
159 | @Override
160 | public Object getItem(int position) {
161 | return DataList.get(position);
162 | }
163 |
164 | @Override
165 | public long getItemId(int position) {
166 | return 0;
167 | }
168 |
169 | @Override
170 | public View getView(int position, View convertView, ViewGroup parent) {
171 | ViewHolder viewHolder = null;
172 | if (convertView == null) {
173 | viewHolder = new ViewHolder();
174 | convertView = getLayoutInflater().inflate(R.layout.item_listview, parent, false);
175 | viewHolder.title = (TextView) convertView.findViewById(R.id.item_title);
176 | convertView.setTag(viewHolder);
177 | } else {
178 | viewHolder = (ViewHolder) convertView.getTag();
179 | }
180 | viewHolder.title.setText(DataList.get(position));
181 | return convertView;
182 | }
183 | }
184 |
185 | class ViewHolder {
186 | TextView title;
187 | }
188 |
189 | public int dp2px(Context context,int dp) {
190 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/MyCustomRrefreshHeader.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.util.AttributeSet;
6 | import android.util.DisplayMetrics;
7 | import android.util.Log;
8 | import android.view.Gravity;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.widget.ImageView;
12 | import android.widget.LinearLayout;
13 | import android.widget.RelativeLayout;
14 |
15 | import com.wang.avi.AVLoadingIndicatorView;
16 | import com.zhl.CBPullRefresh.CBRefreshHeaderView;
17 | import com.zhl.CBPullRefresh.CBRefreshState;
18 | import com.zhl.CBPullRefresh.utils.Blur;
19 | import com.zhl.CBPullRefresh.utils.BlurUtil;
20 |
21 |
22 | /**
23 | * 描述:
24 | * Created by zhaohl on 2016-4-6.
25 | */
26 | public class MyCustomRrefreshHeader extends CBRefreshHeaderView {
27 | private LinearLayout mHeaderContanier;
28 | private RelativeLayout mHeaderContent;
29 | private ImageView blurView;
30 | private View blurContentView;
31 | private AVLoadingIndicatorView indicatorView;
32 | private ImageView rotateView;
33 | private int State;
34 | private Context context;
35 | private int mScreenW,mScreenH;
36 |
37 |
38 | public MyCustomRrefreshHeader(Context context) {
39 | this(context, null);
40 | }
41 |
42 | public MyCustomRrefreshHeader(Context context, AttributeSet attrs) {
43 | this(context, attrs, -1);
44 | }
45 |
46 | public MyCustomRrefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {
47 | super(context, attrs, defStyleAttr);
48 | init(context);
49 | }
50 |
51 | private void init(Context context) {
52 | this.context = context;
53 | DisplayMetrics metrics = context.getResources().getDisplayMetrics();
54 | mScreenW = metrics.widthPixels;
55 | mScreenH = metrics.heightPixels;
56 | // 初始情况,设置下拉刷新view高度为0
57 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0);
58 | mHeaderContanier = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.my_custom_header,null);
59 | mHeaderContent = (RelativeLayout) mHeaderContanier.findViewById(R.id.header_content);
60 | indicatorView = (AVLoadingIndicatorView) mHeaderContanier.findViewById(R.id.avloadingIndicatorView);
61 | rotateView = (ImageView) mHeaderContanier.findViewById(R.id.rotate_icon);
62 | startBlur(0);
63 | addView(mHeaderContanier,lp);
64 | setGravity(Gravity.BOTTOM);
65 | }
66 |
67 | @Override
68 | public void setState(int state) {
69 | this.State = state;
70 | }
71 |
72 | @Override
73 | public void onDragSlide(float deltaY) {
74 | Log.i("mytag", "--------deltaY===========" + deltaY);
75 | if(deltaY>0f){
76 | if(State!= CBRefreshState.STATE_REFRESHING){
77 | startRotae(deltaY);
78 | startBlur(deltaY/1000);
79 | }
80 | }else{
81 | clearBlurImage();
82 | }
83 | }
84 |
85 | private void startRotae(float deltaY) {
86 | rotateView.setRotation(deltaY);
87 | }
88 |
89 | @Override
90 | public void pullToRefresh() {
91 | rotateView.setVisibility(View.VISIBLE);
92 | indicatorView.setVisibility(View.INVISIBLE);
93 | }
94 |
95 | @Override
96 | public void releaseToRefresh() {
97 | super.releaseToRefresh();
98 | }
99 |
100 | @Override
101 | public void onRefreshing() {
102 | rotateView.setVisibility(View.INVISIBLE);
103 | indicatorView.setVisibility(View.VISIBLE);
104 | }
105 |
106 | @Override
107 | public void setVisiableHeight(int height) {
108 | if(height<0){
109 | height = 0;
110 | }
111 | LinearLayout.LayoutParams params = (LayoutParams) mHeaderContanier.getLayoutParams();
112 | params.height = height;
113 | mHeaderContanier.setLayoutParams(params);
114 | }
115 |
116 | @Override
117 | public int getVisiableHeight() {
118 | return mHeaderContanier.getHeight();
119 | }
120 |
121 | @Override
122 | public int getRealHeaderContentHeight() {
123 | // 因为container刚开始设置的高度为0所以这里要获取mHeaderContent的高度为真实高度
124 | if(mHeaderContent!=null){
125 | return mHeaderContent.getHeight();
126 | }
127 | return 0;
128 | }
129 |
130 | @Override
131 | public void setPullRefreshEnable(boolean enable) {
132 | if(enable){
133 | mHeaderContanier.setVisibility(View.VISIBLE);
134 | }else{
135 | mHeaderContanier.setVisibility(View.INVISIBLE);
136 | }
137 | }
138 |
139 |
140 | private void clearBlurImage() {
141 | if(blurView!=null){
142 | blurView.setVisibility(View.GONE);
143 | blurView.setImageBitmap(null);
144 | }
145 | }
146 |
147 | private void startBlur(float slideOffset) {
148 | if(slideOffset>1){
149 | return;
150 | }
151 | if(blurContentView==null||blurView==null){
152 | return;
153 | }
154 | if (blurView.getVisibility() != View.VISIBLE) {
155 | blurView.setImageBitmap(null);
156 | blurView.setVisibility(View.VISIBLE);
157 | Bitmap downScaled = BlurUtil.drawViewToBitmap(blurContentView,
158 | mScreenW, mScreenH, 5);
159 | Bitmap blurred = Blur.apply(context, downScaled, 20);
160 | blurView.setImageBitmap(blurred);
161 | downScaled.recycle();
162 | }
163 | BlurUtil.setAlpha(blurView, 1-slideOffset);
164 | }
165 |
166 | public void setBlurView(View contentView,ImageView BlurView){
167 | this.blurContentView = contentView;
168 | this.blurView = BlurView;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zhl/cbpullrefreshlistview/MyCustomRrefreshHeaderRippleColor.java:
--------------------------------------------------------------------------------
1 | package com.zhl.cbpullrefreshlistview;
2 |
3 | import android.animation.ArgbEvaluator;
4 | import android.animation.ObjectAnimator;
5 | import android.content.Context;
6 | import android.util.AttributeSet;
7 | import android.util.DisplayMetrics;
8 | import android.util.Log;
9 | import android.view.Gravity;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.widget.FrameLayout;
13 | import android.widget.ImageView;
14 | import android.widget.LinearLayout;
15 |
16 | import com.rodolfonavalon.shaperipplelibrary.ShapeRipple;
17 | import com.wang.avi.AVLoadingIndicatorView;
18 | import com.zhl.CBPullRefresh.CBRefreshHeaderView;
19 | import com.zhl.CBPullRefresh.CBRefreshState;
20 |
21 |
22 | /**
23 | * 描述:
24 | * Created by zhaohl on 2016-4-6.
25 | */
26 | public class MyCustomRrefreshHeaderRippleColor extends CBRefreshHeaderView {
27 | private LinearLayout mHeaderContanier;
28 | private FrameLayout mHeaderContent;
29 | private AVLoadingIndicatorView indicatorView;
30 | private ShapeRipple shapeRipple;
31 | private ImageView rotateView;
32 | private int State;
33 | private Context context;
34 | private int mScreenW,mScreenH;
35 | private int duration = 1500;
36 | private ObjectAnimator colorAnimator;
37 |
38 |
39 | public MyCustomRrefreshHeaderRippleColor(Context context) {
40 | this(context, null);
41 | }
42 |
43 | public MyCustomRrefreshHeaderRippleColor(Context context, AttributeSet attrs) {
44 | this(context, attrs, -1);
45 | }
46 |
47 | public MyCustomRrefreshHeaderRippleColor(Context context, AttributeSet attrs, int defStyleAttr) {
48 | super(context, attrs, defStyleAttr);
49 | init(context);
50 | }
51 |
52 | private void init(Context context) {
53 | this.context = context;
54 | DisplayMetrics metrics = context.getResources().getDisplayMetrics();
55 | mScreenW = metrics.widthPixels;
56 | mScreenH = metrics.heightPixels;
57 | // 初始情况,设置下拉刷新view高度为0
58 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
59 | mHeaderContanier = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.my_custom_header_ripplecolor,null);
60 | mHeaderContent = (FrameLayout) mHeaderContanier.findViewById(R.id.header_content);
61 | indicatorView = (AVLoadingIndicatorView) mHeaderContanier.findViewById(R.id.avloadingIndicatorView);
62 | rotateView = (ImageView) mHeaderContanier.findViewById(R.id.rotate_icon);
63 | shapeRipple = (ShapeRipple) mHeaderContanier.findViewById(R.id.shape_ripple);
64 | shapeRipple.setEnableColorTransition(true);
65 | shapeRipple.setEnableRandomPosition(true);
66 | shapeRipple.setEnableRandomColor(true);
67 | // shapeRipple.setRippleShape(new Square());
68 | shapeRipple.setRippleInterval(1);
69 | shapeRipple.setRippleDuration(duration);
70 | shapeRipple.stopRipple();
71 | // initColorAnim();
72 | addView(mHeaderContanier,lp);
73 | setGravity(Gravity.BOTTOM);
74 | }
75 |
76 | private void initColorAnim() {
77 | colorAnimator = ObjectAnimator.ofObject(mHeaderContent,"backgroundColor",new ArgbEvaluator(),0xEFFAFAFA,0x55DE8DAB);
78 | colorAnimator.setDuration(8000);
79 | colorAnimator.setRepeatMode(ObjectAnimator.REVERSE);
80 | colorAnimator.setRepeatCount(ObjectAnimator.INFINITE);
81 | }
82 |
83 | @Override
84 | public void setState(int state) {
85 | this.State = state;
86 | }
87 |
88 | @Override
89 | public void onDragSlide(float deltaY) {
90 | Log.i("MyTag", "--------deltaY===========" + deltaY);
91 | if(deltaY>0&&State!= CBRefreshState.STATE_REFRESHING){
92 | startRotae(deltaY);
93 | }
94 | }
95 |
96 | private void startRotae(float deltaY) {
97 | rotateView.setRotation(deltaY);
98 | }
99 |
100 | @Override
101 | public void pullToRefresh() {
102 | rotateView.setVisibility(View.VISIBLE);
103 | indicatorView.setVisibility(View.INVISIBLE);
104 | shapeRipple.stopRipple();
105 | }
106 |
107 | @Override
108 | public void releaseToRefresh() {
109 | shapeRipple.stopRipple();
110 | }
111 |
112 | @Override
113 | public void onRefreshing() {
114 | rotateView.setVisibility(View.INVISIBLE);
115 | indicatorView.setVisibility(View.VISIBLE);
116 | shapeRipple.startRipple();
117 | }
118 |
119 | @Override
120 | public void setVisiableHeight(int height) {
121 | if(height<0){
122 | height = 0;
123 | }
124 | LayoutParams params = (LayoutParams) mHeaderContanier.getLayoutParams();
125 | params.height = height;
126 | mHeaderContanier.setLayoutParams(params);
127 | }
128 |
129 | @Override
130 | public int getVisiableHeight() {
131 | return mHeaderContanier.getHeight();
132 | }
133 |
134 | @Override
135 | public int getRealHeaderContentHeight() {
136 | // 因为container刚开始设置的高度为0所以这里要获取mHeaderContent的高度为真实高度
137 | if(mHeaderContent!=null){
138 | return mHeaderContent.getHeight();
139 | }
140 | return 0;
141 | }
142 |
143 | @Override
144 | public void setPullRefreshEnable(boolean enable) {
145 | if(enable){
146 | mHeaderContanier.setVisibility(View.VISIBLE);
147 | }else{
148 | mHeaderContanier.setVisibility(View.INVISIBLE);
149 | }
150 | }
151 |
152 |
153 |
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/app_logo_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-hdpi/app_logo_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/item_icon_girl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-hdpi/item_icon_girl.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/app_logo_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/app_logo_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/icon_collection.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/icon_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_header_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/icon_header_refresh.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/item_icon_girl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/item_icon_girl.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/item_icon_girl2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/item_icon_girl2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/item_icon_girl3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/item_icon_girl3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/top_header_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/app/src/main/res/drawable-xhdpi/top_header_bg.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/swipeback_shadow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_custom_header_layout.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
15 |
21 |
22 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_custom_header_layout_ripple.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/base.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_listview.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_listview2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_listview3.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/my_custom_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
24 |
25 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/my_custom_header_ripplecolor.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
19 |
20 |
29 |
30 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/mylistview_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
16 |
22 |
23 |
30 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4ea6ed
4 | #e8e8e8
5 | #33000001
6 | #00000000
7 | #19BF80
8 | #ffffff
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CBPullRefreshListView
3 |
4 | Hello world!
5 | 滑动返回的activity
6 | 自定义刷新头
7 | 自定义刷新头2
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.3'
9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 |
14 | }
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/custom_ripple.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/custom_ripple.gif
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.useDeprecatedNdk=true
20 | #gradlew clean build bintrayUpload -PbintrayUser=yilylong -PbintrayKey=xxxxxx -PdryRun=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yilylong/CBPullRefreshListView/c5c4826df767c5d6c9b48f4480143e06e3c56069/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Jun 26 14:43:52 CST 2017
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-3.3-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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':CBPullRefresh'
2 |
--------------------------------------------------------------------------------