android ListView的上部下拉刷新下部点击加载更多具体实现及拓展

android ListView的上部下拉刷新下部点击加载更多具体实现及拓展

发布: admin | 类别: 程序开发 | 点击:3519 | 更新时间:2018-04-07 08:51:16

0 条评论

这次就不上图了,例子太多太多了,想必大家都见过.这个功能的实现,简直是开发者必备的.
我也不过多介绍了,网上详细介绍的博客太多太多了,若想深入了解,请参考网上其他博文.
在这里,我只是按照自己的理解,模拟实现了一个,顺便代码贡献出来.
我对之详细标明的注释,想必如果不懂的同学们,看注释也应该明白,前提是,你要耐心看,因为代码有点多,但是我整理过了,还算清晰.
详细代码:
[java]
package com.jj.drag; 
 
import android.content.Context; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.view.animation.Animation; 
import android.view.animation.LinearInterpolator; 
import android.view.animation.RotateAnimation; 
import android.widget.AbsListView; 
import android.widget.AbsListView.OnScrollListener; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 
import android.widget.ListView; 
import android.widget.ProgressBar; 
import android.widget.RelativeLayout; 
import android.widget.TextView; 
 
/***
 * 自定义拖拉ListView
 * 
 * @author zhangjia
 * 
 */ 
public class DragListView extends ListView implements OnScrollListener, 
        OnClickListener { 
    // 拖拉ListView枚举所有状态 
    private enum DListViewState { 
        LV_NORMAL, // 普通状态 
        LV_PULL_REFRESH, // 下拉状态(为超过mHeadViewHeight) 
        LV_RELEASE_REFRESH, // 松开可刷新状态(超过mHeadViewHeight) 
        LV_LOADING;// 加载状态 
    } 
 
    // 点击加载更多枚举所有状态 
    private enum DListViewLoadingMore { 
        LV_NORMAL, // 普通状态 
        LV_LOADING, // 加载状态 
        LV_OVER; // 结束状态 
    } 
 
    private View mHeadView;// 头部headView 
    private TextView mRefreshTextview; // 刷新msg(mHeadView) 
    private TextView mLastUpdateTextView;// 更新事件(mHeadView) 
    private ImageView mArrowImageView;// 下拉图标(mHeadView) 
    private ProgressBar mHeadProgressBar;// 刷新进度体(mHeadView) 
 
    private int mHeadViewWidth; // headView的宽(mHeadView) 
    private int mHeadViewHeight;// headView的高(mHeadView) 
 
    private View mFootView;// 尾部mFootView 
    private View mLoadMoreView;// mFootView 的view(mFootView) 
    private TextView mLoadMoreTextView;// 加载更多.(mFootView) 
    private View mLoadingView;// 加载中...View(mFootView) 
 
    private Animation animation, reverseAnimation;// 旋转动画,旋转动画之后旋转动画. 
 
    private int mFirstItemIndex = -1;// 当前视图能看到的第一个项的索引 
 
    // 用于保证startY的值在一个完整的touch事件中只被记录一次 
    private boolean mIsRecord = false; 
 
    private int mStartY, mMoveY;// 按下是的y坐标,move时的y坐标 
 
    private DListViewState mlistViewState = DListViewState.LV_NORMAL;// 拖拉状态.(自定义枚举) 
 
    private DListViewLoadingMore loadingMoreState = DListViewLoadingMore.LV_NORMAL;// 加载更多默认状态. 
 
    private final static int RATIO = 2;// 手势下拉距离比. 
 
    private boolean mBack = false;// headView是否返回. 
 
    private OnRefreshLoadingMoreListener onRefreshLoadingMoreListener;// 下拉刷新接口(自定义) 
 
    private boolean isScroller = true;// 是否屏蔽ListView滑动。 
 
    public DragListView(Context context) { 
        super(context, null); 
        initDragListView(context); 
    } 
 
    public DragListView(Context context, AttributeSet attrs) { 
        super(context, attrs); 
        initDragListView(context); 
    } 
 
    // 注入下拉刷新接口 
    public void setOnRefreshListener( 
            OnRefreshLoadingMoreListener onRefreshLoadingMoreListener) { 
        this.onRefreshLoadingMoreListener = onRefreshLoadingMoreListener; 
    } 
 
    /***
     * 初始化ListView
     */ 
    public void initDragListView(Context context) { 
 
        String time = "1994.12.05";// 更新时间 
 
        initHeadView(context, time);// 初始化该head. 
 
        initLoadMoreView(context);// 初始化footer 
 
        setOnScrollListener(this);// ListView滚动监听 
    } 
 
    /***
     * 初始话头部HeadView
     * 
     * @param context
     *            上下文
     * @param time
     *            上次更新时间
     */ 
    public void initHeadView(Context context, String time) { 
        mHeadView = LayoutInflater.from(context).inflate(R.layout.head, null); 
        mArrowImageView = (ImageView) mHeadView 
                .findViewById(R.id.head_arrowImageView); 
        mArrowImageView.setMinimumWidth(60); 
 
        mHeadProgressBar = (ProgressBar) mHeadView 
                .findViewById(R.id.head_progressBar); 
 
        mRefreshTextview = (TextView) mHeadView 
                .findViewById(R.id.head_tipsTextView); 
 
        mLastUpdateTextView = (TextView) mHeadView 
                .findViewById(R.id.head_lastUpdatedTextView); 
        // 显示更新事件 
        mLastUpdateTextView.setText("最近更新:" + time); 
 
        measureView(mHeadView); 
        // 获取宽和高 
        mHeadViewWidth = mHeadView.getMeasuredWidth(); 
        mHeadViewHeight = mHeadView.getMeasuredHeight(); 
 
        addHeaderView(mHeadView, null, false);// 将初始好的ListView add进拖拽ListView 
        // 在这里我们要将此headView设置到顶部不显示位置. 
        mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0); 
 
        initAnimation();// 初始化动画 
    } 
 
    /***
     * 初始化底部加载更多控件
     */ 
    private void initLoadMoreView(Context context) { 
        mFootView = LayoutInflater.from(context).inflate(R.layout.footer, null); 
 
        mLoadMoreView = mFootView.findViewById(R.id.load_more_view); 
 
        mLoadMoreTextView = (TextView) mFootView 
                .findViewById(R.id.load_more_tv); 
 
        mLoadingView = (LinearLayout) mFootView 
                .findViewById(R.id.loading_layout); 
 
        mLoadMoreView.setOnClickListener(this); 
 
        addFooterView(mFootView); 
    } 
 
    /***
     * 初始化动画
     */ 
    private void initAnimation() { 
        // 旋转动画 
        animation = new RotateAnimation(0, -180, 
                RotateAnimation.RELATIVE_TO_SELF, 0.5f, 
                RotateAnimation.RELATIVE_TO_SELF, 0.5f); 
        animation.setInterpolator(new LinearInterpolator());// 匀速 
        animation.setDuration(250); 
        animation.setFillAfter(true);// 停留在最后状态. 
        // 反向旋转动画 
        reverseAnimation = new RotateAnimation(-180, 0, 
                RotateAnimation.RELATIVE_TO_SELF, 0.5f, 
                RotateAnimation.RELATIVE_TO_SELF, 0.5f); 
        reverseAnimation.setInterpolator(new LinearInterpolator()); 
        reverseAnimation.setDuration(250); 
        reverseAnimation.setFillAfter(true); 
    } 
 
    /***
     * 作用:测量 headView的宽和高.
     * 
     * @param child
     */ 
    private void measureView(View child) { 
        ViewGroup.LayoutParams p = child.getLayoutParams(); 
        if (p == null) { 
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
                    ViewGroup.LayoutParams.WRAP_CONTENT); 
        } 
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width); 
        int lpHeight = p.height; 
        int childHeightSpec; 
        if (lpHeight > 0) { 
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, 
                    MeasureSpec.EXACTLY); 
        } else { 
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, 
                    MeasureSpec.UNSPECIFIED); 
        } 
        child.measure(childWidthSpec, childHeightSpec); 
    } 
 
    /***
     * touch 事件监听
     */ 
    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
        switch (ev.getAction()) { 
        // 按下 
        case MotionEvent.ACTION_DOWN: 
            doActionDown(ev); 
            break; 
        // 移动 
        case MotionEvent.ACTION_MOVE: 
            doActionMove(ev); 
            break; 
        // 抬起 
        case MotionEvent.ACTION_UP: 
            doActionUp(ev); 
            break; 
        default: 
            break; 
        } 
        /***
         * 如果是ListView本身的拉动,那么返回true,这样ListView不可以拖动.
         * 如果不是ListView的拉动,那么调用父类方法,这样就可以上拉执行.
         */ 
        if (isScroller) { 
            return super.onTouchEvent(ev); 
        } else { 
            return true; 
        } 
 
    } 
 
    /***
     * 摁下操作
     * 
     * 作用:获取摁下是的y坐标
     * 
     * @param event
     */ 
    void doActionDown(MotionEvent event) { 
        if (mIsRecord == false && mFirstItemIndex == 0) { 
            mStartY = (int) event.getY(); 
            mIsRecord = true; 
        } 
    } 
 
    /***
     * 拖拽移动操作
     * 
     * @param event
     */ 
    void doActionMove(MotionEvent event) { 
        mMoveY = (int) event.getY();// 获取实时滑动y坐标 
        // 检测是否是一次touch事件. 
        if (mIsRecord == false && mFirstItemIndex == 0)

关键字 :程序开发 android

0 条评论

 

欢迎留下您的评论

红框选项必须输入,不允许html代码。

联系我们

  • Address: Floor.15,Building No.1,Idealism center ,No.38 Tianyi Street, Chengdu high tech Zone,Sichuan China, 610000
  • Phone Number: 18908191278 028-61408608
  • Website: www.drawnet.cn
  • QQ: 464410235
  • WeChat: 464410235
  • Email: master@drawnet.cn

关于我们

关注微信公众号

扫码关注微信服务号

进入微信小程序

扫码进入微信小程序