继承SwipeRefreshLayout实现上拉加载更多功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sumsear/article/details/53674063

Android 的SwipeRefreshLayout是一个比较好的下拉刷新控件,现在已经有越来越多的企业开始使用这个控件了。但是遗憾的是这个控件并没有上拉加载更多的功能,所以自己抽空,根据网上已有的例子,自己写了一个。

首先必须要做的是创建一个类继承SwipeRefreshLayout,这里我把它命名为:XZHRefreshLayout

/**
 * TODO:Created by XuZhenhao on 2016/12/6.
 */

public class XZHRefreshLayout extends SwipeRefreshLayout {


    private boolean isLoading = false;

    private ListView mListView;

    private View mListFooter;

    private OnLoadListener mLoadListener;


    public XZHRefreshLayout(Context context) {
        this(context, null);
    }

    public XZHRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //这里初始化FooterView,并给里面的一个菊花图片添加一个动画
        mListFooter = LayoutInflater.from(context).inflate(R.layout.list_footer, null, false);
        Animation anim = AnimationUtils.loadAnimation(context, R.anim.img_animation);
        LinearInterpolator lin = new LinearInterpolator();
        anim.setInterpolator(lin);
        mListFooter.findViewById(R.id.progress_iv).startAnimation(anim);
    }

    //这里set回调函数
    public void setOnLoadListener(OnLoadListener loadListener) {
        this.mLoadListener = loadListener;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //这里判断ViewGroup里面是不是有个子View,并且第一个是不是ListView
        int childCount = getChildCount();
        if (childCount > 0) {
            View child = getChildAt(0);
            if (child instanceof ListView) {
                mListView = (ListView) child;

            }
        }

    }

    //用于添加和移除FooterView
    public void setLoad(boolean isLoad) {
        isLoading = isLoad;
        if (isLoad) {

            mListView.addFooterView(mListFooter);
        } else {

            mListView.removeFooterView(mListFooter);
        }
    }

    //记录手指触摸屏幕的上一个Y坐标值
    private float lastY;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        float currentY = ev.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:
                //如果当前的Y坐标小于上一个Y坐标的值说明是向上滑动,,并且子ListView不为null,并且没有FooterView
                if (currentY < lastY && mListView != null && mListView.getFooterViewsCount() == 0) {
                    //如果当前listView的最后一个item的position等于可见范围内最后一个item的position,
                    //并且屏幕中的item总数小于11,当前没有加载FooterView
                    if (mListView.getAdapter().getCount() - 1 == mListView.getLastVisiblePosition() 
                        && mListView.getChildCount() >= 11 && !isLoading) {
                        setLoad(true);//添加FooterView
                        mLoadListener.onLoad();//执行回调函数
                    }
                }
                break;
        }
        lastY = currentY;
        return super.onInterceptTouchEvent(ev);
    }
    
    //回调
    public interface OnLoadListener {

        void onLoad();
    }
}

最核心的代码已经实现了,网上有很多Demo是在onScroll方法中实现的,但是我发现在滑动到底部时,onScroll方法一直在执行,那么这样的话会导致我们一直的执行回调函数,因为这里的回调函数是用来加载数据的,从而会导致不停地获取数据,不停的添加和移除FooterView,并且导致ListView的点击事件失效,所以我将其移到了onInterceptTouchEvent(MotionEvent ev)里面去执行。



下面上Activity的代码:

public class MessageListActivity extends AppCompatActivity {


    private Toolbar SMSToolbar;
    private XZHRefreshLayout refreshLayout;
    private ListView lvSMSList;
    private MessageListAdapter adapter;
    private List smsList;
    private MRLTDao dao;

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

        initData();
        initView();
    }


    /**
     * TODO: 初始化控件
     */
    private void initView() {

        SMSToolbar = (Toolbar) findViewById(R.id.sms_list_toolbar);
        SMSToolbar.setTitle("短信列表");
        SMSToolbar.setNavigationIcon(ContextCompat.getDrawable(this, R.mipmap.btn_back));
        SMSToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
        //实现我们自定义的下拉刷新控件
        refreshLayout = (XZHRefreshLayout) findViewById(R.id.refresh_sms_ly);
        refreshLayout.setColorSchemeColors(ContextCompat.getColor(this, android.R.color.holo_blue_bright),
                ContextCompat.getColor(this, android.R.color.holo_green_light),
                ContextCompat.getColor(this, android.R.color.holo_orange_light),
                ContextCompat.getColor(this, android.R.color.holo_red_light));
        //监听下拉刷新事件
        refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        smsList.clear();
                        smsList.addAll(dao.querySMSALL(0));
                        adapter.notifyDataSetChanged();
                        refreshLayout.setRefreshing(false);
                    }
                }, 1500);
            }
        });
        //我们写的回调函数,在里面做查找数据的方法
        refreshLayout.setOnLoadListener(new XZHRefreshLayout.OnLoadListener() {
            @Override
            public void onLoad() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //我这里是用了一个Sqlite,大家可以根据自己的实际应用在这里做数据的查询,相信大家一般都不可能会有问题。
                        if (dao != null && smsList != null) {
                            List<SmsEntity> datas = dao.querySMSALL(smsList.size());
                            if (datas.size() > 0) {//如果查询到有数据,就添加到数据源里面去。
                                smsList.addAll(datas);
                                adapter.notifyDataSetChanged();
                            }else{//如果没有数据,就弹一个吐司
                                MyToast.show(MessageListActivity.this,"没有更多数据!");
                            }
                        }
                        refreshLayout.setLoad(false);

                    }
                }, 1000);

            }
        });

        lvSMSList = (ListView) findViewById(R.id.sms_list_lv);
        adapter = new MessageListAdapter(this, smsList);
        lvSMSList.setAdapter(adapter);
        lvSMSList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SmsEntity entity = (SmsEntity) adapter.getItem(position);
                showSMSDialog(entity);
            }
        });

    }

    /**
     * TODO: 初始化数据
     */
    private void initData() {
        if (smsList == null)
            smsList = new ArrayList<>();
        if (dao == null)
            dao = new MRLTDao(getApplicationContext());
        smsList = dao.querySMSALL(0);

    }


    @Override
    protected void onDestroy() {

        super.onDestroy();
    }
    //点击item弹一个Dialog,显示当前Item的内容
    private void showSMSDialog(SmsEntity entity) {
        if (entity == null) {
            return;
        }
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(entity.getSendcode());
        builder.setMessage("接收时间:"+entity.getCreate_time()+"\n"+entity.getContent());
        builder.setPositiveButton("知道了", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        builder.create().show();

    }
}

总的来说Activity里面完全没有啥技术含量,只是有可能代码写的其丑无比。

下面上XML:

1.Activity的XML文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_message_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.yihuacomputer.sdmrlt.ui.MessageListActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/sms_list_toolbar"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/cpb_blue"
        app:titleTextColor="@color/cpb_white" />
<com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout
    android:id="@+id/refresh_sms_ly"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/sms_list_toolbar">
    <ListView
        android:id="@+id/sms_list_lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:scrollbars="none">

    </ListView>
</com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout>


</RelativeLayout>

2.ListView的Item的XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:paddingBottom="4dp"
    android:paddingTop="4dp"
    android:weightSum="10">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@mipmap/will" />

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="9"
        android:layout_marginLeft="4dp">

        <TextView
            android:id="@+id/item_sms_rvd_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/colorPrimaryDark"
            android:maxLength="15"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/item_sms_time_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/colorPrimaryDark"
            android:textSize="16sp"
            android:layout_alignParentTop="true"
            android:layout_alignParentEnd="true" />

        <TextView
            android:id="@+id/item_sms_content_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/item_sms_rvd_tv"
            android:maxLines="1"
            android:textColor="@color/menu_fragment_background"
            android:textSize="14sp" />
    </RelativeLayout>
</LinearLayout>

3.FooterView的XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/progress_iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/gpu" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="正在加载..."/>

</LinearLayout>

所有的XML文件里面就用到了两个Image,大家随便去找两个就可以了,我是解压了手机QQ的App后这里面找的。

好了所有的东西基本已经实现,大家还可以在这个基础上扩展一下,比如加一个动画,让FooterView被移除的时候好看一点,不要那么突兀的就消失了,如果大家实现了,希望能留个言让我学习学习!!!公司没有录屏工具,我就不上图了。

猜你喜欢

转载自blog.csdn.net/sumsear/article/details/53674063