自定义ListView实现下拉刷新和分页加载(效果类似知乎)
来源:互联网 发布:推广淘宝联盟怎么转码 编辑:程序博客网 时间:2024/05/19 12:37
摘要:
自定义了一个ListView,实现下拉刷新和分页加载。
下拉刷新效果:
当ListView滑到最顶端的时候,向下滑动手指,ListView并不向下滑动,而是在顶端出现一个headerBar,headerBar的宽度与手指向下滑动的距离成正比,手指滑动距离超过阈值,ListView通过接口回调,通知外部进行refresh,刷新内容,同时headerBar变为从左向右不断滑动的动画。
方案:
通过Override ListView的onTouchEvent(MotionEvent ev)方法实现。
分页加载效果:
当ListView滑动到最底端并停止滑动时,ListView通过接口回调,通知外部进行LoadMore,加载更多。
方案:
实现OnScrollListener接口,Override onScrollStateChanged方法,和onScroll方法
xml代码如下,HeaderView用于下拉刷新,FooterView用于分页加载
</pre><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="@dimen/abc_action_bar_default_padding_material" android:orientation="horizontal"> <TextView android:id="@+id/drag_header" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:background="@android:color/holo_blue_light" android:visibility="invisible"/> <LinearLayout android:id="@+id/refresh_header" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:visibility="invisible"> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/holo_blue_light"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="0.5"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/holo_blue_light"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="0.5"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/holo_blue_light"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="0.5"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/holo_blue_light"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="0.5"/> <TextView android:layout_width="0px" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/holo_blue_light"/> </LinearLayout></FrameLayout>
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_footer" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Loading"/></FrameLayout>
Java代码如下
package com.lihao.widget;import android.content.Context;import android.util.Log;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.animation.Animation;import android.view.animation.LinearInterpolator;import android.view.animation.TranslateAnimation;import android.widget.AbsListView;import android.widget.FrameLayout;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.AbsListView.OnScrollListener;import android.widget.TextView;import android.util.AttributeSet;import android.R.color;import com.lihao.R;public class RefreshAndLoadListView extends ListView implements OnScrollListener { Context context; LayoutInflater inflater; OnRefreshAndLoadListener listener; FrameLayout.LayoutParams params; FrameLayout header; FrameLayout footer; TextView drag_header; TextView tv_footer; LinearLayout refresh_header; TranslateAnimation animation; boolean isRefreshing = false; boolean isLoading = false; boolean isLoadingOver = false; boolean pressFromTop = true; boolean isLastItemVisible; int pressPosition; int distanceDown; int firstVisibleItem; int listViewWidth; private final int HEADER_HEIGHT = 10; // in pix private final int FOOTER_HEIGHT = 100; // in pix private final int ANIM_DURATION = 300; // in milliseconds private final int DRAG_THRESHOLD = 400; // in pix private final float ANIM_OFFSET = (1 + 0.5f) / (5 + 4*0.5f) / 2; public RefreshAndLoadListView(Context context) { super(context); init(context); } public RefreshAndLoadListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public RefreshAndLoadListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { this.context = context; inflater = LayoutInflater.from(context); header = (FrameLayout) inflater.inflate(R.layout.lv_refresh_and_load_header, null); footer = (FrameLayout) inflater.inflate(R.layout.lv_refresh_and_load_footer, null); drag_header = (TextView) header.findViewById(R.id.drag_header); tv_footer = (TextView) footer.findViewById(R.id.tv_footer); refresh_header = (LinearLayout) header.findViewById(R.id.refresh_header); this.addHeaderView(header); this.addFooterView(footer); setFooterDividersEnabled(false); setHeaderDividersEnabled(false); params = (FrameLayout.LayoutParams) drag_header.getLayoutParams(); params.height = HEADER_HEIGHT; drag_header.setLayoutParams(params); params = (FrameLayout.LayoutParams) tv_footer.getLayoutParams(); params.height = FOOTER_HEIGHT; tv_footer.setLayoutParams(params); params = (FrameLayout.LayoutParams) refresh_header.getLayoutParams(); params.height = HEADER_HEIGHT; refresh_header.setLayoutParams(params); this.setOnScrollListener(this); animation = new TranslateAnimation( Animation.RELATIVE_TO_PARENT, -ANIM_OFFSET, Animation.RELATIVE_TO_PARENT, ANIM_OFFSET, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f); animation.setRepeatCount(Animation.INFINITE); animation.setRepeatMode(Animation.RESTART); animation.setInterpolator(new LinearInterpolator()); animation.setDuration(ANIM_DURATION); animation.setFillAfter(false); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: pressFromTop = (header.getTop() == 0) && (firstVisibleItem == 0); pressPosition = (int) ev.getY(); if (animation.hasStarted()) { refresh_header.clearAnimation(); refresh_header.setVisibility(INVISIBLE); } break; case MotionEvent.ACTION_MOVE: if (pressFromTop) { setPressed(false); for (int i = 0; i < ev.getHistorySize(); i++) { distanceDown = (int) ev.getHistoricalY(i) - pressPosition; if (!isRefreshing) { onPreRefresh(distanceDown); if (distanceDown > DRAG_THRESHOLD) { onRefresh(); return true; } } } if (distanceDown > 0) { return true; } } break; case MotionEvent.ACTION_UP: if (pressFromTop) { distanceDown = 0; onPreRefresh(distanceDown); } } return super.onTouchEvent(ev); } private void onPreRefresh(int distanceDown) { if (isRefreshing) return; drag_header.setVisibility(VISIBLE); header.setBackgroundColor(color.white); refresh_header.setVisibility(INVISIBLE); listViewWidth = header.getMeasuredWidth(); params = (FrameLayout.LayoutParams) drag_header.getLayoutParams(); params.width = distanceDown * listViewWidth / DRAG_THRESHOLD; drag_header.setLayoutParams(params); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE && isLastItemVisible) { onLoad(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; isLastItemVisible = ((firstVisibleItem + visibleItemCount) == totalItemCount); } /** * 设置listener */ public void setOnRefreshAndLoadListener(OnRefreshAndLoadListener listener) { this.listener = listener; } /** * 外部通知ListView数据更新的状态 */ public void onRefreshComplete() { isRefreshing = false; refresh_header.clearAnimation(); refresh_header.setVisibility(INVISIBLE); } public void onLoadComplete() { isLoading = false; } public void onLoadOver() { isLoadingOver = true; tv_footer.setText("No More Data."); } public void onError() { tv_footer.setText("Unknown Error."); } /** * ListView 通过 callback interface 发出更新数据的指令 */ private void onRefresh() { if (isRefreshing) return; isRefreshing = true; drag_header.setVisibility(INVISIBLE); refresh_header.setVisibility(VISIBLE); refresh_header.startAnimation(animation); if (listener != null) { listener.onRefresh(); } } private void onLoad() { if (isLoading || isLoadingOver) return; isLoading = true; if (listener != null) { listener.onLoad(); } } /** * callback interface */ public interface OnRefreshAndLoadListener { public void onRefresh(); public void onLoad(); }}
作者:李浩。
转载请注明出处。
0 0
- 自定义ListView实现下拉刷新和分页加载(效果类似知乎)
- Android 实现listview 分页加载和下拉刷新
- ListView 下拉回弹效果(类似知乎日报首页效果)
- 自定义控件实现ListView下拉刷新和上拉加载
- 自定义listview实现下拉刷新的效果
- android 自定义ListView实现下拉刷新、分页加载、点击事件——自定义控件学习(七)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- Android UI--自定义ListView(实现下拉刷新+加载更多)
- 知乎下拉刷新SwipeRefreshLayout下拉刷新用法类似知乎下拉刷新
- android 模仿知乎下拉刷新和上拉加载
- Android自定义控件(一) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- Android自定义控件(二) 下拉刷新,上拉分页加载更多(支持ListView, GridView, ScrollView)
- Linux下的tar压缩解压缩命令详解
- [047] 即将陆续推出微信公众平台开发视频教程
- unity FPS 将原来的left,right控制左右移动改为控制向左向右旋转
- autolayout学习介绍------Masonry的使用
- This device has been locked for debugging.
- 自定义ListView实现下拉刷新和分页加载(效果类似知乎)
- android audio system好文收藏
- LruMemoryCache解析
- [腾讯笔试] 2014腾讯校园招聘实习技术类笔试题目
- PLSQL Developer9 注册码
- IOS开发模块总结(一)本地数据存储5 NSFileManager
- telnet memcache
- Cookie的生命周期
- wireshark抓包分析