自定义控件之ListView下拉刷新

来源:互联网 发布:申请淘宝api接口流程 编辑:程序博客网 时间:2024/05/09 20:21

1.定义个类继承ListView

   添加头条目

   添加脚条目

   设置滚动监听(处理上啦加载)

   重写触摸 事件(处理下拉刷新)

public class PullToReFreshListView extends ListView implements OnScrollListener {private View headerView;private int headermeasuredHeight;private RotateAnimation up;private RotateAnimation down;private int downY;/** 下拉刷新 **/public static final int PULL_DOWN = 1;/** 松开刷新 **/public static final int RELEASE_REFRESH = 2;/** 正在刷新 **/public static final int REGFRESHING = 3;/** 当前的状态 **/public static int CURRENTSTATE = PULL_DOWN;private ImageView mArrow;private ProgressBar mPb;private TextView mText;private int footermeasuredHeight;private View footerview;/**是否加载更多,true:加载更多,false:没有加载更多**/private boolean isLoadMore;public PullToReFreshListView(Context context) {// super(context);this(context, null);}public PullToReFreshListView(Context context, AttributeSet attrs) {// super(context, attrs);this(context, attrs, 0);}public PullToReFreshListView(Context context, AttributeSet attrs,int defStyle) {super(context, attrs, defStyle);// 添加刷新头addHeader();// 添加底部条目addFooter();// 监听listview的滚动状态setOnScrollListener(this);}/** * 添加listview底部条目 2016-8-14 上午11:34:23 */private void addFooter() {footerview = View.inflate(getContext(), R.layout.footer_item, null);// 隐藏底部条目footerview.measure(0, 0);footermeasuredHeight = footerview.getMeasuredHeight();footerview.setPadding(0, 0, 0, -footermeasuredHeight);addFooterView(footerview);// 添加listview的底部条目}/** * 添加listview的刷新头 2016-8-14 上午9:53:18 */private void addHeader() {headerView = View.inflate(getContext(), R.layout.header_item, null);// 初始化控件mArrow = (ImageView) headerView.findViewById(R.id.arrow);mPb = (ProgressBar) headerView.findViewById(R.id.pb);mText = (TextView) headerView.findViewById(R.id.text);// 隐藏刷新头headerView.measure(0, 0);// 测量控件  测量规格为未指定headermeasuredHeight = headerView.getMeasuredHeight();headerView.setPadding(0, -headermeasuredHeight, 0, 0);addHeaderView(headerView);// 将view对象,添加到listview的头部initAnimation();}/** * 初始化动画 2016-8-14 上午10:19:53 */private void initAnimation() {// 箭头向上up = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);up.setDuration(500);up.setFillAfter(true);// 保持动画结束的状态// 箭头向下down = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF, 0.5f);down.setDuration(500);down.setFillAfter(true);// 保持动画结束的状态}// 下拉显示刷新头操作// 1.触摸listview// 2.下拉操作// 3.判断当前界面显示的第一个条目是否是listview的第一个条目,是下拉显示刷新头,不是,显示显示listview的其他条目// 1.触摸listview@Overridepublic boolean onTouchEvent(MotionEvent ev) {// 2.下拉操作switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:downY = (int) ev.getY();break;case MotionEvent.ACTION_MOVE:int moveY = (int) ev.getY();int distance = moveY - downY;// 判断是否是下拉操作// 3.判断当前界面显示的第一个条目是否是listview的第一个条目,是下拉显示刷新头,不是,显示显示listview的其他条目// getFirstVisiblePosition : 获取当前界面显示的第一个条目的位置if (distance > 0 && getFirstVisiblePosition() == 0) {// 实现下拉显示刷新头// 计算空白的区域// 空白的区域 = 下拉的距离 - 刷新头的高度int paddingTop = distance - headermeasuredHeight;headerView.setPadding(0, paddingTop, 0, 0);// 下拉刷新 -> 松开刷新if (paddingTop > 0 && CURRENTSTATE == PULL_DOWN) {CURRENTSTATE = RELEASE_REFRESH;switchOption();}// 松开刷新 -> 下拉刷新if (paddingTop < 0 && CURRENTSTATE == RELEASE_REFRESH) {CURRENTSTATE = PULL_DOWN;switchOption();}// 因为系统的listview无法显示空白区域的,所以使用系统的触摸事件会出问题,解决:不使用return true;}break;case MotionEvent.ACTION_UP:// 松开刷新 -> 正在刷新,并且显示刷新头if (CURRENTSTATE == RELEASE_REFRESH) {CURRENTSTATE = REGFRESHING;headerView.setPadding(0, 0, 0, 0);switchOption();// 刷新数据if (onRefreshListener != null) {onRefreshListener.regresh();}}// 下拉刷新 -> 隐藏刷新头if (CURRENTSTATE == PULL_DOWN) {headerView.setPadding(0, -headermeasuredHeight, 0, 0);}break;}// 因为只有是下拉显示空白区域的时候才需要不使用系统的触摸事件,但是如果下拉不是空白区域,还是要使用系统的触摸事件,来实现下拉显示其他条目的操作的return super.onTouchEvent(ev);}/** * 根据状态更改控件的显示内容 2016-8-14 上午10:55:45 */private void switchOption() {switch (CURRENTSTATE) {case PULL_DOWN:// 下拉刷新mText.setText("下拉刷新");mArrow.startAnimation(down);break;case RELEASE_REFRESH:// 松开刷新mText.setText("松开刷新");mArrow.startAnimation(up);break;case REGFRESHING:// 正在刷新mText.setText("正在刷新");mArrow.clearAnimation();// 清除动画mArrow.setVisibility(View.GONE);mPb.setVisibility(View.VISIBLE);break;}}// 取消刷新/** * 取消刷新 2016-8-14 上午11:25:34 */public void finish() {// 正在刷新 -> 下拉刷新,并且隐藏刷新头if (CURRENTSTATE == REGFRESHING) {CURRENTSTATE = PULL_DOWN;mText.setText("下拉刷新");mPb.setVisibility(View.GONE);mArrow.setVisibility(View.VISIBLE);headerView.setPadding(0, -headermeasuredHeight, 0, 0);}//取消加载更多//因为取消下拉刷新和上拉加载是在一个方法中,为了避免取消下拉刷新的时候,同时也会取消上拉加载,设置是否加载更多的标示if (isLoadMore) {footerview.setPadding(0, 0, 0, -footermeasuredHeight);isLoadMore = false;}}// 加载更多// 1.监听listview的滚动状态,如果是停止滚动,显示加载更多条目,// 2.上拉到listview的最后一个条目// 当listview滚动状态改变的时候调用的方法// scrollState : listview滚动的状态@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// 监听listview的滚动状态,如果是停止滚动,显示加载更多条目,上拉到listview的最后一个条目if (scrollState == OnScrollListener.SCROLL_STATE_IDLE&& getLastVisiblePosition() == getCount() - 1 && isLoadMore == false) {isLoadMore = true;// 显示加载更多条目footerview.setPadding(0, 0, 0, 0);// 重新定位listview显示的最后一个条目setSelection(getCount() - 1);// 跳转到listview的哪个条目,position : 条目的位置// 加载更多数据if (onRefreshListener != null) {onRefreshListener.loadmore();}}}// 当listview滚动的时候调用的方法@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// TODO Auto-generated method stub}// 回调函数实现刷新数据操作// 3.创建保存接口实现对象的变量public OnRefreshListener onRefreshListener;// 2.创建获取接口实现对象的方法public void setOnRefreshListener(OnRefreshListener onRefreshListener) {this.onRefreshListener = onRefreshListener;}// 1.创建接口public interface OnRefreshListener {/** 下拉刷新 **/public void regresh();/**加载更多数据**/public void loadmore();}


2.activity

public class MainActivity extends Activity {    private PullToReFreshListView mListView;        private int m;        private int n;@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                initView();    }    /**     * 初始化控件     * 2016-8-14 上午9:31:39     */private void initView() {mListView = (PullToReFreshListView) findViewById(R.id.listview);final List<String> list = new ArrayList<String>();//填充数据for (int i = 0; i < 10; i++) {list.add("德玛西亚"+i+"区");}final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);mListView.setAdapter(arrayAdapter);//刷新数据操作mListView.setOnRefreshListener(new OnRefreshListener() {@Overridepublic void regresh() {//加载数据//延迟一段时间,加载数据new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//list.add("艾欧尼亚"+(++m)+"区");list.add(0, "艾欧尼亚"+(++m)+"区");//将数据添加list集合的哪个位置,location : 位置  object:添加的数据//刷新界面arrayAdapter.notifyDataSetChanged();//取消刷新mListView.finish();}}, 3000);//delayMillis : 延迟时间    Runnable : 执行的操作}@Overridepublic void loadmore() {//延迟一段时间,加载数据new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//list.add("艾欧尼亚"+(++m)+"区");list.add("黑色玫瑰"+(++n)+"区");//将数据添加list集合的哪个位置,location : 位置  object:添加的数据//刷新界面arrayAdapter.notifyDataSetChanged();//取消刷新mListView.finish();}}, 3000);//delayMillis : 延迟时间    Runnable : 执行的操作}});}

3.布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <com.itheima.pulltorefreshlistview.PullToReFreshListView        android:id="@+id/listview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:divider="@android:color/darker_gray"        android:dividerHeight="0.5dp"        ></com.itheima.pulltorefreshlistview.PullToReFreshListView></RelativeLayout>

4.头条目布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal"     android:padding="6dp"    >        <RelativeLayout         android:layout_width="50dp"        android:layout_height="50dp"        android:layout_marginLeft="20dp"        >        <ImageView             android:id="@+id/arrow"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:src="@drawable/arrow"            android:layout_centerInParent="true"            />        <ProgressBar             android:id="@+id/pb"            android:layout_width="30dp"            android:layout_height="30dp"            android:layout_centerInParent="true"            android:indeterminateDrawable="@drawable/progressbarstyle"            android:visibility="gone"            />    </RelativeLayout>            <LinearLayout         android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical"        android:layout_gravity="center_vertical"        android:gravity="center_vertical|center_horizontal"        >        <!-- | : 加意思,两种效果全部生效 -->        <TextView             android:id="@+id/text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="下拉刷新"            android:textColor="#FF0000"            />        <TextView             android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="最后刷时间:2016-08-14 09:48:06"            android:textColor="@android:color/darker_gray"            />    </LinearLayout></LinearLayout>

5.脚条目布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal"     android:gravity="center"    >         <ProgressBar             android:id="@+id/pb"            android:layout_width="30dp"            android:layout_height="30dp"            android:indeterminateDrawable="@drawable/progressbarstyle"            android:layout_marginTop="10dp"            android:layout_marginBottom="10dp"            />          <TextView             android:id="@+id/text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="加载更多..."            android:textColor="#FF0000"            android:layout_marginTop="10dp"            android:layout_marginBottom="10dp"            android:layout_marginLeft="10dp"            /></LinearLayout>



0 0
原创粉丝点击