GridView基于pulltorefresh实现下拉刷新 上拉加载更多功能

举报
再见孙悟空_ 发表于 2022/01/13 01:05:27 2022/01/13
【摘要】 原理和listview一样 ,都是重写android原生控件 Activity package com.example.refreshgridview; import java.util.ArrayList;import java.util.List; import android.app.Activity;import a...

原理和listview一样 ,都是重写android原生控件

Activity


  
  1. package com.example.refreshgridview;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.app.Activity;
  5. import android.os.Bundle;
  6. import android.widget.GridView;
  7. import android.widget.Toast;
  8. import com.example.refreshgridview.PullToRefreshBase.OnRefreshListener;
  9. public class MainActivity extends Activity {
  10. private PullToRefreshGridView mPullRefreshGridView;
  11. private GridView mGridView;
  12. private GridViewAdapter adapter;
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17. mPullRefreshGridView = (PullToRefreshGridView) findViewById(R.id.video_gridView);
  18. mPullRefreshGridView.init(PullToRefreshGridView.MODE_BOTH);
  19. mGridView = mPullRefreshGridView.getRefreshableView();
  20. mPullRefreshGridView.setOnRefreshListener(refreshListener);
  21. List<String> list = new ArrayList<String>();
  22. for (int i = 0; i < 40; i++) {
  23. list.add(i+"");
  24. }
  25. adapter = new GridViewAdapter(MainActivity.this,list);
  26. mGridView.setAdapter(adapter);
  27. }
  28. private OnRefreshListener refreshListener = new OnRefreshListener() {
  29. @Override
  30. public void onRefresh(int mode) {
  31. if (PullToRefreshGridView.MODE_PULL_DOWN_TO_REFRESH == mPullRefreshGridView.getCurrentMode()) {
  32. Toast.makeText(MainActivity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
  33. mPullRefreshGridView.onRefreshComplete();
  34. } else if (mode == PullToRefreshGridView.MODE_PULL_UP_TO_REFRESH) {
  35. // 加载更多
  36. Toast.makeText(MainActivity.this, "上拉加载更多", Toast.LENGTH_SHORT).show();
  37. mPullRefreshGridView.onRefreshComplete();
  38. }
  39. }
  40. };
  41. }

adapter


  
  1. package com.example.refreshgridview;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.text.TextUtils;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.BaseAdapter;
  11. import android.widget.TextView;
  12. public class GridViewAdapter extends BaseAdapter {
  13. private List<String> mList = new ArrayList<String>();
  14. private Context mContext;
  15. public GridViewAdapter(Context context,List<String> list) {
  16. super();
  17. this.mContext = context;
  18. this.mList = list;
  19. }
  20. @Override
  21. public int getCount() {
  22. return mList.size();
  23. }
  24. @Override
  25. public String getItem(int position) {
  26. return mList.get(position);
  27. }
  28. @Override
  29. public long getItemId(int position) {
  30. return position;
  31. }
  32. @Override
  33. public View getView(int position, View convertView, ViewGroup parent) {
  34. ChildHolderOne holder;
  35. if (convertView == null) {
  36. convertView = LayoutInflater.from(mContext).inflate(R.layout.item_grid_live_show, parent, false);
  37. holder = new ChildHolderOne();
  38. holder.tvTitle = (TextView)convertView.findViewById(R.id.title_tv);
  39. convertView.setTag(holder);
  40. } else {
  41. holder = (ChildHolderOne) convertView.getTag();
  42. }
  43. return convertView;
  44. }
  45. class ChildHolderOne {
  46. TextView tvTitle;
  47. }
  48. }


PullToRefreshGridView


  
  1. package com.example.refreshgridview;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.ContextMenu.ContextMenuInfo;
  5. import android.view.View;
  6. import android.widget.GridView;
  7. public class PullToRefreshGridView extends PullToRefreshAdapterViewBase<GridView> {
  8. class InternalGridView extends GridView implements EmptyViewMethodAccessor {
  9. public InternalGridView(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11. }
  12. @Override
  13. public void setEmptyView(View emptyView) {
  14. PullToRefreshGridView.this.setEmptyView(emptyView);
  15. }
  16. @Override
  17. public void setEmptyViewInternal(View emptyView) {
  18. super.setEmptyView(emptyView);
  19. }
  20. @Override
  21. public ContextMenuInfo getContextMenuInfo() {
  22. return super.getContextMenuInfo();
  23. }
  24. }
  25. public PullToRefreshGridView(Context context) {
  26. super(context);
  27. }
  28. public PullToRefreshGridView(Context context, int mode) {
  29. super(context, mode);
  30. }
  31. public PullToRefreshGridView(Context context, AttributeSet attrs) {
  32. super(context, attrs);
  33. }
  34. @Override
  35. protected final GridView createRefreshableView(Context context, AttributeSet attrs) {
  36. GridView gv = new InternalGridView(context, attrs);
  37. // Use Generated ID (from res/values/ids.xml)
  38. gv.setId(R.id.gridview);
  39. return gv;
  40. }
  41. @Override
  42. public ContextMenuInfo getContextMenuInfo() {
  43. return ((InternalGridView) getRefreshableView()).getContextMenuInfo();
  44. }
  45. }

PullToRefreshBase


  
  1. package com.example.refreshgridview;
  2. import android.content.Context;
  3. import android.os.Handler;
  4. import android.util.AttributeSet;
  5. import android.view.MotionEvent;
  6. import android.view.View;
  7. import android.view.ViewConfiguration;
  8. import android.view.ViewGroup;
  9. import android.view.animation.AccelerateDecelerateInterpolator;
  10. import android.view.animation.Interpolator;
  11. import android.widget.LinearLayout;
  12. import android.widget.TextView;
  13. /**
  14. *
  15. * @author zlw
  16. */
  17. public abstract class PullToRefreshBase<T extends View> extends LinearLayout {
  18. final class SmoothScrollRunnable implements Runnable {
  19. static final int ANIMATION_DURATION_MS = 190;
  20. static final int ANIMATION_FPS = 1000 / 60;
  21. private final Interpolator interpolator;
  22. private final int scrollToY;
  23. private final int scrollFromY;
  24. private final Handler handler;
  25. private boolean continueRunning = true;
  26. private long startTime = -1;
  27. private int currentY = -1;
  28. public SmoothScrollRunnable(Handler handler, int fromY, int toY) {
  29. this.handler = handler;
  30. this.scrollFromY = fromY;
  31. this.scrollToY = toY;
  32. this.interpolator = new AccelerateDecelerateInterpolator();
  33. }
  34. @Override
  35. public void run() {
  36. /**
  37. * Only set startTime if this is the first time we're starting, else
  38. * actually calculate the Y delta
  39. */
  40. if (startTime == -1) {
  41. startTime = System.currentTimeMillis();
  42. } else {
  43. /**
  44. * We do do all calculations in long to reduce software float
  45. * calculations. We use 1000 as it gives us good accuracy and
  46. * small rounding errors
  47. */
  48. long normalizedTime = (1000 * (System.currentTimeMillis() - startTime))
  49. / ANIMATION_DURATION_MS;
  50. normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);
  51. final int deltaY = Math
  52. .round((scrollFromY - scrollToY)
  53. * interpolator
  54. .getInterpolation(normalizedTime / 1000f));
  55. this.currentY = scrollFromY - deltaY;
  56. setHeaderScroll(currentY);
  57. }
  58. // If we're not at the target Y, keep going...
  59. if (continueRunning && scrollToY != currentY) {
  60. handler.postDelayed(this, ANIMATION_FPS);
  61. }
  62. }
  63. public void stop() {
  64. this.continueRunning = false;
  65. this.handler.removeCallbacks(this);
  66. }
  67. };
  68. // ===========================================================
  69. // Constants
  70. // ===========================================================
  71. static final float FRICTION = 2.0f;
  72. static final int PULL_TO_REFRESH = 0x0;
  73. static final int RELEASE_TO_REFRESH = 0x1;
  74. static final int REFRESHING = 0x2;
  75. static final int MANUAL_REFRESHING = 0x3;
  76. public static final int MODE_PULL_DOWN_TO_REFRESH = 0x1;
  77. public static final int MODE_PULL_UP_TO_REFRESH = 0x2;
  78. public static final int MODE_BOTH = 0x3;
  79. // ===========================================================
  80. // Fields
  81. // ===========================================================
  82. private int touchSlop;
  83. private float initialMotionY;
  84. private float lastMotionX;
  85. private float lastMotionY;
  86. private boolean isBeingDragged = false;
  87. private int state = PULL_TO_REFRESH;
  88. private int mode = MODE_PULL_UP_TO_REFRESH;
  89. private int currentMode;
  90. private boolean disableScrollingWhileRefreshing = true;
  91. T refreshableView;
  92. private boolean isPullToRefreshEnabled = true;
  93. private LoadingLayout headerLayout;
  94. private LoadingLayout footerLayout;
  95. private int headerHeight;
  96. private final Handler handler = new Handler();
  97. private OnRefreshListener onRefreshListener;
  98. private SmoothScrollRunnable currentSmoothScrollRunnable;
  99. // ===========================================================
  100. // Constructors
  101. // ===========================================================
  102. public PullToRefreshBase(Context context) {
  103. super(context);
  104. init(context, null);
  105. }
  106. public PullToRefreshBase(Context context, int mode) {
  107. super(context);
  108. this.mode = mode;
  109. init(context, null);
  110. }
  111. public PullToRefreshBase(Context context, AttributeSet attrs) {
  112. super(context, attrs);
  113. init(context, attrs);
  114. }
  115. // ===========================================================
  116. // Getter & Setter
  117. // ===========================================================
  118. /**
  119. * Deprecated. Use {@link #getRefreshableView()} from now on.
  120. *
  121. * @deprecated
  122. * @return The Refreshable View which is currently wrapped
  123. */
  124. public final T getAdapterView() {
  125. return refreshableView;
  126. }
  127. /**
  128. * Get the Wrapped Refreshable View. Anything returned here has already been
  129. * added to the content view.
  130. *
  131. * @return The View which is currently wrapped
  132. */
  133. public final T getRefreshableView() {
  134. return refreshableView;
  135. }
  136. /**
  137. * Whether Pull-to-Refresh is enabled
  138. *
  139. * @return enabled
  140. */
  141. public final boolean isPullToRefreshEnabled() {
  142. return isPullToRefreshEnabled;
  143. }
  144. /**
  145. * Returns whether the widget has disabled scrolling on the Refreshable View
  146. * while refreshing.
  147. *
  148. * @return true if the widget has disabled scrolling while refreshing
  149. */
  150. public final boolean isDisableScrollingWhileRefreshing() {
  151. return disableScrollingWhileRefreshing;
  152. }
  153. /**
  154. * Returns whether the Widget is currently in the Refreshing state
  155. *
  156. * @return true if the Widget is currently refreshing
  157. */
  158. public final boolean isRefreshing() {
  159. return state == REFRESHING || state == MANUAL_REFRESHING;
  160. }
  161. /**
  162. * By default the Widget disabled scrolling on the Refreshable View while
  163. * refreshing. This method can change this behaviour.
  164. *
  165. * @param disableScrollingWhileRefreshing
  166. * - true if you want to disable scrolling while refreshing
  167. */
  168. public final void setDisableScrollingWhileRefreshing(
  169. boolean disableScrollingWhileRefreshing) {
  170. this.disableScrollingWhileRefreshing = disableScrollingWhileRefreshing;
  171. }
  172. /**
  173. * Mark the current Refresh as complete. Will Reset the UI and hide the
  174. * Refreshing View
  175. */
  176. public final void onRefreshComplete() {
  177. if (state != PULL_TO_REFRESH) {
  178. resetHeader();
  179. if (onShowLayoutListener != null) {
  180. onShowLayoutListener.onDismiss();
  181. }
  182. }
  183. }
  184. /**
  185. * Set OnRefreshListener for the Widget
  186. *
  187. * @param listener
  188. * - Listener to be used when the Widget is set to Refresh
  189. */
  190. public final void setOnRefreshListener(OnRefreshListener listener) {
  191. onRefreshListener = listener;
  192. }
  193. /**
  194. * auto load headerLayout to refresh
  195. *
  196. * @param listener
  197. */
  198. public final void setFirstAutoPullUpToRefresh(OnRefreshListener listener) {
  199. setRefreshingInternal(true, MODE_PULL_DOWN_TO_REFRESH);
  200. listener.onRefresh(MODE_PULL_DOWN_TO_REFRESH);
  201. }
  202. /**
  203. * set refreshLable , default use null
  204. *
  205. * @param pullLabel
  206. * @param releaseLabel
  207. * @param refreshingLabel
  208. */
  209. public void setRefreshLabel(String pullLabel, String releaseLabel,
  210. String refreshingLabel) {
  211. if (pullLabel != null) {
  212. setPullLabel(pullLabel);
  213. }
  214. if (releaseLabel != null) {
  215. setReleaseLabel(releaseLabel);
  216. }
  217. if (refreshingLabel != null) {
  218. setRefreshingLabel(refreshingLabel);
  219. }
  220. }
  221. /**
  222. * A mutator to enable/disable Pull-to-Refresh for the current View
  223. *
  224. * @param enable
  225. * Whether Pull-To-Refresh should be used
  226. */
  227. public final void setPullToRefreshEnabled(boolean enable) {
  228. this.isPullToRefreshEnabled = enable;
  229. }
  230. /**
  231. * Set Text to show when the Widget is being pulled, and will refresh when
  232. * released
  233. *
  234. * @param releaseLabel
  235. * - String to display
  236. */
  237. private void setReleaseLabel(String releaseLabel) {
  238. if (null != headerLayout) {
  239. headerLayout.setReleaseLabel(releaseLabel);
  240. }
  241. if (null != footerLayout) {
  242. footerLayout.setReleaseLabel(releaseLabel);
  243. }
  244. }
  245. /**
  246. * Set Text to show when the Widget is being Pulled
  247. *
  248. * @param pullLabel
  249. * - String to display
  250. */
  251. private void setPullLabel(String pullLabel) {
  252. if (null != headerLayout) {
  253. headerLayout.setPullLabel(pullLabel);
  254. }
  255. if (null != footerLayout) {
  256. footerLayout.setPullLabel(pullLabel);
  257. }
  258. }
  259. /**
  260. * Set Text to show when the Widget is refreshing
  261. *
  262. * @param refreshingLabel
  263. * - String to display
  264. */
  265. private void setRefreshingLabel(String refreshingLabel) {
  266. if (null != headerLayout) {
  267. headerLayout.setRefreshingLabel(refreshingLabel);
  268. }
  269. if (null != footerLayout) {
  270. footerLayout.setRefreshingLabel(refreshingLabel);
  271. }
  272. }
  273. public final void setRefreshing() {
  274. this.setRefreshing(true);
  275. }
  276. /**
  277. * Sets the Widget to be in the refresh state. The UI will be updated to
  278. * show the 'Refreshing' view.
  279. *
  280. * @param doScroll
  281. * - true if you want to force a scroll to the Refreshing view.
  282. */
  283. public final void setRefreshing(boolean doScroll) {
  284. if (!isRefreshing()) {
  285. setRefreshingInternal(doScroll);
  286. state = MANUAL_REFRESHING;
  287. }
  288. }
  289. public final boolean hasPullFromTop() {
  290. return currentMode != MODE_PULL_UP_TO_REFRESH;
  291. }
  292. // ===========================================================
  293. // Methods for/from SuperClass/Interfaces
  294. // ===========================================================
  295. @Override
  296. public final boolean onTouchEvent(MotionEvent event) {
  297. if (!isPullToRefreshEnabled) {
  298. return false;
  299. }
  300. if (isRefreshing() && disableScrollingWhileRefreshing) {
  301. return true;
  302. }
  303. if (event.getAction() == MotionEvent.ACTION_DOWN
  304. && event.getEdgeFlags() != 0) {
  305. return false;
  306. }
  307. switch (event.getAction()) {
  308. case MotionEvent.ACTION_MOVE: {
  309. if (isBeingDragged) {
  310. if (Math.abs(event.getY() - downLocation) > 5
  311. && onShowLayoutListener != null) {
  312. onShowLayoutListener.onShow();
  313. }
  314. lastMotionY = event.getY();
  315. this.pullEvent();
  316. return true;
  317. }
  318. break;
  319. }
  320. case MotionEvent.ACTION_DOWN: {
  321. if (isReadyForPull()) {
  322. downLocation = event.getY();
  323. lastMotionY = initialMotionY = event.getY();
  324. return true;
  325. }
  326. break;
  327. }
  328. case MotionEvent.ACTION_CANCEL:
  329. case MotionEvent.ACTION_UP: {
  330. if (isBeingDragged) {
  331. isBeingDragged = false;
  332. if (state == RELEASE_TO_REFRESH && null != onRefreshListener) {
  333. setRefreshingInternal(true);
  334. onRefreshListener.onRefresh(currentMode);
  335. } else {
  336. smoothScrollTo(0);
  337. if (onShowLayoutListener != null) {
  338. onShowLayoutListener.onDismiss();
  339. }
  340. }
  341. return true;
  342. }
  343. break;
  344. }
  345. }
  346. return false;
  347. }
  348. // remeber to down location
  349. private float downLocation = 0;
  350. @Override
  351. public final boolean onInterceptTouchEvent(MotionEvent event) {
  352. if (!isPullToRefreshEnabled) {
  353. return false;
  354. }
  355. if (isRefreshing() && disableScrollingWhileRefreshing) {
  356. return true;
  357. }
  358. final int action = event.getAction();
  359. if (action == MotionEvent.ACTION_CANCEL
  360. || action == MotionEvent.ACTION_UP) {
  361. isBeingDragged = false;
  362. return false;
  363. }
  364. if (action != MotionEvent.ACTION_DOWN && isBeingDragged) {
  365. return true;
  366. }
  367. switch (action) {
  368. case MotionEvent.ACTION_MOVE: {
  369. if (isReadyForPull()) {
  370. final float y = event.getY();
  371. final float dy = y - lastMotionY;
  372. final float yDiff = Math.abs(dy);
  373. final float xDiff = Math.abs(event.getX() - lastMotionX);
  374. if (yDiff > touchSlop && yDiff > xDiff) {
  375. if ((mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH)
  376. && dy >= 0.0001f && isReadyForPullDown()) {
  377. lastMotionY = y;
  378. isBeingDragged = true;
  379. if (mode == MODE_BOTH) {
  380. currentMode = MODE_PULL_DOWN_TO_REFRESH;
  381. }
  382. } else if ((mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH)
  383. && dy <= 0.0001f && isReadyForPullUp()) {
  384. lastMotionY = y;
  385. isBeingDragged = true;
  386. if (mode == MODE_BOTH) {
  387. currentMode = MODE_PULL_UP_TO_REFRESH;
  388. }
  389. }
  390. }
  391. }
  392. break;
  393. }
  394. case MotionEvent.ACTION_DOWN: {
  395. if (isReadyForPull()) {
  396. lastMotionY = initialMotionY = event.getY();
  397. lastMotionX = event.getX();
  398. isBeingDragged = false;
  399. }
  400. break;
  401. }
  402. case MotionEvent.ACTION_UP:
  403. break;
  404. }
  405. setRefreshLabel(currentMode);
  406. return isBeingDragged;
  407. }
  408. protected void addRefreshableView(Context context, T refreshableView) {
  409. addView(refreshableView, new LinearLayout.LayoutParams(
  410. LayoutParams.FILL_PARENT, 0, 1.0f));
  411. }
  412. /**
  413. * This is implemented by derived classes to return the created View. If you
  414. * need to use a custom View (such as a custom ListView), override this
  415. * method and return an instance of your custom class.
  416. *
  417. * Be sure to set the ID of the view in this method, especially if you're
  418. * using a ListActivity or ListFragment.
  419. *
  420. * @param context
  421. * @param attrs
  422. * AttributeSet from wrapped class. Means that anything you
  423. * include in the XML layout declaration will be routed to the
  424. * created View
  425. * @return New instance of the Refreshable View
  426. */
  427. protected abstract T createRefreshableView(Context context,
  428. AttributeSet attrs);
  429. public final int getCurrentMode() {
  430. return currentMode;
  431. }
  432. protected final LoadingLayout getFooterLayout() {
  433. return footerLayout;
  434. }
  435. protected final LoadingLayout getHeaderLayout() {
  436. return headerLayout;
  437. }
  438. protected final int getHeaderHeight() {
  439. return headerHeight;
  440. }
  441. protected final int getMode() {
  442. return mode;
  443. }
  444. /**
  445. * Implemented by derived class to return whether the View is in a state
  446. * where the user can Pull to Refresh by scrolling down.
  447. *
  448. * @return true if the View is currently the correct state (for example, top
  449. * of a ListView)
  450. */
  451. protected abstract boolean isReadyForPullDown();
  452. /**
  453. * Implemented by derived class to return whether the View is in a state
  454. * where the user can Pull to Refresh by scrolling up.
  455. *
  456. * @return true if the View is currently in the correct state (for example,
  457. * bottom of a ListView)
  458. */
  459. protected abstract boolean isReadyForPullUp();
  460. // ===========================================================
  461. // Methods
  462. // ===========================================================
  463. protected void resetHeader() {
  464. state = PULL_TO_REFRESH;
  465. isBeingDragged = false;
  466. if (null != headerLayout) {
  467. headerLayout.reset();
  468. }
  469. if (null != footerLayout) {
  470. footerLayout.reset();
  471. }
  472. smoothScrollTo(0);
  473. }
  474. /**
  475. * unless special requirements to call the method ,default call the method
  476. * {@link #setRefreshingInternal(boolean doScroll)}
  477. *
  478. * @param doScroll
  479. * @param mode
  480. */
  481. protected void setRefreshingInternal(boolean doScroll, int mode) {
  482. state = REFRESHING;
  483. setRefreshLabel(mode);
  484. if (null != headerLayout) {
  485. headerLayout.refreshing();
  486. }
  487. if (doScroll) {
  488. smoothScrollTo(mode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight
  489. : headerHeight);
  490. }
  491. }
  492. /**
  493. * set last refresh time
  494. *
  495. * @param time
  496. */
  497. public void setRefreshTime(String time) {
  498. TextView mHeaderTimeView = (TextView) headerLayout
  499. .findViewById(R.id.xlistview_header_time);
  500. mHeaderTimeView.setText(time);
  501. }
  502. public void setRefreshTime(long time){
  503. TextView mHeaderTimeView = (TextView) headerLayout
  504. .findViewById(R.id.xlistview_header_time);
  505. mHeaderTimeView.setText(TimeUtil.getChatTime(time));
  506. }
  507. protected void setRefreshingInternal(boolean doScroll) {
  508. state = REFRESHING;
  509. setRefreshLabel(currentMode);
  510. if (null != footerLayout) {
  511. footerLayout.refreshing();
  512. }
  513. if (null != headerLayout) {
  514. headerLayout.refreshing();
  515. }
  516. if (doScroll) {
  517. smoothScrollTo(currentMode == MODE_PULL_DOWN_TO_REFRESH ? -headerHeight
  518. : headerHeight);
  519. }
  520. }
  521. private void setRefreshLabel(int mode) {
  522. if (mode == MODE_PULL_DOWN_TO_REFRESH) {
  523. setRefreshLabel("涓嬫媺鍒锋柊", "閲婃斁绔嬪嵆鍒锋柊", "姝e湪鍒锋柊");
  524. }
  525. if (mode == MODE_PULL_UP_TO_REFRESH) {
  526. setRefreshLabel("涓婃媺鑾峰彇鏇村", "鏉惧紑鏄剧ず鏇村", "姝e湪鍔犺浇");
  527. }
  528. }
  529. protected final void setHeaderScroll(int y) {
  530. scrollTo(0, y);
  531. }
  532. protected final void smoothScrollTo(int y) {
  533. if (null != currentSmoothScrollRunnable) {
  534. currentSmoothScrollRunnable.stop();
  535. }
  536. if (this.getScrollY() != y) {
  537. this.currentSmoothScrollRunnable = new SmoothScrollRunnable(
  538. handler, getScrollY(), y);
  539. handler.post(currentSmoothScrollRunnable);
  540. }
  541. }
  542. public void init(int mode) {
  543. // Loading View Strings
  544. String pullLabel = context
  545. .getString(R.string.pull_to_refresh_pull_label);
  546. String refreshingLabel = context
  547. .getString(R.string.pull_to_refresh_refreshing_label);
  548. String releaseLabel = context
  549. .getString(R.string.pull_to_refresh_release_label);
  550. // Add Loading Views
  551. if (mode == MODE_PULL_DOWN_TO_REFRESH || mode == MODE_BOTH) {
  552. headerLayout = new LoadingLayout(context,MODE_PULL_DOWN_TO_REFRESH, releaseLabel, pullLabel,refreshingLabel);
  553. addView(headerLayout, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
  554. measureView(headerLayout);
  555. headerHeight = headerLayout.getMeasuredHeight();
  556. }
  557. if (mode == MODE_PULL_UP_TO_REFRESH || mode == MODE_BOTH) {
  558. footerLayout = new LoadingLayout(context, MODE_PULL_UP_TO_REFRESH,releaseLabel, pullLabel, refreshingLabel);
  559. addView(footerLayout, new LinearLayout.LayoutParams(
  560. ViewGroup.LayoutParams.FILL_PARENT,
  561. ViewGroup.LayoutParams.WRAP_CONTENT));
  562. measureView(footerLayout);
  563. headerHeight = footerLayout.getMeasuredHeight();
  564. }
  565. // Styleables from XML
  566. if (null != headerLayout) {
  567. // headerLayout.setTextColor(Color.BLACK);
  568. }
  569. if (null != footerLayout) {
  570. // footerLayout.setTextColor(Color.BLACK);
  571. }
  572. // Hide Loading Views
  573. switch (mode) {
  574. case MODE_BOTH:
  575. setPadding(0, -headerHeight, 0, -headerHeight);
  576. break;
  577. case MODE_PULL_UP_TO_REFRESH:
  578. setPadding(0, 0, 0, -headerHeight);
  579. break;
  580. case MODE_PULL_DOWN_TO_REFRESH:
  581. default:
  582. setPadding(0, -headerHeight, 0, 0);
  583. break;
  584. }
  585. // If we're not using MODE_BOTH, then just set currentMode to current
  586. // mode
  587. if (mode != MODE_BOTH) {
  588. currentMode = mode;
  589. }
  590. this.mode = mode;
  591. }
  592. private void init(Context context, AttributeSet attrs) {
  593. this.context = context;
  594. setOrientation(LinearLayout.VERTICAL);
  595. touchSlop = ViewConfiguration.getTouchSlop();
  596. // Refreshable View
  597. // By passing the attrs, we can add ListView/GridView params via XML
  598. refreshableView = this.createRefreshableView(context, attrs);
  599. this.addRefreshableView(context, refreshableView);
  600. }
  601. private Context context;
  602. private void measureView(View child) {
  603. ViewGroup.LayoutParams p = child.getLayoutParams();
  604. if (p == null) {
  605. p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
  606. ViewGroup.LayoutParams.WRAP_CONTENT);
  607. }
  608. int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
  609. int lpHeight = p.height;
  610. int childHeightSpec;
  611. if (lpHeight > 0) {
  612. childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
  613. MeasureSpec.EXACTLY);
  614. } else {
  615. childHeightSpec = MeasureSpec.makeMeasureSpec(0,
  616. MeasureSpec.UNSPECIFIED);
  617. }
  618. child.measure(childWidthSpec, childHeightSpec);
  619. }
  620. /**
  621. * Actions a Pull Event
  622. *
  623. * @return true if the Event has been handled, false if there has been no
  624. * change
  625. */
  626. private boolean pullEvent() {
  627. final int newHeight;
  628. final int oldHeight = this.getScrollY();
  629. switch (currentMode) {
  630. case MODE_PULL_UP_TO_REFRESH:
  631. newHeight = Math.round(Math.max(initialMotionY - lastMotionY, 0)
  632. / FRICTION);
  633. // newHeight = Math.round((initialMotionY - lastMotionY) /
  634. // FRICTION);
  635. break;
  636. case MODE_PULL_DOWN_TO_REFRESH:
  637. default:
  638. newHeight = Math.round(Math.min(initialMotionY - lastMotionY, 0)
  639. / FRICTION);
  640. // newHeight = Math.round((initialMotionY - lastMotionY) /
  641. // FRICTION);
  642. break;
  643. }
  644. setHeaderScroll(newHeight);
  645. if (newHeight != 0) {
  646. if (state == PULL_TO_REFRESH && headerHeight < Math.abs(newHeight)) {
  647. state = RELEASE_TO_REFRESH;
  648. switch (currentMode) {
  649. case MODE_PULL_UP_TO_REFRESH:
  650. footerLayout.releaseToRefresh();
  651. break;
  652. case MODE_PULL_DOWN_TO_REFRESH:
  653. headerLayout.releaseToRefresh();
  654. break;
  655. }
  656. return true;
  657. } else if (state == RELEASE_TO_REFRESH
  658. && headerHeight >= Math.abs(newHeight)) {
  659. state = PULL_TO_REFRESH;
  660. switch (currentMode) {
  661. case MODE_PULL_UP_TO_REFRESH:
  662. footerLayout.pullToRefresh();
  663. break;
  664. case MODE_PULL_DOWN_TO_REFRESH:
  665. headerLayout.pullToRefresh();
  666. break;
  667. }
  668. return true;
  669. }
  670. }
  671. return oldHeight != newHeight;
  672. }
  673. private boolean isReadyForPull() {
  674. switch (mode) {
  675. case MODE_PULL_DOWN_TO_REFRESH:
  676. return isReadyForPullDown();
  677. case MODE_PULL_UP_TO_REFRESH:
  678. return isReadyForPullUp();
  679. case MODE_BOTH:
  680. return isReadyForPullUp() || isReadyForPullDown();
  681. }
  682. return false;
  683. }
  684. // ===========================================================
  685. // Inner and Anonymous Classes
  686. // ===========================================================
  687. public static interface OnRefreshListener {
  688. public void onRefresh(int mode);
  689. }
  690. private OnShowLayoutListener onShowLayoutListener;
  691. public void setOnShowLayoutListener(OnShowLayoutListener listener) {
  692. this.onShowLayoutListener = listener;
  693. }
  694. public static interface OnShowLayoutListener {
  695. /**
  696. * 鏄惁姝e湪鏄剧ず搴曢儴甯冨眬
  697. */
  698. public void onShow();
  699. /**
  700. * 鏄惁娑堝け
  701. */
  702. public void onDismiss();
  703. }
  704. public static interface OnLastItemVisibleListener {
  705. public void onLastItemVisible();
  706. }
  707. @Override
  708. public void setLongClickable(boolean longClickable) {
  709. getRefreshableView().setLongClickable(longClickable);
  710. }
  711. }


主要代码都在上面贴出来了,当然还是一定要有demo

DEMO源码下载

这个源码里面 我把  PullToRefreshExpandableListView 和 PullToRefreshListView  也都放进来了,一样的逻辑。希望对大家有用。

如果还有其它问题 希望大家加入我的qq群 Android开发经验交流群 454430053 互相讨论交流。

文章来源: wukong.blog.csdn.net,作者:再见孙悟空_,版权归原作者所有,如需转载,请联系作者。

原文链接:wukong.blog.csdn.net/article/details/53159142

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。