Android下拉刷新组件—SwipeRefreshLayout

来源:互联网 发布:照片打印软件哪个好 编辑:程序博客网 时间:2024/05/19 17:48

介绍

这里写图片描述
一个功能强大的自定义下拉刷新组件。
SwipeRefreshLayout也是一种下拉刷新控件,不同的它的刷新状态效果和传统的PuulToRefresh完全不一样。
SwipeRefreshLayout 是谷歌公司推出的用于下拉刷新的控件,SwipeRefreshLayout已经被放到了sdk中,在Version 19.1之后SwipeRefreshLayout 被放到support v4中。

方法API

setOnRefreshListener(OnRefreshListener):添加下拉刷新监听器
setRefreshing(boolean):显示或者隐藏刷新进度条
isRefreshing():检查是否处于刷新状态
setColorSchemeResources():设置进度条的颜色主题,最多设置四种,以前的setColorScheme()方法已经弃用了。

简单使用

1.SwipeRefreshLayout本身自带下拉刷新的效果,那么我们可以选择在RecyclerView布局外部嵌套一层SwipeRefreshLayout布局即可,具体布局文件如下:

<?xmlversionxmlversion="1.0" encoding="utf-8"?>  <LinearLayoutxmlns:androidLinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical"android:layout_width="match_parent"     android:layout_height="match_parent">      <includelayoutincludelayout="@layout/common_top_bar_layout"/>     <android.support.v4.widget.SwipeRefreshLayout         android:id="@+id/demo_swiperefreshlayout"         android:layout_width="fill_parent"         android:layout_height="fill_parent"          android:scrollbars="vertical"          >         <android.support.v7.widget.RecyclerView             android:id="@+id/demo_recycler"             android:layout_width="fill_parent"             android:layout_height="fill_parent"             ></android.support.v7.widget.RecyclerView>     </android.support.v4.widget.SwipeRefreshLayout>  </LinearLayout>  

2.接着在Activity中获取SwipeRefreshLayout控件并且设置OnRefreshListener监听器,同时实现里边的onRefresh()方法,在该方法中进行网络请求最新数据,然后刷新RecyclerView列表同时设置SwipeRefreshLayout的进度Bar的隐藏或者显示效果。具体代码如下:

demo_swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {              @Override              public void onRefresh() {                  Log.d("zttjiangqq","invoke onRefresh...");                  new Handler().postDelayed(newRunnable() {                      @Override                      public void run() {                          List<String> newDatas = new ArrayList<String>();                          for (int i = 0; i <5; i++) {                              int index = i + 1;                             newDatas.add("new item" + index);                          }                         adapter.addItem(newDatas);                         demo_swiperefreshlayout.setRefreshing(false);                         Toast.makeText(RecyclerRefreshActivity.this, "更新了五条数据...", Toast.LENGTH_SHORT).show();                      }                  }, 5000);              }          });  

SwipeRefreshLayout里面需要注意的Api:

       1setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener):设置手势滑动监听器。         2setProgressBackgroundColor(int colorRes):设置进度圈的背景色。         3setColorSchemeResources(int… colorResIds):设置进度动画的颜色。         4setRefreshing(Boolean refreshing):设置组件的刷洗状态。         5setSize(int size):设置进度圈的大小,只有两个值:DEFAULT、LARGE

案例使用

原理:是一个刷新布局,来自兼容包v4可以运行在低版本,控件如果想要支持下拉刷新,只要使用当前布局包裹
setColorSchemeColors:修改旋转颜色,可以添加多种颜色
setRefreshing: 是否显示loading状态
setOnRefreshListener:下拉刷新监听

例子:public class MainActivity extends AppCompatActivity {    private SwipeRefreshLayout swipeRefreshLayout;    protected void onCreate(Bundle savedInstanceState) {                 ·····   swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout);        //设置旋转的颜色效果        swipeRefreshLayout.setColorSchemeColors(Color.GREEN, Color.YELLOW, Color.RED);        //设置下拉刷新的监听器        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {            public void onRefresh() {                requestData();            }        });    }    private void requestData() {        new Handler().postDelayed(new Runnable() {//延时加载       public void run() {                String json = "{name:小米}";                TextView text = (TextView) findViewById(R.id.text);                text.setText(json);                swipeRefreshLayout.setRefreshing(false);//关闭显示            }        }, 2000);    }

加载更多——上滑加载数据
思路:1.滚动到底部 getItemCount()-2 ==bottomPosition
2.不处理滚动中
OnScrollListener监听滚动加载的监听器
int dy 滚动距离,向上滚动为正
layoutManager.findLastVisibleItemPosition获取处于底部数据的下标
dy>0与isLoading 都是用来控件灵敏度

public class HomeFragment extends Fragment {        private SwipeRefreshLayout swipeRefreshLayout;        private RecyclerView recyclerView;        private AppAdapter adapter;        @Override        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {                //有一个显示网络状态                //StateLayout stateLayout  = new StateLayout(container.getContext());            swipeRefreshLayout = new SwipeRefreshLayout(container.getContext());            //设置颜色            swipeRefreshLayout.setColorSchemeColors(Color.GREEN);            //设置下拉监听            swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {                @Override                public void onRefresh() {                    HttpConnect.get(ApiUrls.HOME+"?index=0", callback);                }            });            recyclerView = new RecyclerView(container.getContext());            //设置排列规则            recyclerView.setLayoutManager(new LinearLayoutManager(container.getContext()));            //预先设置了Noemal视图,但是normal视图没有内容    stateLayout.addNormalView(recyclerView);            swipeRefreshLayout.addView(recyclerView);            //发送请求给服务器            HttpConnect.get(ApiUrls.HOME+"?index=0",callback);            return swipeRefreshLayout;        }        DefaultCallBack callback = new DefaultCallBack() {            @Override            public void onStart(int what) {                swipeRefreshLayout.setRefreshing(true);            }            @Override            public void onFinish(int what) {                swipeRefreshLayout.setRefreshing(false);            }            //拿到数据            protected void createView(String json) {                HomeWebInfo info = new Gson().fromJson(json, HomeWebInfo.class);                //创建控件,设置适配器                adapter=new AppAdapter(info.list);                recyclerView.setAdapter(adapter);                //上滑加载数据                addLoadMoreList();            }        };        private void addLoadMoreList(){        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){            private boolean isLoading = false;           //int dy 上下滑动的距离 +数代表往上滑动            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                //判断 是否是排列布局                RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();                //判断是否是线性排列,并且是否滑动距离                if(layoutManager instanceof  LinearLayoutManager && dy>0 ){                    //当前是列表                    int total = adapter.getItemCount();                    int lastPosition = total-2;                    //获取rv 的bottom条目                    int currLastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();                    if(currLastPosition==lastPosition&&!isLoading){      }                    isLoading=true;                    Toast.makeText(MyApp.getContext(),"加载更多...",Toast.LENGTH_SHORT).show();                    new Handler().postDelayed(new Runnable() {                        @Override                        public void run() {                            Toast.makeText(MyApp.getContext(), "加载成功", Toast.LENGTH_SHORT).show();                            isLoading=false;                        }                    },5000);                }            }        });      }  }

开源框架RecyclerRefreshLayout

这里写图片描述
源码点击查看
RecyclerRefreshLayout 基于 {@link android.support.v4.widget.SwipeRefreshLayout} RecyclerRefreshLayout 可以被用于用户通过一个垂直滑动的手势刷新当前 view 内容的场景. 实例化这个视图的操作中总应该添加一个OnRefreshListener监听刷新动作完成后通知。 RecyclerRefreshLayout 每次手势操作完成后都会通知监听器(OnRefreshListener), 监听器负责决定何时来发起一个刷新操作。 如果监听器决定不触发刷新操作则需要调用 setRefreshing(false) 取消刷新的任何可视指示. 如果用户想要强制执行一次刷新动画, 则需要调用 setRefreshing(true). 如果想要禁用刷新动画,则可以调用 setEnabled(false)。

注意: RecyclerRefreshLayout 支持所有的View: ListView, GridView, ScrollView, FrameLayout, 甚至一个 TextView

在你的build.gradle文件里添加下面依赖:

  dependencies {        compile 'com.dinuscxj:recyclerrefreshlayout:2.0.3'    }

在xml中配置

<?xml version="1.0" encoding="utf-8"?><com.dinuscxj.refresh.RecyclerRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView     android:id="@+id/recycler_view"     android:layout_width="match_parent"     android:layout_height="match_parent" /></app.dinus.com.refresh.RecyclerRefreshLayout>

配置下面的属性(* 必选)

设置监听器监听手势操作是否触发刷新操作

RecyclerRefreshLayout.setOnRefreshListener(OnRefreshListener);

通知刷新状态已经改变. 当刷新由滑动手势触发不要调用它。

RecyclerRefreshLayout.setRefreshing(boolean);

配置下面的属性(可选)

设置将刷新动画从手势释放的位置移动到刷新位置的动画所需要的Interpolator

RecyclerRefreshLayout.setAnimateToRefreshInterpolator(Interpolator);

设置将刷新动画从手势释放的位置(或刷新位置)移动到起始位置的动画所需要的Interpolator

RecyclerRefreshLayout.setAnimateToStartInterpolator(Interpolator);

设置将刷新动画从手势释放的位置移动到刷新位置的动画所需要的时间

RecyclerRefreshLayout.setAnimateToRefreshDuration(int);

设置将刷新动画从手势释放的位置(或刷新位置)移动到起始位置的动画所需要的时间

RecyclerRefreshLayout.setAnimateToStartDuration(int);

设置RefreshView相对父组件的初始位置

RecyclerRefreshLayoutsetRefreshInitialOffset(float)

设置触发刷新需要滑动的最小距离

RecyclerRefreshLayout.setRefreshTargetOffset(float)

设置RefreshView的样式

RecyclerRefreshLayout.setRefreshStyle(@NonNull RefreshStyle) 

自定义
为 RecyclerRefreshLayout 自定义刷新动画 (需要实现接口 IRefreshStatus)

public interface IRefreshStatus {/*** 当手势操作完成且刷新动画滑动到起始位置*/void reset();/*** 正在刷新*/void refreshing();/*** 刷新动画被下拉到刷新位置*/void pullToRefresh();/*** 刷新动画被释放到刷新位置*/void releaseToRefresh();/*** @param pullDistance 刷新动画被拖动的距离* @param pullProgress 刷新动画被拖动的进度,当大于触发刷新的距离会大于1.0f*                     pullProgress = pullDistance / refreshTargetOffset*/void pullProgress(float pullDistance, float pullProgress);}

自定义网络加载图片控件—StateLayout:

需求:需要一个状态控件,1:自定义控件 继承ViewGroup/View 2:底层都使用Paint Canvas或者ImageView TextView

//步骤一 。完成构造函数public class StateLayout extends FrameLayout {    private View mLoading = null;    private View mError = null;    private View mEmpty = null;    private View mNormal = null;    public StateLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //步骤二 将布局打气进来并且作为一个元素添加当前的容器        View view = View.inflate(context, R.layout.state_layout, null);        mLoading = view.findViewById(R.id.loading);        mError = view.findViewById(R.id.error);        mEmpty = view.findViewById(R.id.nodata);//        mNormal = view.findViewById(R.id.normal);        this.addView(view);    }    public StateLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public StateLayout(Context context) {        this(context, null, 0);    }    //三。重置让所有的控件变成gone    private void reset() {        mLoading.setVisibility(View.GONE);        mError.setVisibility(View.GONE);        mEmpty.setVisibility(View.GONE);        if (mNormal != null) {            mNormal.setVisibility(View.GONE);        }    }    //显示加载中    public void showLoading() {        reset();        mLoading.setVisibility(View.VISIBLE);    }    //显示网络出错    public void showError() {        reset();        mError.setVisibility(View.VISIBLE);    }    //显示空    public void showEmpty() {        reset();        mEmpty.setVisibility(View.VISIBLE);    }    public void addNormalView(Object normalViewLayout) {        if (normalViewLayout instanceof Integer) {            mNormal = LayoutInflater.from(getContext()).inflate((Integer) normalViewLayout, this, false);        } else {            mNormal = (View) normalViewLayout;        }        this.addView(mNormal);//只有添加到当前布局的元素才可以显示    }    //显示正常    public void showNormal() {        reset();        mNormal.setVisibility(View.VISIBLE);    }}
0 0
原创粉丝点击