Android 简易上下拉刷新
Android 简易上下拉刷新
以前忘记是在哪里听过一句话说,干android的必须要会上下拉刷新。
所以自己思索了一下,在加上网上的一些思路,完成了自己的简易上下拉刷新。
1.下拉刷新思路:
当item的position为0的时候就可以执行下拉刷新,在滑动刷新过程中要经历4中状态:
- NONE(ListView的初始状态).
- PULL(ListView在下拉过程中,还没进入能松开刷新的状态)
- REALSE(ListView进入到手指抬起后可刷新状态)
- REFRESHING(ListView正在刷新状态)
然后根据状态的不同,对HeadView里面的内容进行改变即可
2.上拉加载更多
监听ListView的滚动,来判断ListView滚动到哪里来进行在家更多。
3.数据获取:采用接口回调的方法来执行
部分代码:
1 public class ScrollOverListViewReplica extends ListView implements 2 OnScrollListener { 3 4 private final static int RATIO = 2; 5 private View headView; 6 private ProgressBar headProgressBar; 7 private ImageView headArrowImageView; 8 private TextView headTipToLoad, headTipPullToRefresh; 9 private int headViewHeight; 10 // 定义下拉刷新时候的四种状态 11 private final static int NONE = 0; 12 private final static int PULL = 1; 13 private final static int RELEASE = 2; 14 private final static int REFRESHING = 3; 15 private int startY; 16 // 在按下的时候才记录startY的值 17 private boolean isDown = true; 18 // 当前状态值 19 private int state; 20 // 动画效果 21 RotateAnimation mRotateAnimation, mRotateAnimation2; 22 private int firstVisibleItem; 23 private int scrollState; 24 private boolean isback = false; 25 private IOnRefreshListener mListener; 26 // 脚部View 27 private View footerView; 28 private TextView footer_text; 29 private ProgressBar footer_loading; 30 // 倒数第几个开始加载更多选项 31 private int bottomPosition; 32 private int LastVisibleItemPosition; 33 private int totalItemCount; 34 private IonLoadMore mIonLoadMore; 35 36 public ScrollOverListViewReplica(Context context) { 37 super(context); 38 initView(context); 39 40 } 41 42 public ScrollOverListViewReplica(Context context, AttributeSet attrs) { 43 super(context, attrs); 44 initView(context); 45 } 46 47 public ScrollOverListViewReplica(Context context, AttributeSet attrs, 48 int defStyle) { 49 super(context, attrs, defStyle); 50 initView(context); 51 } 52 53 private void initView(Context context) { 54 state = NONE; 55 headView = LayoutInflater.from(context).inflate(R.layout.head_view, 56 null); 57 headProgressBar = (ProgressBar) headView 58 .findViewById(R.id.head_progressBar); 59 headArrowImageView = (ImageView) headView 60 .findViewById(R.id.head_arrowImageView); 61 headTipPullToRefresh = (TextView) headView 62 .findViewById(R.id.head_tip_pull_to_refresh); 63 headTipToLoad = (TextView) headView.findViewById(R.id.head_tip_to_load); 64 // 对 headView 进行测量 65 measure(headView); 66 // 获取顶部的高度 67 headViewHeight = headView.getMeasuredHeight(); 68 // 设置padding,初始化的时候不显示headView 69 headView.setPadding(headView.getLeft(), -headViewHeight, 70 headView.getRight(), headView.getBottom()); 71 headView.invalidate(); 72 addHeaderView(headView); 73 initAnimation(); 74 initListener(); 75 // 添加底部加载更多 76 addFooterView(context); 77 78 } 79 80 private void addFooterView(Context context) { 81 footerView = LayoutInflater.from(context).inflate( 82 R.layout.pulldown_footer, null); 83 footer_text = (TextView) footerView 84 .findViewById(R.id.pulldown_footer_text); 85 footer_loading = (ProgressBar) footerView 86 .findViewById(R.id.pulldown_footer_loading); 87 footerView.setVisibility(View.GONE); 88 addFooterView(footerView); 89 // 判断数据是否填充了了整个ListView 90 91 } 92 93 private void initListener() { 94 setOnScrollListener(this); 95 // setOnScrollListener(new OnScrollListener() { 96 // 97 // @Override 98 // public void onScrollStateChanged(AbsListView view, int scrollState) { 99 // scrollState1 = scrollState; 100 // } 101 // 102 // @Override 103 // public void onScroll(AbsListView view, int firstVisibleItem, 104 // int visibleItemCount, int totalItemCount) { 105 // firstVisiblePosition = firstVisibleItem; 106 // 107 // } 108 // }); 109 } 110 111 // 初始化动画效果 112 private void initAnimation() { 113 mRotateAnimation = new RotateAnimation(0, -180, 114 RotateAnimation.RELATIVE_TO_SELF, 0.5F, 115 RotateAnimation.RELATIVE_TO_SELF, 0.5F); 116 mRotateAnimation.setInterpolator(new LinearInterpolator()); 117 mRotateAnimation.setDuration(250); 118 mRotateAnimation.setFillAfter(true); 119 120 mRotateAnimation2 = new RotateAnimation(-180, 0, 121 RotateAnimation.RELATIVE_TO_SELF, 0.5F, 122 RotateAnimation.RELATIVE_TO_SELF, 0.5F); 123 mRotateAnimation2.setInterpolator(new LinearInterpolator()); 124 mRotateAnimation2.setDuration(200); 125 mRotateAnimation2.setFillAfter(true); 126 127 } 128 129 private void measure(View child) { 130 LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) child 131 .getLayoutParams(); 132 if (lp == null) { 133 lp = new android.widget.LinearLayout.LayoutParams( 134 LinearLayout.LayoutParams.MATCH_PARENT, 135 LinearLayout.LayoutParams.WRAP_CONTENT); 136 } 137 138 int headIWidthSpec = LinearLayout.getChildMeasureSpec(0, 0, lp.width); 139 int headHeight = lp.height; 140 int headHeightSpec; 141 if (headHeight > 0) { 142 headHeightSpec = MeasureSpec.makeMeasureSpec(headHeight, 143 MeasureSpec.EXACTLY); 144 } else { 145 headHeightSpec = MeasureSpec.makeMeasureSpec(0, 146 MeasureSpec.UNSPECIFIED); 147 } 148 149 child.measure(headIWidthSpec, headHeightSpec); 150 } 151 152 @Override 153 public boolean onTouchEvent(MotionEvent ev) { 154 155 switch (ev.getAction()) { 156 case MotionEvent.ACTION_DOWN: 157 158 if (firstVisibleItem == 0) { 159 startY = (int) ev.getY(); 160 } 161 162 break; 163 case MotionEvent.ACTION_MOVE: 164 165 // 在第一个条目在的时候才能下拉刷新 166 if (firstVisibleItem == 0) { 167 motionMove(ev); 168 } 169 170 int childrenCount = getChildCount(); 171 if (childrenCount == 0) { 172 return super.onTouchEvent(ev); 173 } 174 175 break; 176 case MotionEvent.ACTION_UP: 177 if (state == RELEASE) { 178 state = REFRESHING; 179 changHeadViewByState(); 180 } else { 181 state = NONE; 182 changHeadViewByState(); 183 } 184 185 break; 186 default: 187 break; 188 } 189 190 return super.onTouchEvent(ev); 191 } 192 193 private void motionMove(MotionEvent ev) { 194 // 记录滑动时候的Y的值 195 int moveY = (int) ev.getY(); 196 // 获取滑动距离 197 int detal = (moveY - startY) / RATIO; 198 System.out.println("DETAL-->>" + detal); 199 switch (state) { 200 case NONE: 201 202 if (detal > 0) { 203 state = PULL; 204 } 205 206 break; 207 case PULL: 208 209 if (-headViewHeight + detal > 30) { 210 state = RELEASE; 211 isback = false; 212 headArrowImageView.clearAnimation(); 213 headArrowImageView.startAnimation(mRotateAnimation); 214 changHeadViewByState(); 215 } else { 216 state = NONE; 217 changHeadViewByState(); 218 } 219 headView.setPadding(0, -headViewHeight + detal, 0, 0); 220 break; 221 case RELEASE: 222 if (-headViewHeight + detal < 30 223 && scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 224 state = PULL; 225 // isback = true; 226 headArrowImageView.clearAnimation(); 227 headArrowImageView.startAnimation(mRotateAnimation2); 228 changHeadViewByState(); 229 } else if (detal < 0) { 230 state = NONE; 231 changHeadViewByState(); 232 } 233 headView.setPadding(0, -headViewHeight + detal, 0, 0); 234 235 break; 236 } 237 238 } 239 240 // private ProgressBar headProgressBar; 241 // private ImageView headArrowImageView; 242 // private TextView headTipToLoad, headTipPullToRefresh; 243 244 // 根据不同状态来改变headView 245 private void changHeadViewByState() { 246 switch (state) { 247 case NONE: 248 headProgressBar.setVisibility(View.GONE); 249 headArrowImageView.setVisibility(View.VISIBLE); 250 headTipToLoad.setVisibility(View.GONE); 251 headTipPullToRefresh.setVisibility(View.VISIBLE); 252 headTipPullToRefresh.setText("下拉即可刷新"); 253 // headArrowImageView.clearAnimation(); 254 headView.setPadding(0, -headViewHeight, 0, 0); 255 break; 256 case PULL: 257 headProgressBar.setVisibility(View.GONE); 258 headArrowImageView.setVisibility(View.VISIBLE); 259 headTipToLoad.setVisibility(View.GONE); 260 headTipPullToRefresh.setVisibility(View.VISIBLE); 261 headTipPullToRefresh.setText("下拉即可刷新"); 262 263 break; 264 case RELEASE: 265 headProgressBar.setVisibility(View.GONE); 266 headArrowImageView.setVisibility(View.VISIBLE); 267 headTipToLoad.setVisibility(View.GONE); 268 headTipPullToRefresh.setVisibility(View.VISIBLE); 269 headTipPullToRefresh.setText("松开即可刷新"); 270 break; 271 case REFRESHING: 272 headProgressBar.setVisibility(View.VISIBLE); 273 headArrowImageView.setVisibility(View.GONE); 274 headTipToLoad.setVisibility(View.VISIBLE); 275 headTipPullToRefresh.setVisibility(View.GONE); 276 headView.setPadding(0, 0, 0, 0); 277 mListener.onRefresh(); 278 break; 279 } 280 } 281 282 public void completeRefresh() { 283 state = NONE; 284 headArrowImageView.clearAnimation(); 285 headProgressBar.setVisibility(View.GONE); 286 headArrowImageView.setVisibility(View.VISIBLE); 287 headTipToLoad.setVisibility(View.GONE); 288 headTipPullToRefresh.setVisibility(View.VISIBLE); 289 headTipPullToRefresh.setText("下拉即可刷新"); 290 headView.setPadding(0, -headViewHeight, 0, 0); 291 } 292 293 public void setOnRefreshListener(IOnRefreshListener mListener) { 294 this.mListener = mListener; 295 } 296 297 public interface IOnRefreshListener { 298 public void onRefresh(); 299 } 300 301 // 设置在倒数第几个的时候出发上拉加载更多 302 303 public int getBottomPosition() { 304 return bottomPosition; 305 } 306 307 public void setBottomPosition(int bottomPosition) { 308 this.bottomPosition = bottomPosition; 309 } 310 311 @Override 312 public void onScrollStateChanged(AbsListView view, int scrollState) { 313 314 this.scrollState = scrollState; 315 316 if (scrollState != OnScrollListener.SCROLL_STATE_FLING) { 317 System.out.println("LastVisibleItemPosition-->>" 318 + LastVisibleItemPosition); 319 if (LastVisibleItemPosition >= totalItemCount - bottomPosition) { 320 footerView.setVisibility(View.VISIBLE); 321 mIonLoadMore.onMore(); 322 } 323 324 } 325 326 } 327 328 public void setOnLoadMoreListener(IonLoadMore mIonLoadMore) { 329 this.mIonLoadMore = mIonLoadMore; 330 } 331 332 public interface IonLoadMore { 333 public void onMore(); 334 } 335 336 @Override 337 public void onScroll(AbsListView view, int firstVisibleItem, 338 int visibleItemCount, int totalItemCount) { 339 this.firstVisibleItem = firstVisibleItem; 340 // 当前显示的最后一个Item的position 341 this.LastVisibleItemPosition = firstVisibleItem + visibleItemCount; 342 this.totalItemCount = totalItemCount; 343 } 344 345 }
运行后效果是:
因为是简易的上下拉刷新,bug还是有的后期完善。
源码下载地址:下载

浙公网安备 33010602011771号