鹅厂系列四 : 仿QQ下拉刷新

—— 黄观,我们之前提到过这个人,他就是明朝的另一个连中三元者,当时他的职务是右侍中。他的募兵没有多大效果,但在听到京城即将不保的消息后,他仍然坚持要到京城去,虽然他也明白这一去必无生理。但对于他而言,履行诺言,尽到职责的意义要远远大于苟且偷生。当他走到安庆时,消息传来:京城沦陷了,新皇帝已经登基。黄观明白大势已去,但他却没有人们想象中的慌张,只是哀叹痛哭道:“我的妻子是有气节的人,她一定已经死了。”之后他为妻子招魂,办理完必要的仪式,便坐船沿江而下。到罗刹矶时,他穿戴整齐,向东而拜,投江自尽。黄观没有说错,他的妻子在他之前已经带着两个女儿和十个亲属在淮清桥上投江而死。无论如何,他们夫妇最终还是团圆了。黄观作为朱允炆的亲信和殉节者,遭到了朱棣的妒恨,他把黄观的名字从登科榜上划去,于是明朝的历史上只留下了一位连中三元者商辂的记载。虽然之前我们曾经提到过这件事情,但在此我还是要为这位勇敢的人再次正名:黄观,洪武年间连中三元,其登科名为篡权者朱棣划去,尽忠而死。我相信,真相是永远无法掩盖的。

看看效果吧
效果1效果2

(黄观是真的连中三元,经过六次考试(县考、府考、院考、乡试、会试、殿试),均获第一名,时人赞誉他“三元天下有,六首世间无。”,明朝很厉害的一个人,太可惜了. 商辂第一次会试的时候没考好,隔了十年才拿到第一名)右边,是鹅厂系列前三整合,有兴趣的可以去看看http://blog.csdn.net/z8z87878 嗯,先来看看这个下拉刷新的实现原理吧,这个头上的刷新视图是

addHeaderView(mHeadView);

效果是这样子的
初始化

这样子后

addHeaderView(mHeadView);
        mHeadView.setPadding(0,-80,0,0); //setPadding(int left, int top, int right, int bottom)

效果是这样子的
处理1

然后我们再这样子改改

addHeaderView(mHeadView);
        mHeadView.setPadding(0,80,0,0); //setPadding(int left, int top, int right, int bottom)

然后结果是这样子的
处理2

即,我们可以通过设置padding来控制上面的刷新视图,默认它是setPadding(0,0,0,0)的,我们改变它的第二个参数,即top就能控制隐藏还是显示出来.所以我们这里是根据这个来实现下拉刷新的.来吧,开始慢慢实现吧,先实现正常滑动

public class RefreshListview extends ListView {
    private int mHeadViewHeight;
    private View mHeadView;

    private ImageView mIv_arrow;
    private ProgressBar mProgressBar;
    private TextView mTextView;

    private int mTopPadding;

    public RefreshListview(Context context) {
        super(context);

        init(context);
    }

    public RefreshListview(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context);


    }

    public void init(Context context) {
        mHeadView = View.inflate(context, R.layout.head_item, null);

        mIv_arrow = (ImageView) mHeadView.findViewById(R.id.iv_arrow);
        mProgressBar = (ProgressBar) mHeadView.findViewById(R.id.progress);
        mTextView = (TextView) mHeadView.findViewById(R.id.head_text);

        addHeaderView(mHeadView);


        mHeadView.measure(0,0);  //叫系统去给我测量
        mHeadViewHeight = mHeadView.getMeasuredHeight();
        mHeadView.setPadding(0,-mHeadViewHeight,0,0);           //设置负的Padding,顶上去

    }


    private int mDownY = 0;
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()){

            case MotionEvent.ACTION_DOWN:
                mDownY = (int) ev.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:

                int deleY = (int) (ev.getRawY() - mDownY);  //滑动距离

                mTopPadding = deleY - mHeadViewHeight;

                if (mTopPadding > - mHeadViewHeight && getFirstVisiblePosition() == 0){  //topPadding不能小于头视图的高度,防止滑不下来

                    mHeadView.setPadding(0, mTopPadding,0,0);


                    return true;  //拦截listview的滑动事件,仿止滑的距离不受控制
                }

                break;

            case MotionEvent.ACTION_UP:


                break;
        }


        return super.onTouchEvent(ev);
    }

}

xiaoguo

嗯,这样子就可以正常滑动了,接下来我们该做的就是去触摸的滑动那根据topPadding是不是大于等于0,下拉和释放刷新状态判断,在抬起那判断是刷新,还是隐藏头视图.

private int mDownY = 0;
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()){

            case MotionEvent.ACTION_DOWN:
                mDownY = (int) ev.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:

                int deleY = (int) (ev.getRawY() - mDownY);  //滑动距离

                mTopPadding = deleY - mHeadViewHeight;

                if (mTopPadding > - mHeadViewHeight && getFirstVisiblePosition() == 0){  //topPadding不能小于头视图的高度,防止滑不下来

                    mHeadView.setPadding(0, mTopPadding,0,0);

                    if (mTopPadding >= 0 && curStatus == PULL_TO_REFRESH){ //滑动状态下只允许由下拉进入松开
                        curStatus = RELEASE_TO_REFRESH;
                        RefreshStatusChanged();

                    }else if (mTopPadding < 0 && curStatus == RELEASE_TO_REFRESH){//同上理
                        curStatus = PULL_TO_REFRESH;
                        RefreshStatusChanged();
                    }


                    return true;  //拦截listview的滑动事件,仿止滑的距离不受控制
                }

                break;

            case MotionEvent.ACTION_UP:


                if (mTopPadding >= 0 && curStatus == RELEASE_TO_REFRESH){ //只能由释放刷新状态进入刷新状态

                    mHeadView.setPadding(0,0,0,0);
                    curStatus = NOW_TO_REFRESH;
                    RefreshStatusChanged();

                    if (mOnRefreshListener != null){
                        mOnRefreshListener.onRefresh();//接口回调
                    }

                }else {

                    mHeadView.setPadding(0,-mHeadViewHeight,0,0); //关闭刷新视图

                }


                break;
        }


        return super.onTouchEvent(ev);
    }


    private void RefreshStatusChanged(){

        switch (curStatus){

            case PULL_TO_REFRESH:
                mTextView.setText("下拉刷新");
                mIv_arrow.startAnimation(rel_to_pull_animation);

                break;

            case RELEASE_TO_REFRESH:

                mTextView.setText("释放立即刷新");
                mIv_arrow.startAnimation(pull_to_rel_animation);

                break;

            case NOW_TO_REFRESH:

                mIv_arrow.clearAnimation();        //清除动画,不然动画没完成不能隐藏
                mIv_arrow.setVisibility(INVISIBLE);
                mProgressBar.setVisibility(VISIBLE);
                mTextView.setText("正在刷新中....");

                break;

        }
    }

xiao

好了,到这里是不是就基本做完了,接下来就是设置刷新成功,或刷新失败的函数由外部调用了,还有刷新的监听接口回调

 /**刷新成功
     * @param handler
     */
    public void RefreshSuccess(Handler handler){
        mTextView.setText("刷新成功");
        mProgressBar.setVisibility(INVISIBLE);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mHeadView.setPadding(0,-mHeadViewHeight,0,0);
                mIv_arrow.setVisibility(VISIBLE);
                mTextView.setText("下拉刷新");
                curStatus = PULL_TO_REFRESH;
            }
        },1000);
    }

    /**
     * 刷新失败
     */
    public void RefreshError(){
        mProgressBar.setVisibility(INVISIBLE);
        mHeadView.setPadding(0,-mHeadViewHeight,0,0);
        mIv_arrow.setVisibility(VISIBLE);
        mTextView.setText("下拉刷新");
        curStatus = PULL_TO_REFRESH;
    }


    public interface OnRefreshListener{

        void onRefresh();
    }

    private OnRefreshListener mOnRefreshListener;
    public void setOnRefreshListener(OnRefreshListener onRefreshListener){
        mOnRefreshListener = onRefreshListener;
    }

activity中的代码

public class MainActivity extends Activity {

    public Handler mHandler = new Handler();
    private RefreshListview mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);


        mListView = (RefreshListview) findViewById(R.id.list);

        String data[] = new String[50];
        for (int i = 0; i < data.length; i++) {

            data[i] = "去吧去吧     "+i;
        }


        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data){

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                TextView view = (TextView) super.getView(position, convertView, parent);  //这个布局就是一个textView,修改字体颜色
                view.setTextColor(Color.BLACK);
                return view;
            }
        };



        mListView.setAdapter(adapter);


        mListView.setOnRefreshListener(new RefreshListview.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      mListView.RefreshSuccess(mHandler);
                      //mListView.RefreshError();
                    }
                },3000);
            }
        });

    }
}

嗯,到这就完了…这个控件相对比较简单..原理说明白了,感觉没什么好说的..有问题,评论问我吧,这里贴下控件完整代码,工程文件审核通过好,我会在评论区把这个还有整合前面侧滑菜单,侧拉删除,消息拖动小球的代码下载链接贴出来

public class RefreshListview extends ListView {


    private int mHeadViewHeight;
    private View mHeadView;

    private static final int PULL_TO_REFRESH = 1;            //下拉刷新
    private static final int RELEASE_TO_REFRESH = 2;         //松开刷新
    private static final int NOW_TO_REFRESH = 3;            //刷新中

    private int curStatus = PULL_TO_REFRESH;        //当前状态为下拉刷新

    private ImageView mIv_arrow;
    private ProgressBar mProgressBar;
    private TextView mTextView;

    private RotateAnimation pull_to_rel_animation;
    private RotateAnimation rel_to_pull_animation;
    private int mTopPadding;

    public RefreshListview(Context context) {
        super(context);

        init(context);
    }

    public RefreshListview(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context);


    }

    public void init(Context context) {
        mHeadView = View.inflate(context, R.layout.head_item, null);

        mIv_arrow = (ImageView) mHeadView.findViewById(R.id.iv_arrow);
        mProgressBar = (ProgressBar) mHeadView.findViewById(R.id.progress);
        mTextView = (TextView) mHeadView.findViewById(R.id.head_text);

        addHeaderView(mHeadView);


        mHeadView.measure(0,0);  //叫系统去给我测量
        mHeadViewHeight = mHeadView.getMeasuredHeight();
        mHeadView.setPadding(0,-mHeadViewHeight,0,0);           //设置负的Padding,顶上去

        pull_to_rel_animation = new RotateAnimation(0,180, Animation.RELATIVE_TO_SELF,.5f,Animation.RELATIVE_TO_SELF,
                .5f);
        pull_to_rel_animation.setDuration(300);
        pull_to_rel_animation.setFillAfter(true); //保存动画最后状态

        rel_to_pull_animation = new RotateAnimation(180,360, Animation.RELATIVE_TO_SELF,.5f,Animation.RELATIVE_TO_SELF,.5f);
        rel_to_pull_animation.setDuration(300);
        rel_to_pull_animation.setFillAfter(true); //保存动画最后状态
    }


    private int mDownY = 0;
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()){

            case MotionEvent.ACTION_DOWN:
                mDownY = (int) ev.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:

                int deleY = (int) (ev.getRawY() - mDownY);  //滑动距离

                mTopPadding = deleY - mHeadViewHeight;

                if (mTopPadding > - mHeadViewHeight && getFirstVisiblePosition() == 0){  //topPadding不能小于头视图的高度,防止滑不下来

                    mHeadView.setPadding(0, mTopPadding,0,0);

                    if (mTopPadding >= 0 && curStatus == PULL_TO_REFRESH){ //滑动状态下只允许由下拉进入松开
                        curStatus = RELEASE_TO_REFRESH;
                        RefreshStatusChanged();

                    }else if (mTopPadding < 0 && curStatus == RELEASE_TO_REFRESH){//同上理
                        curStatus = PULL_TO_REFRESH;
                        RefreshStatusChanged();
                    }


                    return true;  //拦截listview的滑动事件,仿止滑的距离不受控制
                }

                break;

            case MotionEvent.ACTION_UP:


                if (mTopPadding >= 0 && curStatus == RELEASE_TO_REFRESH){ //只能由释放刷新状态进入刷新状态

                    mHeadView.setPadding(0,0,0,0);
                    curStatus = NOW_TO_REFRESH;
                    RefreshStatusChanged();

                    if (mOnRefreshListener != null){
                        mOnRefreshListener.onRefresh();
                    }

                }else {

                    mHeadView.setPadding(0,-mHeadViewHeight,0,0);

                }


                break;
        }


        return super.onTouchEvent(ev);
    }


    private void RefreshStatusChanged(){

        switch (curStatus){

            case PULL_TO_REFRESH:
                mTextView.setText("下拉刷新");
                mIv_arrow.startAnimation(rel_to_pull_animation);

                break;

            case RELEASE_TO_REFRESH:

                mTextView.setText("释放立即刷新");
                mIv_arrow.startAnimation(pull_to_rel_animation);

                break;

            case NOW_TO_REFRESH:

                mIv_arrow.clearAnimation();        //清除动画,不然动画没完成不能隐藏
                mIv_arrow.setVisibility(INVISIBLE);
                mProgressBar.setVisibility(VISIBLE);
                mTextView.setText("正在刷新中....");

                break;

        }
    }


    /**刷新成功
     * @param handler
     */
    public void RefreshSuccess(Handler handler){
        mTextView.setText("刷新成功");
        mProgressBar.setVisibility(INVISIBLE);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mHeadView.setPadding(0,-mHeadViewHeight,0,0);
                mIv_arrow.setVisibility(VISIBLE);
                mTextView.setText("下拉刷新");
                curStatus = PULL_TO_REFRESH;
            }
        },1000);
    }

    /**
     * 刷新失败
     */
    public void RefreshError(){
        mProgressBar.setVisibility(INVISIBLE);
        mHeadView.setPadding(0,-mHeadViewHeight,0,0);
        mIv_arrow.setVisibility(VISIBLE);
        mTextView.setText("下拉刷新");
        curStatus = PULL_TO_REFRESH;
    }


    public interface OnRefreshListener{

        void onRefresh();
    }

    private OnRefreshListener mOnRefreshListener;
    public void setOnRefreshListener(OnRefreshListener onRefreshListener){
        mOnRefreshListener = onRefreshListener;
    }


}
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值