美文网首页Android收藏夹Android资源收录
Android开发总结(七)上拉刷新、下拉加载库的使用

Android开发总结(七)上拉刷新、下拉加载库的使用

作者: 程序猿男神 | 来源:发表于2017-07-11 13:04 被阅读1171次

    文/程序员男神

    前言

    本周被派遣到上海出差,去医院演示项目,收集收集医院的需求;大早上起得比平时早了那么一会,就感觉一天有点疲乏。晚上到了,突然精神来了,写篇文章压压惊。说实话,上拉刷新、下拉加载功能很常用,也很常见,但是需要自己开发时,却感觉那么多不知道选用哪个了?记录下来,让自己在刷新面前不在迷茫。


    aj

    概述

    先上效果图:上拉刷新,下拉加载的功能。

    效果图
    废话不多说,先给出两个项目的地址:
    下拉刷新
    https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
    上拉刷新、上拉加载更多
    https://github.com/captainbupt/android-Ultra-Pull-To-Refresh-With-Load-More/blob/master/README-cn.md

    实现步骤

    只讲使用方法,不扯淡,就是那么认真。

    1、参数说明

    • 在旧版本中,ptr_duration_to_close是指回到刷新状态的事件。另外ptr_duration_to_close_header代表回到开始状态(不可见)的事件。这两个属性有点类似,因此可能造成误解,特别是在添加了footer之后。所以,在新版本中,ptr_duration_to_close被删除,而使用ptr_duration_to_back_refresh作为替代。同时,也加入了ptr_duration_to_back_header和ptr_duration_to_back_footer来区分头部和脚部。
    • 新版本中,添加ptr_duration_to_close_either代表回到开始状态(不可见)的事件。
    • 针对ptr_resistance,也分别添加ptr_resistance_header和ptr_resistance_footer。

    2、添加的方法和类

    • setFooterView:对应于setHeaderView()。在set完footer后,你需要调用 addPtrUIHandler(),这和设置header的机制是一样的。
    • PtrHandler2:原有PtrHandler类的一个补充。当需要使用上拉加载更多的时候,你应该调用setPtrHandler(new PtrHandler2()),而不是setPtrHandler(new PtrHandler())。
    • PtrDefaultHandler2:实现了默认的 checkCanDoLoadMore() 逻辑,可以适用于大部分的View。机制和PtrDefaultHandler一致。
    • PtrClassicDefaultFooter:默认的footer,将默认header反转了过来。
    • setMode(Mode): Mode是本分支的一个新特性。通过调用setMode, 你可以任意的开启/关闭header或者footer。参数类型是一个枚举变量,可以通过以下方式调用:setMode(Mode.BOTH)。

    3、使用方法

    首先,在gradle中:

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

    下面是布局文件,activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <in.srain.cube.views.ptr.PtrClassicFrameLayout
            android:id="@+id/ptr_classic_frame_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#FFFFFF"
            app:ptr_duration_to_back_refresh="200"
            app:ptr_duration_to_close_footer="1000"
            app:ptr_duration_to_close_header="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">
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycle_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </in.srain.cube.views.ptr.PtrClassicFrameLayout>
    
    </LinearLayout>
    

    接下来就是我们的adapter的代码:

    package com.winning.health.rims.recoverydemo.adapter;
    
    import android.app.Activity;
    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.util.DisplayMetrics;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.winning.health.rims.recoverydemo.R;
    import com.winning.health.rims.recoverydemo.model.Project;
    import com.winning.health.rims.recoverydemo.view.SlidingButtonView;
    
    import java.util.List;
    
    /**
     * desc: adapter
     * author:djj on 2017/7/3 12:49
     * 简书:http://www.jianshu.com/u/dfbde65a03fc
     */
    public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.MyViewHolder> implements SlidingButtonView.IonSlidingButtonListener {
    
        private List<Project> data;
        private Context mContext;
        private SlidingButtonView mMenu = null;
    
        public RecycleAdapter(List<Project> data, Context mContext) {
            this.data = data;
            this.mContext = mContext;
        }
    
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
            MyViewHolder myViewHolder = new MyViewHolder(view);
            return myViewHolder;
        }
    
        @Override
        public void onBindViewHolder(final MyViewHolder holder, int position) {
    
            //将数据填充到具体的view中
            holder.itemTitle.setText(data.get(position).getItemTitle());
            holder.itemDuration.setText(data.get(position).getItemDuration() + "");
            holder.startTask.setText(data.get(position).getStartTask());
            holder.tvDelete.setText(data.get(position).getTvDelete());
    
            //设置内容布局的宽为屏幕宽度
            DisplayMetrics metrics = new DisplayMetrics();
            ((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int width = metrics.widthPixels;
            holder.layoutContent.getLayoutParams().width = width;
    
            // 如果设置了回调,则设置点击事件
            if (mIDeleteBtnClickListener != null) {
                holder.startTask.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        int n = holder.getLayoutPosition();
                        mIDeleteBtnClickListener.onStartItemClick(view, holder, n);
                    }
                });
                holder.layoutContent.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //判断侧滑是否打开
                        if (menuIsOpen()) {
                            closeMenu();
                        } else {
                            int n = holder.getLayoutPosition();
                            mIDeleteBtnClickListener.onDeleteBtnClick(view, holder, n);
                        }
                    }
                });
                holder.tvDelete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        int n = holder.getLayoutPosition();
                        mIDeleteBtnClickListener.onDeleteBtnClick(view, holder, n);
                    }
                });
            }
        }
    
        @Override
        public int getItemCount() {
            if (data != null) {
                return data.size();
            }
            return 0;
        }
    
        /**
         * 删除菜单打开信息接收
         */
        @Override
        public void onMenuIsOpen(View view) {
            mMenu = (SlidingButtonView) view;
        }
    
        /**
         * 滑动或者点击了Item监听
         *
         * @param slidingButtonView
         */
        @Override
        public void onDownOrMove(SlidingButtonView slidingButtonView) {
            if (menuIsOpen()) {
                if (mMenu != slidingButtonView) {
                    closeMenu();
                }
            }
        }
    
        /**
         * 关闭菜单
         */
        public void closeMenu() {
            mMenu.closeMenu();
            mMenu = null;
        }
    
        /**
         * 判断是否有菜单打开
         */
        public Boolean menuIsOpen() {
            if (mMenu != null) {
                return true;
            }
            return false;
        }
    
    
        /**
         * 定义接口回调
         */
        private IonSlidingViewClickListener mIDeleteBtnClickListener;
    
        public void setOnSlidingViewClickListener(IonSlidingViewClickListener listener) {
            this.mIDeleteBtnClickListener = listener;
        }
    
        public interface IonSlidingViewClickListener {
            void onStartItemClick(View view, MyViewHolder holder, int position);
    
            void onDeleteBtnClick(View view, MyViewHolder holder, int position);
        }
    
        public class MyViewHolder extends RecyclerView.ViewHolder {
    
            public TextView itemTitle;
            public TextView itemDuration;
            public TextView startTask;
            public TextView tvDelete;
            public ViewGroup layoutContent;
    
            public MyViewHolder(View itemView) {
                super(itemView);
                itemTitle = itemView.findViewById(R.id.item_title);
                itemDuration = itemView.findViewById(R.id.item_duration);
                startTask = itemView.findViewById(R.id.start_task);
                tvDelete = itemView.findViewById(R.id.tv_delete);
                layoutContent = itemView.findViewById(R.id.layout_content);
                ((SlidingButtonView) itemView).setSlidingButtonListener(RecycleAdapter.this);
    
            }
        }
    }
    

    接下来贴出item的xml代码item_list.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <com.winning.health.rims.recoverydemo.view.SlidingButtonView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="@android:color/white">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <RelativeLayout
                android:id="@+id/layout_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="12dp"
                    android:layout_marginTop="12dp"
                    android:background="@color/white"
                    android:descendantFocusability="blocksDescendants"
                    android:gravity="center_vertical"
                    android:orientation="horizontal">
    
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center_vertical"
                        android:orientation="vertical">
    
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:gravity="center_vertical"
                            android:orientation="horizontal">
    
                            <TextView
                                android:id="@+id/item_title"
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                android:layout_marginLeft="10dp"
                                android:layout_weight="1"
                                android:text="推拿"
                                android:textColor="@color/textColor"
                                android:textSize="14sp" />
    
                            <TextView
                                android:id="@+id/item_duration"
                                style="@style/itemTextStyle"
                                android:layout_width="0dp"
                                android:layout_marginLeft="30dp"
                                android:layout_weight="0.5"
                                android:text="00:45:00" />
                        </LinearLayout>
    
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:gravity="center_vertical"
                            android:orientation="horizontal">
    
                            <TextView
                                android:id="@+id/item_patient_name"
                                style="@style/itemTextStyle"
                                android:layout_width="0dp"
                                android:layout_marginLeft="10dp"
                                android:layout_weight="0.5"
                                android:text="李青" />
    
    
                            <TextView
                                android:id="@+id/item_patient_age"
                                style="@style/itemTextStyle"
                                android:layout_width="wrap_content"
                                android:text="26岁" />
    
                            <TextView
                                android:id="@+id/item_patient_sex"
                                style="@style/itemTextStyle"
                                android:layout_width="0dp"
                                android:layout_weight="0.5"
                                android:text="男" />
    
                            <TextView
                                android:id="@+id/item_patient_num"
                                style="@style/itemTextStyle"
                                android:layout_width="0dp"
                                android:layout_weight="0.5"
                                android:text="20170511" />
                        </LinearLayout>
    
                    </LinearLayout>
    
                    <TextView
                        android:id="@+id/start_task"
                        android:layout_width="45dp"
                        android:layout_height="45dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginRight="10dp"
                        android:background="@drawable/button_back"
                        android:focusable="true"
                        android:focusableInTouchMode="false"
                        android:gravity="center"
                        android:text="开始"
                        android:textSize="12sp" />
                </LinearLayout>
            </RelativeLayout>
    
            <TextView
                android:id="@+id/tv_delete"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:layout_toEndOf="@+id/layout_content"
                android:layout_toRightOf="@+id/layout_content"
                android:background="@color/red"
                android:gravity="center"
                android:text="取 消"
                android:textColor="@color/white" />
        </RelativeLayout>
    
    </com.winning.health.rims.recoverydemo.view.SlidingButtonView>
    

    实体类Project的代码,set、get方法自己添加:

    package com.winning.health.rims.recoverydemo.model;
    
    /**
     * desc: 治疗项目实体类
     * <p>
     * author:djj
     * <p>
     * date: 2017/7/3 13:12
     * <p>
     * blog:http://www.jianshu.com/u/dfbde65a03fc
     */
    
    public class Project {
    
        private String itemTitle;
        private int itemDuration;
        private String startTask;
        private String tvDelete;
    }
    

    由于这是在有滑动删除的Recycleview代码基础上添加的刷新,所以也把滑动的自定义贴出来:

    package com.winning.health.rims.recoverydemo.view;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.HorizontalScrollView;
    import android.widget.TextView;
    
    import com.winning.health.rims.recoverydemo.R;
    
    /**
     * desc: 侧滑按钮自定义
     * author: dj
     * date: 2017/3/10 10:01
     */
    
    public class SlidingButtonView extends HorizontalScrollView {
    
        private TextView mTextView_Delete;
        private int mScrollWidth;
        private Boolean isOpen = false;
        private Boolean once = false;
    
        public SlidingButtonView(Context context) {
            this(context, null);
        }
    
        public SlidingButtonView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SlidingButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.setOverScrollMode(OVER_SCROLL_NEVER);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if (!once) {
                mTextView_Delete = (TextView) findViewById(R.id.tv_delete);
                once = true;
            }
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
            if (changed) {
                this.scrollTo(0, 0);
                //获取水平滚动条可以滑动的范围,即右侧按钮的宽度
                mScrollWidth = mTextView_Delete.getWidth();
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    mIonSlidingButtonListener.onDownOrMove(this);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    changeScrollx();
                    return true;
                default:
                    break;
            }
            return super.onTouchEvent(ev);
        }
    
        /**
         * 按滚动条被拖动距离判断关闭或打开菜单
         */
        public void changeScrollx() {
            if (getScrollX() >= (mScrollWidth / 2)) {
                this.smoothScrollTo(mScrollWidth, 0);
                isOpen = true;
                mIonSlidingButtonListener.onMenuIsOpen(this);
            } else {
                this.smoothScrollTo(0, 0);
                isOpen = false;
            }
        }
    
        /**
         * 打开菜单
         */
        public void openMenu() {
            if (isOpen) {
                return;
            }
            this.smoothScrollTo(mScrollWidth, 0);
            isOpen = true;
            mIonSlidingButtonListener.onMenuIsOpen(this);
        }
    
        /**
         * 关闭菜单
         */
        public void closeMenu() {
            if (!isOpen) {
                return;
            }
            this.smoothScrollTo(0, 0);
            isOpen = false;
        }
    
        private IonSlidingButtonListener mIonSlidingButtonListener;
    
        public void setSlidingButtonListener(IonSlidingButtonListener listener) {
            this.mIonSlidingButtonListener = listener;
        }
    
        public interface IonSlidingButtonListener {
            void onMenuIsOpen(View view);
    
            void onDownOrMove(SlidingButtonView slidingButtonView);
        }
    }
    

    最后就是我们的activity的代码,Mainactivity.java:

    package com.winning.health.rims.recoverydemo.activity;
    
    import android.graphics.Color;
    import android.os.Bundle;
    import android.os.CountDownTimer;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.DividerItemDecoration;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    import android.widget.Toast;
    
    import com.winning.health.rims.recoverydemo.R;
    import com.winning.health.rims.recoverydemo.adapter.RecycleAdapter;
    import com.winning.health.rims.recoverydemo.model.Project;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import in.srain.cube.views.ptr.PtrClassicDefaultFooter;
    import in.srain.cube.views.ptr.PtrClassicDefaultHeader;
    import in.srain.cube.views.ptr.PtrClassicFrameLayout;
    import in.srain.cube.views.ptr.PtrDefaultHandler2;
    import in.srain.cube.views.ptr.PtrFrameLayout;
    import in.srain.cube.views.ptr.PtrHandler2;
    import in.srain.cube.views.ptr.util.PtrLocalDisplay;
    
    public class MainActivity extends AppCompatActivity {
    
        private RecyclerView mRecyclerView;
        private RecycleAdapter mAdapter;
        private RecyclerView.LayoutManager mLayoutManager;
        private List<Project> projectList;
        private PtrClassicFrameLayout ptrClassicLayout;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initDate();
            initView();
    
    
        }
    
        //初始化数据
        private void initDate() {
            projectList = new ArrayList<Project>();
            for (int i = 0; i < 20; i++) {
                Project project = new Project();
                project.setItemTitle("微波治疗");
                project.setItemDuration(10);
                project.setStartTask("开始");
                project.setTvDelete("取消");
                projectList.add(project);
            }
        }
    
        //初始化控件
        private void initView() {
            mRecyclerView = (RecyclerView) findViewById(R.id.recycle_view);
            ptrClassicLayout = (PtrClassicFrameLayout) findViewById(R.id.ptr_classic_frame_layout);
            mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);
            mAdapter = new RecycleAdapter(projectList, MainActivity.this);
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.setOnSlidingViewClickListener(new RecycleAdapter.IonSlidingViewClickListener() {
                @Override
                public void onStartItemClick(View view, final RecycleAdapter.MyViewHolder holder, int position) {
                    //判断状态调收费接口
                    CountDownTimer timer = new CountDownTimer((20 * 1000), 1000) {
                        @Override
                        public void onTick(long l) {
                            holder.itemDuration.setText(l / 1000 + "");
                            holder.startTask.setBackgroundResource(R.drawable.button_load_back);
                            holder.startTask.setTextColor(Color.parseColor("#0BC0BA"));
                            holder.startTask.setText("进行");
    
                        }
    
                        @Override
                        public void onFinish() {
                            holder.itemDuration.setText("00:00:00");
                            holder.startTask.setBackgroundResource(R.drawable.button_no_back);
                            holder.startTask.setText("完成");
                        }
                    };
                    timer.start();
                }
    
                @Override
                public void onDeleteBtnClick(View view, RecycleAdapter.MyViewHolder holder, int position) {
                    Toast.makeText(MainActivity.this, "onDeleteBtnClick", Toast.LENGTH_SHORT).show();
    
                }
            });
            /**
             * 经典 风格的头部实现
             */
            final PtrClassicDefaultHeader header = new PtrClassicDefaultHeader(this);
            header.setPadding(0, PtrLocalDisplay.dp2px(15), 0, 0);
    
            PtrClassicDefaultFooter footer = new PtrClassicDefaultFooter(this);
            footer.setPadding(0, 0, 0, PtrLocalDisplay.dp2px(15));
    
            ptrClassicLayout.setHeaderView(header);
            ptrClassicLayout.addPtrUIHandler(header);
    
            ptrClassicLayout.setFooterView(footer);
            ptrClassicLayout.addPtrUIHandler(footer);
            //mPtrFrame.setKeepHeaderWhenRefresh(true);//刷新时保持头部的显示,默认为true
            //mPtrFrame.disableWhenHorizontalMove(true);//如果是ViewPager,设置为true,会解决ViewPager滑动冲突问题。
            ptrClassicLayout.setPtrHandler(new PtrHandler2() {
                @Override
                public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {
                    // 默认实现,根据实际情况做改动
                    return PtrDefaultHandler2.checkContentCanBePulledUp(frame, content, footer);
                }
    
                /**
                 * 加载更多的回调
                 * @param frame
                 */
                @Override
                public void onLoadMoreBegin(PtrFrameLayout frame) {
                    frame.postDelayed(new Runnable() {
                        @Override
                        public void run() {
    
                            ptrClassicLayout.refreshComplete();
                        }
                    }, 2000);
                }
    
                @Override
                public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                    // 默认实现,根据实际情况做改动
                    return PtrDefaultHandler2.checkContentCanBePulledDown(frame, content, header);
                }
    
                /**
                 * 下拉刷新的回调
                 * @param frame
                 */
                @Override
                public void onRefreshBegin(PtrFrameLayout frame) {
                    frame.postDelayed(new Runnable() {
                        @Override
                        public void run() {
    
                            ptrClassicLayout.refreshComplete();
                        }
                    }, 1000);
                }
            });
    
        }
    }
    

    这些都是我真实项目的demo,里面不止上拉刷新、下拉加载的功能,在以前功能基础上添加到,把这分享出来和大家交流,希望可以更好的进步。
    最后贴上源码地址:https://github.com/hellodonj/PtrClassicDemo.git

    总结:
    学习需要坚持。不要怂,就是干。

    相关文章

      网友评论

        本文标题:Android开发总结(七)上拉刷新、下拉加载库的使用

        本文链接:https://www.haomeiwen.com/subject/cmssxxtx.html