SwipeRefreshLayout的升级版RefreshLayout

来源:互联网 发布:摩托罗拉v8和v9 java 编辑:程序博客网 时间:2024/05/17 03:59

随着下拉刷新 加载更多的功能的广泛应用,谷歌也推出了自己的下拉刷新下组件SwipeRefreshLayout,首先先对这个组件进行一些简单的介绍:
从谷歌官网看来 这个控件继承自ViewGroup 可以理解成就是一个View控件
对于这个控件的具体描述如下:
The SwipeRefreshLayout should be used whenever the user can refresh the contents of a view via a vertical swipe gesture. The activity that instantiates this view should add an OnRefreshListener to be notified whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout will notify the listener each and every time the gesture is completed again; the listener is responsible for correctly determining when to actually initiate a refresh of its content. If the listener determines there should not be a refresh, it must call setRefreshing(false) to cancel any visual indication of a refresh. If an activity wishes to show just the progress animation, it should call setRefreshing(true). To disable the gesture and progress animation, call setEnabled(false) on the view.

This layout should be made the parent of the view that will be refreshed as a result of the gesture and can only support one direct child. This view will also be made the target of the gesture and will be forced to match both the width and the height supplied in this layout. The SwipeRefreshLayout does not provide accessibility events; instead, a menu item must be provided to allow refresh of the content wherever this gesture is used.

简单点儿来说就是:就是这控件是用来用户是否刷新内容时候用的控件,通过接口监听来手势滑动的,通过这个监听器来负责决定什么时候开始正确刷新内容。如果,监听决定不应该有一个刷新,那么必须设置setRefreshing(false)方法去取消视觉显示刷新效果。如果需要进一步展示动画,则通过setRefreshing(true)这个方法。如果需要禁用手势和动画效果则通过设置setEnabled(false)这个方法。还有就是这个布局控件只支持包含一个子控件。
总结如下几点:
1.它内部可以包裹listview,gridview等具有垂直方向的手势控件
2.它可以设置刷新监听

下面通过代码来实现以下SwipeRefreshLayout 所能实现的下拉刷新的效果:
在最新的v4包里已经集成了SwipeRefreshLayout ,我们直接在布局文件中拿来用即可。
介绍常用的方法:

//设置刷新动画的颜色        swipe_container.setColorSchemeResources(R.color.colorPrimary, R.color.green0, R.color.toasterro);//设置滚动条背景颜色    swipe_container.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.colorAccent));// 设置触发的距离swipe_container.setDistanceToTriggerSync(1000);     //结束刷新 更改动画swipe_container.setRefreshing(false);

实现效果:
这里写图片描述
完整代码如下:
1.布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">   <android.support.v4.widget.SwipeRefreshLayout       android:id="@+id/swipe_container"       android:layout_width="match_parent"       android:layout_height="match_parent">       <ListView           android:id="@+id/lv"           android:layout_width="match_parent"           android:layout_height="match_parent"           android:divider="@null"           android:scrollbars="none" ></ListView>   </android.support.v4.widget.SwipeRefreshLayout></RelativeLayout>

2.代码:

这里写代码片package com.example.administrator.refreshlayoutdemo;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.support.v4.widget.SwipeRefreshLayout;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;/** * @author yangzc * @des */public class MainActivity extends Activity implements SwipeRefreshLayout.OnRefreshListener {    private ListView lv;    private SwipeRefreshLayout swipe_container;    private ArrayList<String> list;    private ArrayAdapter<String> stringArrayAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initViews();        initDatas();    }    private void initViews() {        lv = (ListView) findViewById(R.id.lv);        swipe_container = (SwipeRefreshLayout) findViewById(R.id.swipe_container);    }    private void initDatas() {        swipe_container.setOnRefreshListener(this);        list = new ArrayList<String>();        for (int i = 0;i<20;i++){            list.add(i+"个数据");        }        stringArrayAdapter = new ArrayAdapter<String>(this, R.layout.lv_item, list);        lv.setAdapter(stringArrayAdapter);        //设置刷新动画的颜色        swipe_container.setColorSchemeColors(R.color.colorPrimary,R.color.green0,R.color.toasterro);    }    /**     * 设置刷新监听     */    @Override    public void onRefresh() {        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                list.add(0, "下拉刷新的数据");                stringArrayAdapter.notifyDataSetChanged();                //结束刷新 更改动画                swipe_container.setRefreshing(false);            }        },2000);    }}

到目前为止,我们通过SwipeRefreshLayout的下拉刷新的功能就实现了。这个时候,我们不禁就要有个疑问了,往往在我们的应用当中,是下拉刷新和上拉加载是同时出现的,但是这里并没有实现上拉加载的功能,就需要我们自己实现一下,以下就是今天的重点了升级版的SwipeRefreshLayout——RefreshLayout
先看一下实现的效果:
这里写图片描述
这里面实现加载更多的功能就是我们对于SwipeRefreshLayout的进一步优化:
代码如下:
RefreshLayout继承自SwipeRefreshLayout

package com.example.administrator.refreshlayoutdemo;import android.content.Context;import android.support.v4.widget.SwipeRefreshLayout;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.AbsListView;import android.widget.ListView;/** * 继承自SwipeRefreshLayout,从而实现滑动到底部时上拉加载更多的功能. * */public class RefreshLayout extends SwipeRefreshLayout implements AbsListView.OnScrollListener {    /**     * 滑动到最下面时的上拉操作     */    private int mTouchSlop;    /**     * listview实例     */    private ListView mListView;    /**     * 上拉监听器, 到了最底部的上拉加载操作     */    private OnLoadListener mOnLoadListener;    /**     * ListView的加载中footer     */    private View mListViewFooter;    /**     * 按下时的y坐标     */    private int mYDown;    /**     * 抬起时的y坐标, 与mYDown一起用于滑动到底部时判断是上拉还是下拉     */    private int mLastY;    /**     * 是否在加载中 ( 上拉加载更多 )     */    private boolean isLoading = false;    private int mYUp;    /**     * @param context     */    public RefreshLayout(Context context) {        this(context, null);    }    public RefreshLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();        mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer, null,                false);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        // 初始化ListView对象        if (mListView == null) {            getListView();        }    }    /**     * 获取ListView对象     */    private void getListView() {        int childs = getChildCount();        if (childs > 0) {            View childView = getChildAt(0);            if (childView instanceof ListView) {                mListView = (ListView) childView;                // 设置滚动监听器给ListView, 使得滚动的情况下也可以自动加载                mListView.setOnScrollListener(this);            }        }    }    /*     * (non-Javadoc)     * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)     */    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        final int action = event.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN:                // 按下                mYDown = (int) event.getRawY();                break;            case MotionEvent.ACTION_MOVE:                // 移动                mLastY = (int) event.getRawY();                break;            case MotionEvent.ACTION_UP:                mYUp = (int) event.getRawY();                // 抬起                if (canLoad()) {                    loadData();                }                break;            default:                break;        }        return super.dispatchTouchEvent(event);    }    /**     * 是否可以加载更多, 条件是到了最底部, listview不在加载中, 且为上拉操作.     *     * @return     */    private boolean canLoad() {        return isBottom() && !isLoading && isPullUp();    }    /**     * 判断是否到了最底部     */    private boolean isBottom() {        if (mListView != null && mListView.getAdapter() != null) {            return mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1);        }        return false;    }    /**     * 是否是上拉操作     *     * @return     */    private boolean isPullUp() {        return (mYDown - mYUp) >= 600;    }    /**     * 如果到了最底部,而且是上拉操作.那么执行onLoad方法     */    private void loadData() {        if (mOnLoadListener != null) {            // 设置状态            setLoading(true);            //            mOnLoadListener.onLoad();        }    }    /**     * @param loading     */    public void setLoading(boolean loading) {        isLoading = loading;        if (isLoading) {            if (mListView.getFooterViewsCount() != 0){                mListViewFooter.setVisibility(View.VISIBLE);            }else{                mListView.addFooterView(mListViewFooter);            }        } else {            mListViewFooter.setVisibility(View.GONE);            //不去移除掉这个footerview 防止跳跃 然后上边判断是否存在//            mListView.removeFooterView(mListViewFooter);            mYDown = 0;            mLastY = 0;        }    }    /**     * @param loadListener     */    public void setOnLoadListener(OnLoadListener loadListener) {        mOnLoadListener = loadListener;    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,                         int totalItemCount) {        // 滚动时到了最底部也可以加载更多        if (canLoad()) {            loadData();        }    }    /**     * 加载更多的监听器     *     * @author mrsimple     */    public static interface OnLoadListener {        public void onLoad();    }}

需要增加一个脚的布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:gravity="center"    android:padding="5dp">    <ProgressBar        android:id="@+id/load_more_progressBar"        style="?android:attr/progressBarStyleSmall"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/loadMoreButton"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toRightOf="@+id/load_more_progressBar"        android:includeFontPadding="false"        android:paddingLeft="5dp"        android:text="加载更多"        android:textColor="#9b9ea1"        android:textSize="13sp" /></RelativeLayout>

在布局文件当中需要:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">   <com.example.administrator.refreshlayoutdemo.RefreshLayout       android:id="@+id/swipe_container"       android:layout_width="match_parent"       android:layout_height="match_parent">       <ListView           android:id="@+id/lv"           android:layout_width="match_parent"           android:layout_height="match_parent"           android:divider="@null"           android:scrollbars="none" ></ListView>   </com.example.administrator.refreshlayoutdemo.RefreshLayout></RelativeLayout>

在之前代码基础之上增加加载更多的监听以及操作:

package com.example.administrator.refreshlayoutdemo;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.support.v4.widget.SwipeRefreshLayout;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;/** * @author yangzc * @des */public class MainActivity extends Activity implements SwipeRefreshLayout.OnRefreshListener, RefreshLayout.OnLoadListener {    private ListView lv;    private RefreshLayout swipe_container;    private ArrayList<String> list;    private ArrayAdapter<String> stringArrayAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initViews();        initDatas();    }    private void initViews() {        lv = (ListView) findViewById(R.id.lv);        swipe_container = (RefreshLayout) findViewById(R.id.swipe_container);    }    private void initDatas() {        swipe_container.setOnRefreshListener(this);        swipe_container.setOnLoadListener(this);        list = new ArrayList<String>();        for (int i = 0; i < 20; i++) {            list.add(i + "个数据");        }        stringArrayAdapter = new ArrayAdapter<String>(this, R.layout.lv_item, list);        lv.setAdapter(stringArrayAdapter);        //设置刷新动画的颜色        swipe_container.setColorSchemeResources(R.color.colorPrimary, R.color.green0, R.color.toasterro);    }    /**     * 设置刷新监听     */    @Override    public void onRefresh() {        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                list.add(0, "下拉刷新的数据");                stringArrayAdapter.notifyDataSetChanged();                //结束刷新 更改动画                swipe_container.setRefreshing(false);            }        }, 5000);    }    /**     * 加载更多的方法     */    @Override    public void onLoad() {        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                list.add(list.size(), "加载更多的数据");                stringArrayAdapter.notifyDataSetChanged();                //结束动画                swipe_container.setLoading(false);            }        }, 2000);    }}

以上就是完整的下拉刷新,上拉加载更多的全部内容

1 0