热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

通过SwipeRefreshLayout实现ListView的上拉加载下拉刷新

上拉刷新下拉加载相信是在日常的开发中使用的最频繁的一个组件了,大量数据的展示一定会使用到分页的功能以提升用户体验,目前可以看到的市面上的应用的下拉刷新也都是配合的SwipeRefreshLayo

上拉刷新下拉加载相信是在日常的开发中使用的最频繁的一个组件了,大量数据的展示一定会使用到分页的功能以提升用户体验,目前可以看到的市面上的应用的下拉刷新也都是配合的SwipeRefreshLayout来实现的,看起来比较美观,相比自定义的下拉刷新的动画效果,这个就显得比较简洁大方了。

下面看一下运行效果:
这里写图片描述

由于ListView没有提供默认的分页加载的功能,因此这里就需要我们自定了,实现起来也是比较简单的,大致的思路就是:给ListView添加一个FootView用来显示正在加载的等待动画,以及滑动到listview最底部的Item的监听,然后通过回调将事件的处理交给外部进行。

LoadListView.Java

/** * Created by 春水碧于天 on 2017/1/29. */

public class LoadListView extends ListView implements AbsListView.OnScrollListener {


    private int mFootViewHeight;
    private View mFootView;
    private int LOADSTATE = 0; //加载的状态

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

        InitFootView(context);
        setOnScrollListener(this);
    }

    public LoadListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //初始化脚布局并添加到当前的ListView
        InitFootView(context);
        setOnScrollListener(this);
    }

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


    private void InitFootView(Context context) {

        mFootView = View.inflate(context, R.layout.foot_load_item, null);

        mFootView.measure(0, 0); //测量

        mFootViewHeight = mFootView.getMeasuredWidth();

        addFooterView(mFootView);

    }

    //加载完成调用隐藏脚布局,并把mLoadState的状态设置为0,表示未刷新状态
    public void setLoadComplete() {

        LOADSTATE = 0;

        //加载完成后隐藏脚布局
        mFootView.setPadding(0, -mFootViewHeight, 0, 0);

    }

    //滑动状态改变的监听
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }



    /** * 滑动时一直调用 * @param view * @param firstVisibleItem 当前能看见的第一条item的Id * @param visibleItemCount 当前能看见的item的总数 * @param totalItemCount 所有的item */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {


        Log.i("wk","firstVisibleItem: "+firstVisibleItem+"visibleItemCount: "+visibleItemCount+"totalItemCount: "+totalItemCount);


        //判断是否滑动到当前listview的最后一个条目
        if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {

            if (LOADSTATE == 0) {
                //取消隐藏
                mFootView.setPadding(0, 0, 0, 0);

                onLoadListener.onLoading();

                LOADSTATE = 1; //设置状态为加载中,放置多次调用onLoading

            }

        }

    }

    //加载更多的回调接口
    private OnLoadListener onLoadListener;

    public void setOnLoadlistener(OnLoadListener onLoadListener) {

        this.OnLoadListener= onLoadListener;

    }

    public interface OnLoadListener {

        void onLoading();

    }
}

这里记录一下OnScrollListener中的两个回调方法的作用:

1.onScrollStateChanged

      //滑动状态改变的监听
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

        switch (scrollState) {

            //根据手指离开后的惯性滑动时调用
            case OnScrollListener.SCROLL_STATE_FLING:

               Log.i("wk","惯性滑动");

                break;

            //滚动停止时调用
            case OnScrollListener.SCROLL_STATE_IDLE:
                Log.i("wk","滚动停止");

                break;

            //正在滚动时调用
            case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:

                Log.i("wk","正在滚动");

                break;


        }


    }

这个方法根据第二个参数 scrollState 来决定回调的次数

2.onScroll

    /** * 滑动时一直调用 * * @param view * @param firstVisibleItem 当前能看见的第一条item的Id * @param visibleItemCount 当前能看见的item的总数 * @param totalItemCount 所有的item */
@Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

它在ListView滑动时一直调用,通过onScroll中的三个参数,非常精确的描述了ListView的当前状态

  • firstVisibleItem 当前能看见的第一条item的Position

  • visibleItemCount 当前能看见的item的总数(包括没有完全显示的条目)

  • totalItemCount 所有的item

判断显示到了最后一行:

        if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) { }

判断ListView滑动的方向:

    private int lastVisibleItem = 0;
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        Log.i("wk","lastVisibleItem=> "+lastVisibleItem+"firstVisibleItem=> "+firstVisibleItem);

        if(lastVisibleItem>firstVisibleItem){

            Log.i("wk","下滑");

        }else if (lastVisibleItem"wk","上滑");


        }

        lastVisibleItem = firstVisibleItem;

foot_load_item.Java


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal">

    <ProgressBar  android:layout_margin="10dp" android:layout_width="50dp" android:layout_height="50dp" />
<TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在加载中……" android:layout_margin="10dp" android:textSize="20dp" android:layout_gravity="center" />


LinearLayout>

这样一个支持上拉加载更多的ListView就实现了。

下面通过配合SwipeRefreshLayout来实现下拉刷新:

activity_main.xml

"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_hljs-string">"match_parent"
    android:layout_hljs-string">"match_parent"
    android:orientation="vertical"
    tools:cOntext="com.example.studyslide.MainActivity">
.support.v4.widget.SwipeRefreshLayout

    android:id="@+id/swipeRefreshLayout"
    android:layout_hljs-string">"match_parent"
    android:layout_hljs-string">"match_parent">
    <com.example.studyslide.LoadListView
        android:id="@+id/listView"
        android:layout_hljs-string">"match_parent"
        android:layout_hljs-string">"match_parent">


    com.example.studyslide.LoadListView>

.support.v4.widget.SwipeRefreshLayout>

MainActivity.Java

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private LoadListView mListView;
    private ArrayList mDatas;
    private SwipeRefreshLayout swipeRefreshLayout;
    private Handler mHandler;

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


        InitData();
        InitUI();

        //设置加载显示的颜色,可以设置显示多种颜色
        swipeRefreshLayout.setColorSchemeColors(Color.BLUE, Color.RED, Color.GREEN, Color.GRAY);

        //设置swipeRefreshLayout的背景颜色
        //swipeRefreshLayout.setBackgroundColor(Color.CYAN);

        //设置显示的大小
        swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE);
/* //设置手指下拉多少出现刷新 swipeRefreshLayout.setDistanceToTriggerSync(200); //设置刷新出现的位置 swipeRefreshLayout.setProgressViewEndTarget(false,200);*/

        //设置刷新的监听
        swipeRefreshLayout.setOnRefreshListener(this);

        final myAdapter myAdapter = new myAdapter();

        /** * 模拟网络数据加载 */
        mHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);

                int tag = msg.what;

                switch (tag) {
                    //刷新
                    case 0:
                        for (int i = 0; i <10; i++) {

                            mDatas.add(0, "刷新出的数据" + i);

                        }

                        swipeRefreshLayout.setRefreshing(false);
                        myAdapter.notifyDataSetChanged();

                        break;

                    //加载更多
                    case 1:

                        for (int i = 0; i <10; i++) {

                            mDatas.add("加载出的数据" + i);

                        }

                        mListView.setLoadComplete();
                        myAdapter.notifyDataSetChanged();
                        break;


                }


            }
        };


        mListView.setAdapter(myAdapter);


        mListView.setOnLoadlistener(new LoadListView.OnLoadListener() {
            @Override
            public void onLoading() {

                Toast.makeText(MainActivity.this, "加载更多", Toast.LENGTH_SHORT).show();


                //模拟网络加载数据延迟
                new Thread(new Runnable() {
                    @Override
                    public void run() {


                        try {
                            Thread.sleep(2000);

                            mHandler.sendEmptyMessage(1);

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } finally {
                        }


                    }
                }).start();


            }
        });


    }

    private void InitUI() {

        mListView = (LoadListView) findViewById(R.id.listView);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);

    }

    private void InitData() {

        mDatas = new ArrayList();

        for (int i = 0; i <40; i++) {
            mDatas.add("这是" + i + "条数据");

        }


    }


    @Override
    public void onRefresh() {

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Thread.sleep(2000);
                    mHandler.sendEmptyMessage(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                }


            }
        }).start();


    }

    //ListView的适配器
    class myAdapter extends BaseAdapter {


        @Override
        public int getCount() {
            return mDatas.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

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


            ViewHolder viewHolder = null;

            if (cOnvertView== null) {

                viewHolder = new ViewHolder();
                cOnvertView= View.inflate(MainActivity.this, R.layout.item_listview, null);
                viewHolder.tv = (TextView) convertView.findViewById(R.id.textView);
                convertView.setTag(viewHolder);

            } else {

                viewHolder = (ViewHolder) convertView.getTag();

            }


            viewHolder.tv.setText(mDatas.get(position));


            return convertView;
        }

        final class ViewHolder {

            public TextView tv;


        }

    }


}

下面记录一下SwipeRefreshLayout的使用:

常用的方法:

  • setOnRefreshListener(this):添加一个刷新的监听

  • setRefreshing(): 显示或隐藏刷新进度条

  • isRefreshing(): 检查当前是否处于刷新状态

  • setColorScheme(): 设置进度条的颜色主题,最多能设置四种

  • swipeRefreshLayout.setBackgroundColor():设置SwipeRefreshLayout 的背景色

  • swipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE):设置刷新控件显示大小,默认为small

  • swipeRefreshLayout.setDistanceToTriggerSync(200):设置手指下拉多少出现刷新

  • swipeRefreshLayout.setProgressViewEndTarget(false,200):设置刷新出现的位置

这样一个可以上拉加载下拉刷新的ListView就完成了,呵呵,比较朴素的效果实现。


推荐阅读
author-avatar
游山玩水人生
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有