歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 類ListView下拉刷新控件實現

Android 類ListView下拉刷新控件實現

日期:2017/3/1 10:35:02   编辑:Linux編程

Android下拉刷新,在目前好多應用被使用到。

比如微博,下拉刷新更多數據。

一般我們在運用的ListView,本身就實現了下拉獲取更多數據。只是這個下拉刷新的操作時在listView拉到底端的監聽。

對於ListView刷新,我們可以分為兩種情況:

1.獲取更多的數據,按服務器數據庫時間順序存儲入情況,此刻我們是獲取是顯示在我們應用中的數據更早前的數據,這也是最常見的情況。

比如(微博獲取更多信息,就是獲取更多更早前的信息,然後動態的添加到已有的數據的下方);

2.獲取更多的最新的數據,其實還是一種獲取更多的操作方式。但是這裡主要考慮到用戶的操作習慣了。一般,用戶的操作習慣分這麼兩種

第一種,獲取下一頁,第二種,類似於網頁的F5刷新,停留在當前頁面的刷新。

ListView刷新其實類似於網頁。如果沒用下拉刷新,那麼用戶得將ListView拖拉到最後(當然也可以是在界面頂端添加一個刷新按鈕控件,但是,對於手機這樣界面不是很大,這樣的設計其實是不應太多的。),如果數據太多,那麼用戶要下拉到很下面才能執行刷新。而對於大多數用戶習慣,獲取更多的最新資訊後,希望他添加的時候是在界面最上面的顯眼處的。也就是,用戶還是喜歡的是懶操作,在同一個可顯示界面完成所有操作。那麼,下拉刷新是一個不錯的設計。

效果圖:正常狀態


下拉刷新:

基本效果就是這樣。

自定義控件代碼

[java]
  1. /**
  2. * 刷新控制view
  3. *
  4. * @author Nono
  5. *
  6. */
  7. public class RefreshableView extends LinearLayout {
  8. private static final String TAG = "LILITH";
  9. private Scroller scroller;
  10. private View refreshView;
  11. private ImageView refreshIndicatorView;
  12. private int refreshTargetTop = -60;
  13. private ProgressBar bar;
  14. private TextView downTextView;
  15. private TextView timeTextView;
  16. private RefreshListener refreshListener;
  17. private String downTextString;
  18. private String releaseTextString;
  19. private Long refreshTime = null;
  20. private int lastX;
  21. private int lastY;
  22. // 拉動標記
  23. private boolean isDragging = false;
  24. // 是否可刷新標記
  25. private boolean isRefreshEnabled = true;
  26. // 在刷新中標記
  27. private boolean isRefreshing = false;
  28. private Context mContext;
  29. public RefreshableView(Context context) {
  30. super(context);
  31. mContext = context;
  32. }
  33. public RefreshableView(Context context, AttributeSet attrs) {
  34. super(context, attrs);
  35. mContext = context;
  36. init();
  37. }
  38. private void init() {
  39. // TODO Auto-generated method stub
  40. //滑動對象,
  41. scroller = new Scroller(mContext);
  42. //刷新視圖頂端的的view
  43. refreshView = LayoutInflater.from(mContext).inflate(R.layout.refresh_top_item, null);
  44. //指示器view
  45. refreshIndicatorView = (ImageView) refreshView.findViewById(R.id.indicator);
  46. //刷新bar
  47. bar = (ProgressBar) refreshView.findViewById(R.id.progress);
  48. //下拉顯示text
  49. downTextView = (TextView) refreshView.findViewById(R.id.refresh_hint);
  50. //下來顯示時間
  51. timeTextView = (TextView) refreshView.findViewById(R.id.refresh_time);
  52. LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, -refreshTargetTop);
  53. lp.topMargin = refreshTargetTop;
  54. lp.gravity = Gravity.CENTER;
  55. addView(refreshView, lp);
  56. downTextString = mContext.getResources().getString(R.string.refresh_down_text);
  57. releaseTextString = mContext.getResources().getString(R.string.refresh_release_text);
  58. }
  59. /**
  60. * 刷新
  61. * @param time
  62. */
  63. private void setRefreshText(String time) {
  64. // TODO Auto-generated method stub
  65. //timeTextView.setText(time);
  66. }
  67. @Override
  68. public boolean onTouchEvent(MotionEvent event) {
  69. int y= (int) event.getRawY();
  70. switch (event.getAction()) {
  71. case MotionEvent.ACTION_DOWN:
  72. //記錄下y坐標
  73. lastY = y;
  74. break;
  75. case MotionEvent.ACTION_MOVE:
  76. Log.i(TAG, "ACTION_MOVE");
  77. //y移動坐標
  78. int m = y - lastY;
  79. if(((m < 6) && (m > -1)) || (!isDragging )){
  80. doMovement(m);
  81. }
  82. //記錄下此刻y坐標
  83. this.lastY = y;
  84. break;
  85. case MotionEvent.ACTION_UP:
  86. Log.i(TAG, "ACTION_UP");
  87. fling();
  88. break;
  89. }
  90. return true;
  91. }
  92. /**
  93. * up事件處理
  94. */
  95. private void fling() {
  96. // TODO Auto-generated method stub
  97. LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
  98. Log.i(TAG, "fling()" + lp.topMargin);
  99. if(lp.topMargin > 0){//拉到了觸發可刷新事件
  100. refresh();
  101. }else{
  102. returnInitState();
  103. }
  104. }
  105. private void returnInitState() {
  106. // TODO Auto-generated method stub
  107. LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
  108. int i = lp.topMargin;
  109. scroller.startScroll(0, i, 0, refreshTargetTop);
  110. invalidate();
  111. }
  112. private void refresh() {
  113. // TODO Auto-generated method stub
  114. LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
  115. int i = lp.topMargin;
  116. refreshIndicatorView.setVisibility(View.GONE);
  117. bar.setVisibility(View.VISIBLE);
  118. timeTextView.setVisibility(View.GONE);
  119. downTextView.setVisibility(View.GONE);
  120. scroller.startScroll(0, i, 0, 0-i);
  121. invalidate();
  122. if(refreshListener !=null){
  123. refreshListener.onRefresh(this);
  124. isRefreshing = true;
  125. }
  126. }
  127. /**
  128. *
  129. */
  130. @Override
  131. public void computeScroll() {
  132. // TODO Auto-generated method stub
  133. if(scroller.computeScrollOffset()){
  134. int i = this.scroller.getCurrY();
  135. LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
  136. int k = Math.max(i, refreshTargetTop);
  137. lp.topMargin = k;
  138. this.refreshView.setLayoutParams(lp);
  139. this.refreshView.invalidate();
  140. invalidate();
  141. }
  142. }
  143. /**
  144. * 下拉move事件處理
  145. * @param moveY
  146. */
  147. private void doMovement(int moveY) {
  148. // TODO Auto-generated method stub
  149. LinearLayout.LayoutParams lp = (LayoutParams) refreshView.getLayoutParams();
  150. if(moveY > 0){
  151. //獲取view的上邊距
  152. float f1 =lp.topMargin;
  153. float f2 = moveY * 0.3F;
  154. int i = (int)(f1+f2);
  155. //修改上邊距
  156. lp.topMargin = i;
  157. //修改後刷新
  158. refreshView.setLayoutParams(lp);
  159. refreshView.invalidate();
  160. invalidate();
  161. }
  162. timeTextView.setVisibility(View.VISIBLE);
  163. if(refreshTime!= null){
  164. setRefreshTime(refreshTime);
  165. }
  166. downTextView.setVisibility(View.VISIBLE);
  167. refreshIndicatorView.setVisibility(View.VISIBLE);
  168. bar.setVisibility(View.GONE);
  169. if(lp.topMargin > 0){
  170. downTextView.setText(R.string.refresh_release_text);
  171. refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_up);
  172. }else{
  173. downTextView.setText(R.string.refresh_down_text);
  174. refreshIndicatorView.setImageResource(R.drawable.refresh_arrow_down);
  175. }
  176. }
  177. public void setRefreshEnabled(boolean b) {
  178. this.isRefreshEnabled = b;
  179. }
  180. public void setRefreshListener(RefreshListener listener) {
  181. this.refreshListener = listener;
  182. }
  183. /**
  184. * 刷新時間
  185. * @param refreshTime2
  186. */
  187. private void setRefreshTime(Long time) {
  188. // TODO Auto-generated method stub
  189. }
  190. /**
  191. * 結束刷新事件
  192. */
  193. public void finishRefresh(){
  194. Log.i(TAG, "執行了=====finishRefresh");
  195. LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams)this.refreshView.getLayoutParams();
  196. int i = lp.topMargin;
  197. refreshIndicatorView.setVisibility(View.VISIBLE);
  198. timeTextView.setVisibility(View.VISIBLE);
  199. scroller.startScroll(0, i, 0, refreshTargetTop);
  200. invalidate();
  201. isRefreshing = false;
  202. }
  203. /*該方法一般和ontouchEvent 一起用
  204. * (non-Javadoc)
  205. * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
  206. */
  207. @Override
  208. public boolean onInterceptTouchEvent(MotionEvent e) {
  209. // TODO Auto-generated method stub
  210. int action = e.getAction();
  211. int y= (int) e.getRawY();
  212. switch (action) {
  213. case MotionEvent.ACTION_DOWN:
  214. lastY = y;
  215. break;
  216. case MotionEvent.ACTION_MOVE:
  217. //y移動坐標
  218. int m = y - lastY;
  219. //記錄下此刻y坐標
  220. this.lastY = y;
  221. if(m > 6 && canScroll()){
  222. return true;
  223. }
  224. break;
  225. case MotionEvent.ACTION_UP:
  226. break;
  227. case MotionEvent.ACTION_CANCEL:
  228. break;
  229. }
  230. return false;
  231. }
  232. private boolean canScroll() {
  233. // TODO Auto-generated method stub
  234. View childView;
  235. if(getChildCount()>1){
  236. childView = this.getChildAt(1);
  237. if(childView instanceof ListView){
  238. int top =((ListView)childView).getChildAt(0).getTop();
  239. int pad =((ListView)childView).getListPaddingTop();
  240. if((Math.abs(top-pad)) < 3&&
  241. ((ListView) childView).getFirstVisiblePosition() == 0){
  242. return true;
  243. }else{
  244. return false;
  245. }
  246. }else if(childView instanceof ScrollView){
  247. if(((ScrollView)childView).getScrollY() == 0){
  248. return true;
  249. }else{
  250. return false;
  251. }
  252. }
  253. }
  254. return false;
  255. }
  256. /**
  257. * 刷新監聽接口
  258. * @author Nono
  259. *
  260. */
  261. public interface RefreshListener{
  262. public void onRefresh(RefreshableView view);
  263. }
  264. }

此控件自定義實現一個線性布局,內部包含一個第一個子控件,刷新顯示的View。

Copyright © Linux教程網 All Rights Reserved