Android - 框架】之刷新加载框架Ultra-Pull-To-Refresh的使用,及其自定义头部刷新和底部加载更多

最近项目已经接近尾声了,由于一些原因,我可能又要找新的工作了,啊啊啊,有点忧伤。

之前有在新浪写过一写博客,现在准备在CSDN上写博客了,CSDN博客-最大IT写作分享平台,很多资料都可以在这找到,所有我也搬家了。

自己也写了好几个项目了,但是博客还没有多少,其实有很多东西都需要记记得,温故而知新嘛!趁不忙,就记录记录。

好了 ,上面的可以忽略,下面正式开始了!

 

下拉刷新,上拉加载更多

地址:https://github.com/captainbupt/android-Ultra-Pull-To-Refresh-With-Load-More

 

优点:

这个框架的扩展性还是很强的,头部和底部都可以自定义,

它其中可以嵌套任何控件,ListView、GridView、ScrollView、RecyclerView,甚至TextView。

更多样式参照GitHub中的源码

 

一.jar包的引用

开发工具是AS

在gradle添加到项目中,我这里是1.0.6,最新版可以到githup上看

 

compile 'in.srain.cube:ptr-load-more:1.0.6'

 

 

 

二、使用方法

首先在你需要刷新和加载的地方,最外层加入

in.srain.cube.views.ptr.PtrClassicFrameLayout

 

 

以我的为例,我这是给gridview加刷新和加载更多

 

在xml中

 

<in.srain.cube.views.ptr.PtrClassicFrameLayout android:id="@+id/rotate_header_grid_view_frame" 
android:layout_width="match_parent" 
android:layout_height="match_parent"
 app:ptr_duration_to_close_either="1000"
 app:ptr_keep_header_when_refresh="true"
 app:ptr_pull_to_fresh="false" 
app:ptr_ratio_of_header_height_to_refresh="1.2" 
app:ptr_resistance="1.7"> 
<GridView android:id="@+id/myPoints_gridview"
 android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:layout_marginBottom="@dimen/margin_ten" android:layout_marginLeft="@dimen/margin_ten" android:layout_marginRight="@dimen/margin_ten" 
android:layout_marginTop="@dimen/margin_ten"
 android:fadingEdge="none" 
android:horizontalSpacing="@dimen/margin_ten" android:listSelector="@android:color/transparent" android:numColumns="2" android:overScrollMode="never" android:scrollbars="none" android:verticalSpacing="@dimen/margin_ten">
</GridView></in.srain.cube.views.ptr.PtrClassicFrameLayout>
<!--  ptr:ptr_duration_to_close_either:头部和底部回弹时间  ptr:ptr_keep_header_when_refresh:刷新过程中是否保留头部  ptr:ptr_pull_to_fresh:下拉刷新/释放刷新,默认是释放刷新  ptr:ptr_ratio_of_header_height_to_refresh:触发刷新时移动的位置比例,指的是与头部的比例  ptr:ptr_resistance:阻尼系数,越大下拉越吃力 -->

 

 

 

在Activity中

 

使用默认样式

//初始化

 

@ViewInject(R.id.rotate_header_grid_view_frame)
private PtrClassicFrameLayout mPtrFrame;

 

 

 

//在oncreate中

 

 
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);  setContentView(R.layout.activity_my_points);  initReFresh(); }

 

 

 

 

 

/**
 * 设置下拉刷新上拉加载
 */
private void initReFresh() {

    //设置下拉刷新上拉加载
    mPtrFrame.disableWhenHorizontalMove(true);//解决横向滑动冲突
    mPtrFrame.setPtrHandler(new PtrDefaultHandler2() {
                                @Override
                                public void onRefreshBegin(PtrFrameLayout frame) {
                                    mPtrFrame.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                          //刷新数据
                                        }
                                    }, 1000);
                                }

                                @Override
                                public void onLoadMoreBegin(PtrFrameLayout frame) {
                                    mPtrFrame.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                       //加载更多
                                        }
                                    }, 1000);
                                }

                                @Override
                                public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {

                                    return super.checkCanDoLoadMore(frame, gridView, footer);

                                }

                                @Override
                                public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                                    return super.checkCanDoRefresh(frame, gridView, header);
                                }


                            }

    );


}

//结束刷新和加载更多的动画,在你成功请求到数据后写入

 

 

mPtrFrame.refreshComplete();

 

 

 

默认样式就是这样了

 

自定义头的部和底部

自定时都继承PtrUIHandler

 

自定义的头部文件

MyHeadView

 

package com.example.ruidun.ShanXunApplication.view;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.example.ruidun.ShanXunApplication.R;

import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrUIHandler;
import in.srain.cube.views.ptr.indicator.PtrIndicator;

/**
 * 
 * 项目名称:¥{PROJECT_NAME}
 * 创建人:潇潇
 * 
 */

public class MyHeadView extends FrameLayout implements PtrUIHandler {

    private TextView tvLoading;
    private View view;

    //箭头
    private ImageView mArrowImageView;
    //开始加载的动画
    private ProgressBar mProgressBar;
    //动画
    private Animation mRotateUpAnim;
    //显示当前进度的textview
    private TextView mHintTextView;
    private Animation mRotateDownAnim;
    private final int ROTATE_ANIM_DURATION = 180;


    public MyHeadView(Context context) {
        this(context, null);
    }

    public MyHeadView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    //实例化控件
    private void init() {
        view = LayoutInflater.from(getContext()).inflate(R.layout.xlistview_header, this, false);
        addView(view);
        tvLoading = (TextView) view.findViewById(R.id.xlistview_header_hint_textview);
        mArrowImageView = (ImageView) view.findViewById(R.id.xlistview_header_arrow);
        mProgressBar = (ProgressBar) view.findViewById(R.id.xlistview_header_progressbar);
        mHintTextView = (TextView) view.findViewById(R.id.xlistview_header_hint_textview);

// 初始情况,设置下拉刷新view高度为0

        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateUpAnim.setFillAfter(true);

        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateDownAnim.setFillAfter(true);
    }

    //重写方法
    @Override
    public void onUIReset(PtrFrameLayout frame) {
        //重置
    }

    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
        //准备刷新    //重置时,将动画置为初始状态
        mArrowImageView.clearAnimation();
        mArrowImageView.startAnimation(mRotateUpAnim);
        mHintTextView.setText(R.string.xlistview_header_hint_ready);
    }

    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        //开始刷新 显示刷新进度跟文本   //开始刷新,启动动画
        mArrowImageView.setVisibility(View.INVISIBLE);
        mProgressBar.setVisibility(View.VISIBLE);
        tvLoading.setText("正在加载");
    }


    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame, boolean isHeader) {
        //刷新完成  设置文本 设置进度隐藏
        tvLoading.setText("加载完毕");
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mArrowImageView.setVisibility(View.VISIBLE);
                mProgressBar.setVisibility(View.INVISIBLE);
            }
        }, 500);

    }


    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
        final int mOffsetToRefresh = frame.getOffsetToRefresh();
        final int currentPos = ptrIndicator.getCurrentPosY();
        final int lastPos = ptrIndicator.getLastPosY();



        if (currentPos < mOffsetToRefresh) {
            //未到达刷新线
            if (status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                mArrowImageView.startAnimation(mRotateDownAnim);
                tvLoading.setText("下拉刷新");
            }

        } else if (currentPos > mOffsetToRefresh) {
            //到达或超过刷新线
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                mArrowImageView.clearAnimation();
                tvLoading.setText("释放刷新");

            }
        }




    }



    //设置背景色
    public void setHeadColor(int color) {
        view.setBackgroundColor(color);
    }
}

 

自定义底部布局跟自定义头布局都是一样

 

MyFooterView

 

package com.example.ruidun.ShanXunApplication.view;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.example.ruidun.ShanXunApplication.R;

import java.text.SimpleDateFormat;
import java.util.Date;

import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrUIHandler;
import in.srain.cube.views.ptr.indicator.PtrIndicator;

/**
 * 
 * 项目名称:¥{PROJECT_NAME}
 * 创建人:潇潇
 * 
 */

public class MyFooterView extends FrameLayout implements PtrUIHandler {

    private final static String KEY_SharedPreferences = "cube_ptr_classic_last_update";
    private static SimpleDateFormat sDataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private int mRotateAniTime = 150;
    protected RotateAnimation mFlipAnimation;
    protected RotateAnimation mReverseFlipAnimation;

    //当前加载进度描述
    protected TextView mTitleTextView;
    //加载动画
    private View mProgressBar;
    private long mLastUpdateTime = -1;
    private String mLastUpdateTimeKey;
    private boolean mShouldShowLastUpdate;


    private MyFooterView.LastUpdateTimeUpdater mLastUpdateTimeUpdater = new MyFooterView.LastUpdateTimeUpdater();

    public MyFooterView(Context context) {
        super(context);
        initViews(null);
    }

    public MyFooterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews(attrs);
    }

    public MyFooterView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initViews(attrs);
    }

    //初始化布局
    protected void initViews(AttributeSet attrs) {
        TypedArray arr = getContext().obtainStyledAttributes(attrs, in.srain.cube.views.ptr.R.styleable.PtrClassicHeader, 0, 0);
        if (arr != null) {
            mRotateAniTime = arr.getInt(in.srain.cube.views.ptr.R.styleable.PtrClassicHeader_ptr_rotate_ani_time, mRotateAniTime);
        }
        buildAnimation();
        View header = LayoutInflater.from(getContext()).inflate(R.layout.xlistview_footer, this);
        mTitleTextView = (TextView) header.findViewById(R.id.xlistview_footer_hint_textview);
        mProgressBar = header.findViewById(R.id.xlistview_footer_progressbar);
        resetView();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mLastUpdateTimeUpdater != null) {
            mLastUpdateTimeUpdater.stop();
        }
    }

    public void setRotateAniTime(int time) {
        if (time == mRotateAniTime || time == 0) {
            return;
        }
        mRotateAniTime = time;
        buildAnimation();
    }

    /**
     * Specify the last update time by this key string
     *
     * @param key
     */
    public void setLastUpdateTimeKey(String key) {
        if (TextUtils.isEmpty(key)) {
            return;
        }
        mLastUpdateTimeKey = key;
    }

    /**
     * Using an object to specify the last update time.
     *
     * @param object
     */
    public void setLastUpdateTimeRelateObject(Object object) {
        setLastUpdateTimeKey(object.getClass().getName() + "footer");
    }

    //加载时的动画效果
    protected void buildAnimation() {
        mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mFlipAnimation.setInterpolator(new LinearInterpolator());
        mFlipAnimation.setDuration(mRotateAniTime);
        mFlipAnimation.setFillAfter(true);

        mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
        mReverseFlipAnimation.setDuration(mRotateAniTime);
        mReverseFlipAnimation.setFillAfter(true);
    }

    private void resetView() {
        hideRotateView();
        mProgressBar.setVisibility(INVISIBLE);
    }

    private void hideRotateView() {
//        mRotateView.clearAnimation();
//        mRotateView.setVisibility(INVISIBLE);
    }

    @Override
    public void onUIReset(PtrFrameLayout frame) {
        //重置
        resetView();
        mShouldShowLastUpdate = true;
        tryUpdateLastUpdateTime();
    }

    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
        //准备加载更多   //重置时,将动画置为初始状态
        mShouldShowLastUpdate = true;
        tryUpdateLastUpdateTime();
        mLastUpdateTimeUpdater.start();

        mProgressBar.setVisibility(INVISIBLE);

//        mRotateView.setVisibility(VISIBLE);
        mTitleTextView.setVisibility(VISIBLE);
        if (frame.isPullToRefresh()) {
            //释放加载
            mTitleTextView.setText("松开载入更多");
        } else {
            //上拉
            mTitleTextView.setText("查看更多");
        }
    }

    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        //开始加载

        mShouldShowLastUpdate = false;
        hideRotateView();
        mProgressBar.setVisibility(VISIBLE);
        //正在加载中
        mTitleTextView.setVisibility(GONE);
        mTitleTextView.setText(in.srain.cube.views.ptr.R.string.cube_ptr_loading);

        tryUpdateLastUpdateTime();
        mLastUpdateTimeUpdater.stop();
    }

    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame, boolean isHeader) {
        //加载完成

        if (isHeader) {
            return;
        }
        hideRotateView();
        mProgressBar.setVisibility(INVISIBLE);

        //加载完成
        mTitleTextView.setVisibility(VISIBLE);
        mTitleTextView.setText(getResources().getString(in.srain.cube.views.ptr.R.string.cube_ptr_load_complete));

        // update last update time
        SharedPreferences sharedPreferences = getContext().getSharedPreferences(KEY_SharedPreferences, 0);
        if (!TextUtils.isEmpty(mLastUpdateTimeKey)) {
            mLastUpdateTime = new Date().getTime();
            sharedPreferences.edit().putLong(mLastUpdateTimeKey, mLastUpdateTime).commit();
        }
    }

    private void tryUpdateLastUpdateTime() {
        if (TextUtils.isEmpty(mLastUpdateTimeKey) || !mShouldShowLastUpdate) {

        } else {
            String time = getLastUpdateTime();
            if (TextUtils.isEmpty(time)) {

            } else {

            }
        }
    }

    private String getLastUpdateTime() {

        if (mLastUpdateTime == -1 && !TextUtils.isEmpty(mLastUpdateTimeKey)) {
            mLastUpdateTime = getContext().getSharedPreferences(KEY_SharedPreferences, 0).getLong(mLastUpdateTimeKey, -1);
        }
        if (mLastUpdateTime == -1) {
            return null;
        }
        long diffTime = new Date().getTime() - mLastUpdateTime;
        int seconds = (int) (diffTime / 1000);
        if (diffTime < 0) {
            return null;
        }
        if (seconds <= 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_last_update));

        if (seconds < 60) {
            sb.append(seconds + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_seconds_ago));
        } else {
            int minutes = (seconds / 60);
            if (minutes > 60) {
                int hours = minutes / 60;
                if (hours > 24) {
                    Date date = new Date(mLastUpdateTime);
                    sb.append(sDataFormat.format(date));
                } else {
                    sb.append(hours + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_hours_ago));
                }

            } else {
                sb.append(minutes + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_minutes_ago));
            }
        }
        return sb.toString();
    }

    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {

        final int mOffsetToRefresh = frame.getOffsetToRefresh();
        final int currentPos = ptrIndicator.getCurrentPosY();
        final int lastPos = ptrIndicator.getLastPosY();

        if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                crossRotateLineFromBottomUnderTouch(frame);
//                if (mRotateView != null) {
//                    mRotateView.clearAnimation();
//                    mRotateView.startAnimation(mReverseFlipAnimation);
//                }
            }
        } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                crossRotateLineFromTopUnderTouch(frame);
//                if (mRotateView != null) {
//                    mRotateView.clearAnimation();
//                    mRotateView.startAnimation(mFlipAnimation);
//                }
            }
        }
    }

    private void crossRotateLineFromTopUnderTouch(PtrFrameLayout frame) {
        if (!frame.isPullToRefresh()) {
            mTitleTextView.setVisibility(VISIBLE);
            mTitleTextView.setText("松开载入更多");
        }
    }

    private void crossRotateLineFromBottomUnderTouch(PtrFrameLayout frame) {
        mTitleTextView.setVisibility(VISIBLE);
        if (frame.isPullToRefresh()) {
            mTitleTextView.setText("松开载入更多");
        } else {
            mTitleTextView.setText("查看更多");
        }
    }

    private class LastUpdateTimeUpdater implements Runnable {

        private boolean mRunning = false;

        private void start() {
            if (TextUtils.isEmpty(mLastUpdateTimeKey)) {
                return;
            }
            mRunning = true;
            run();
        }

        private void stop() {
            mRunning = false;
            removeCallbacks(this);
        }

        @Override
        public void run() {
            tryUpdateLastUpdateTime();
            if (mRunning) {
                postDelayed(this, 1000);
            }
        }
    }
}

 

 

 

 

 

 

 

 

在Activity中使用吧头布局和底部加上就ok了

 

 

/**
 * 设置下拉刷新上拉加载
 */
private void initReFresh() {


    MyFooterView fView = new MyFooterView(MyPointsActivity.this);//自定义底部加载更多
    mPtrFrame.setFooterView(fView);
    mPtrFrame.addPtrUIHandler(fView);


    MyHeadView hView = new MyHeadView(MyPointsActivity.this); //自定义头部 刷新
    mPtrFrame.setKeepHeaderWhenRefresh(true);//刷新时保留头部
    mPtrFrame.setHeaderView(hView);
    mPtrFrame.addPtrUIHandler(hView);


    //设置下拉刷新上拉加载
    mPtrFrame.disableWhenHorizontalMove(true);//解决横向滑动冲突
    mPtrFrame.setPtrHandler(new PtrDefaultHandler2() {
                                @Override
                                public void onRefreshBegin(PtrFrameLayout frame) {
                                    mPtrFrame.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                           //刷新
                                           
                                        }
                                    }, 1000);
                                }

                                @Override
                                public void onLoadMoreBegin(PtrFrameLayout frame) {
                                    mPtrFrame.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            //加载更多

                                        }
                                    }, 1000);
                                }

                                @Override
                                public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {

                                    return super.checkCanDoLoadMore(frame, gridView, footer);

                                }

                                @Override
                                public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                                    return super.checkCanDoRefresh(frame, gridView, header);
                                }


                            }

    );


}

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值