android下拉刷新ListView的介绍和实现代码

kx010101

kx010101

2016-02-19 10:09

有一种朋友不在生活里,却在生命力;有一种陪伴不在身边,却在心间。图老师即在大家的生活中又在身边。这么贴心的服务你感受到了吗?话不多说下面就和大家分享android下拉刷新ListView的介绍和实现代码吧。

    大致上,我们发现,下拉刷新的列表和一般列表的区别是,当滚动条在顶端的时候,再往下拉动就会把整个列表拉下来,显示出松开刷新的提示。由此可以看出,在构建这个下拉刷新的组件的时候,只用继承ListView,然后重写onTouchEvent就能实现。还有就是要能在xml布局文件中引用,还需要一个参数为Context,AttributeSet的构造函数。

  表面上的功能大概就这些了。另一方面,刷新的行为似乎还没有定义,在刷新前做什么,刷新时要做什么,刷新完成后要做什么,这些行为写入一个接口中,然后让组件去实现。

  在整个组件的实现中,主体部分自然是onTouchEvent的部分。这里需要做一些说明,在ListView中,数据的滚动和ListView.scrollTo的行为是不一样的。数据的滚动是大概适配器的事。所以在不满足下拉整个列表的条件下,onTouchEvent 应该返回super.onTouchEvent(ev),让ListView组件原本的OnTouchEvent去处理。

  考虑到组件的id和表头的布局需要事先定义,同时我想把这个组件应用于多个项目里,所以就把这个组件作为一个Library去实现。

     下面就是具体的实现代码。

  首先来看一下表头的布局文件chenzong_push_refresh_header.xml:

代码如下:

?xml version="1.0" encoding="utf-8"?
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dip"
      
    ImageView
        android:layout_width="30dip"
        android:layout_height="40dip"
        android:background="@drawable/arrow_down"
           android:layout_alignParentLeft="true"
        android:id="@+id/push_refresh_header_img"
        android:layout_marginLeft="10dip"
        /
    ProgressBar
        android:layout_width="40dip"
        android:layout_height="40dip"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="10dip"
        android:id="@+id/push_refresh_header_pb"
        style="@android:style/Widget.ProgressBar.Inverse"
        android:visibility="gone"/
    LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical"
       
        TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="最近一次更新在:"
            android:textColor="#000000"
            /
        TextView
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/push_refresh_header_date"
            android:textColor="#000000"
            android:text="2013-03-04 08:03:38"/
    /LinearLayout
/RelativeLayout

       箭头、processBar和最近的一次刷新时间,表头文件就这三个元素。

       刷新的行为接口RefreshOperation的代码:

代码如下:

public interface RefreshOperation {
    public void OnRefreshStart();
    public void OnRefreshing();
    public void OnRefreshEnd();
}

     列表拉下来时,箭头翻转的动画arrow_rotate.xml:

代码如下:

?xml version="1.0" encoding="utf-8"?
rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:fromDegrees="0"
    android:toDegrees="180"
    android:duration="300"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fillAfter="true"
    android:repeatCount="0"

/rotate

      这些文件和一些资源文件备齐了之后,接下来就是下拉刷新列表PushRefreshList的具体实现:

代码如下:

package com.chenzong;

import java.util.Calendar;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

import com.doall.pushrefreshlist.R;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ListView;
import android.widget.TextView;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

public class PushRefreshList extends ListView implements RefreshOperation{

    private int header_layout=R.layout.chenzong_push_refresh_header;
    //表头文件
    private int arrow_down=R.drawable.arrow_down;
    //箭头往下的资源
    private int arrow_up=R.drawable.arrow_up;
    //箭头往上的资源
    private int img=R.id.push_refresh_header_img;
    //显示箭头的控件id
    private int pb=R.id.push_refresh_header_pb;
    //刷新时的进度条
    private int startPoint=0;
    //触摸的起始点
    private RefreshOperation refresh;
    //刷新行为的对象
    private Animation animation=null;
    private Context context;
    private View headerView;
    private int minPushHeight;

   
    private final String TAG="pushRefresh";

    public PushRefreshList(Context cotext, AttributeSet attrs) {
        super(context, attrs);
        View empty=new View(context);
        //判断是否到列表的顶端,通常要用到this.getFirstVisiblePosition(),这里创建一个高度的为零View,加到headerView和数据之间
        this.addHeaderView(empty);
        LayoutInflater inflater=LayoutInflater.from(context);
        headerView=inflater.inflate(header_layout, null);
        this.addHeaderView(headerView);
        this.setRefreshOperation(this);
        this.context=context;

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        this.minPushHeight=headerView.getMeasuredHeight();
        //获取下拉刷新的触发高度
        super.onLayout(changed, l, t, r, b);
    }

    private boolean canHandleEvent(int dy)
    {
        return (dy0&&this.getFirstVisiblePosition()==0&&!isPbVisible());
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        int action=ev.getAction();
        switch(action)
        {
        case MotionEvent.ACTION_DOWN:
            startPoint=(int)ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            int dy=startPoint-(int)ev.getY();
            if(canHandleEvent(dy))
            {
                if(animation==null)
                {
                    if(Math.abs(this.getScrollY())=this.minPushHeight)
                    {   
                        animation=AnimationUtils.loadAnimation(context, R.anim.arrow_rotate);
                        View mView=headerView.findViewById(img);
                        mView.startAnimation(animation);
                        this.setScrollbarFadingEnabled(true);
                    }
                }
                this.scrollTo(0,dy/2);   
                return true;
            }
            break;
        case MotionEvent.ACTION_UP:

                this.setScrollbarFadingEnabled(false);
                if(animation!=null)
                {
                    setImgBackgroundUp();
                    switchCompent(View.INVISIBLE,View.VISIBLE);
                    this.scrollTo(0,-minPushHeight);
                    PushRefreshList.this.refresh.OnRefreshStart();
                    new Thread(mRunnable).start();
                    animation=null;
                }
                else
                    this.scrollTo(0,0);
            break;
        }
        return super.onTouchEvent(ev);
    }

    private Runnable mRunnable=new Runnable()
    {

        @Override
        public void run() {
            PushRefreshList.this.refresh.OnRefreshing();
            mHandler.obtainMessage().sendToTarget();
        }
    };

    private Handler mHandler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            PushRefreshList.this.refresh.OnRefreshEnd();
            PushRefreshList.this.scrollTo(0, 0);
            PushRefreshList.this.setImgBackgroundDown();
            PushRefreshList.this.switchCompent(View.VISIBLE, View.GONE);
            TextView tv=(TextView)headerView.findViewById(R.id.push_refresh_header_date);
            tv.setText(this.getDateStr());
        }

        private String getDateStr()
        {
            Calendar ca=Calendar.getInstance();
            int year=ca.get(Calendar.YEAR);
            int month=ca.get(Calendar.MONTH);
            int date=ca.get(Calendar.DATE);
            int hour=ca.get(Calendar.HOUR);
            int mintes=ca.get(Calendar.MINUTE);
            int second=ca.get(Calendar.SECOND);
            return year+"-"+(month+1)+"-"+date+" "+hour+":"+mintes+":"+second;
        }
    };

    private void switchCompent(int imgStatus,int pbStatus)
    {
        View img=headerView.findViewById(R.id.push_refresh_header_img);
        img.clearAnimation();
        //执行了动画的控件如果不调用clearAnimation,setVisibility(View.GONE)会失效
        img.setVisibility(imgStatus);
        headerView.findViewById(R.id.push_refresh_header_pb).setVisibility(pbStatus);
    }

    private boolean isPbVisible()
    {
        return View.VISIBLE==headerView.findViewById(R.id.push_refresh_header_pb).getVisibility();
    }

    private void setImgBackgroundUp()
    {
        View mView=headerView.findViewById(this.img);
        mView.setBackgroundResource(arrow_up);
    }

    private void setImgBackgroundDown()
    {
        View mView=headerView.findViewById(this.img);
        mView.setBackgroundResource(arrow_down);
    }

    public void setRefreshOperation(RefreshOperation refresh)
    {
        this.refresh=refresh;
    }

    @Override
    public void OnRefreshStart() {

    }

    @Override
    public void OnRefreshing() {

    }

    @Override
    public void OnRefreshEnd() {
    }

展开更多 50%)
分享

猜你喜欢

android下拉刷新ListView的介绍和实现代码

编程语言 网络编程
android下拉刷新ListView的介绍和实现代码

Android下拉刷新ListView——RTPullListView(demo)

编程语言 网络编程
Android下拉刷新ListView——RTPullListView(demo)

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

android ListView和GridView拖拽移位实现代码

编程语言 网络编程
android ListView和GridView拖拽移位实现代码

android panellistview 圆角实现代码

编程语言 网络编程
android panellistview 圆角实现代码

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

android屏幕全屏的实现代码

编程语言 网络编程
android屏幕全屏的实现代码

Android 倒影算法的实现代码

编程语言 网络编程
Android 倒影算法的实现代码

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Android 用SQLite实现事务的方法

Android 用SQLite实现事务的方法

基于Android XML解析与保存的实现

基于Android XML解析与保存的实现
下拉加载更多内容 ↓