安卓开发-ListView侧拉菜单,置顶等仿QQ侧拉菜单侧拉点击切换图片,侧拉点击事件带上拉加载更多,下拉刷新

项目中需要有listview侧拉出菜单,点击可以置顶,撤销,暂停,删除的功能 在此记录一下。
需求是侧拉可以拉出菜单,然后点击侧拉菜单的每个条目有相应的点击事件处理,而且再次侧拉的图标需要改变,再加上上拉加载更多,下拉刷新。安卓原生的listview不像苹果的tableview一样自带侧拉接口,所有肯定需要自定义控件了,所以刚开始试了3种实现方式
先看效果图(这是3的效果图)


demo地址
1.第一种就是把listview的item布局设置成paddingleft或者paddingright是负的,然后继承listview 重写onTouchEvent方法,然在move时候判断x坐标变化,以此来判断左滑还是右滑,然后滑出来的点击事件在adapter里操作,因为我侧拉置顶或者别的需要点击事件继续请求服务器,实际操作中很麻烦而且换不了侧拉后的图标,所以planA放弃了

package com.hxzh.uniwill.lingjian.View;

/**
 * Created by pang on 2017/3/30.
 */
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Scroller;

/**
 * 侧向滑出菜单的ListView
 * 使用请注意与ListView的Item的布局配合,
 * 该效果的实现是基于在Item的布局中通过设置PaddingLeft和PaddingRight来隐藏左右菜单的,
 * 所以使用此ListView时,请务必在布局Item时使用PaddingLeft和PaddingRight;
 * 或者自己改写此ListView,已达到想要的实现方式
 *
 */
public class SlideListView2 extends ListView {

    /**禁止侧滑模式*/
    public static int MOD_FORBID = 0;
    /**从左向右滑出菜单模式*/
    public static int MOD_LEFT = 1;
    /**从右向左滑出菜单模式*/
    public static int MOD_RIGHT = 2;
    /**左右均可以滑出菜单模式*/
    public static int MOD_BOTH = 3;
    /**当前的模式*/
    private int mode = MOD_FORBID;
    /**左侧菜单的长度*/
    private int leftLength = 0;
    /**右侧菜单的长度*/
    private int rightLength = 0;

    /**
     * 当前滑动的ListView position
     */
    private int slidePosition;
    /**
     * 手指按下X的坐标
     */
    private int downY;
    /**
     * 手指按下Y的坐标
     */
    private int downX;
    /**
     * ListView的item
     */
    private View itemView;
    /**
     * 滑动类
     */
    private Scroller scroller;
    /**
     * 认为是用户滑动的最小距离
     */
    private int mTouchSlop;

    /**
     * 判断是否可以侧向滑动
     */
    private boolean canMove = false;
    /**
     * 标示是否完成侧滑
     */
    private boolean isSlided = false;

    /**后加
     * 速度追踪对象
     */
    private VelocityTracker velocityTracker;
    private static final int SNAP_VELOCITY = 600;
    /**后加
     * 是否响应滑动,默认为不响应
     */
    private boolean isSlide = false;

    private OnDeleteListener listener;


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

    public SlideListView2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlideListView2(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        scroller = new Scroller(context);
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }

    public void setOnDeleteListener(OnDeleteListener l) {
        listener = l;
    }


    /**
     * 初始化菜单的滑出模式
     * @param mode
     */
    public void initSlideMode(int mode){
        this.mode = mode;
    }
    /**
     * 后加+
     * 分发事件,主要做的是判断点击的是那个item, 以及通过postDelayed来设置响应左右滑动事件
     */

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                System.out.println("dispatch-->" + "down");
                addVelocityTracker(event);

                // 假如scroller滚动还没有结束,我们直接返回
                if (!scroller.isFinished()) {
                    return false;
                }
                downX = (int) event.getX();
                downY = (int) event.getY();

                slidePosition = pointToPosition(downX, downY);

                // 无效的position, 不做任何处理
                if (slidePosition == AdapterView.INVALID_POSITION) {
                    return super.dispatchTouchEvent(event);
                }

                // 获取我们点击的item view
                itemView = getChildAt(slidePosition - getFirstVisiblePosition());
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                System.out.println("dispatch-->" + "move");
                if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY
                        || (Math.abs(event.getX() - downX) > mTouchSlop && Math
                        .abs(event.getY() - downY) < mTouchSlop)) {
                    isSlide = true;

                }
                break;
            }
            case MotionEvent.ACTION_UP:
                recycleVelocityTracker();
                break;
        }

        return super.dispatchTouchEvent(event);
    }


    /**
     * 处理我们拖动ListView item的逻辑
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        final int action = ev.getAction();
        int lastX = (int) ev.getX();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                System.out.println("touch-->" + "down");
                /*当前模式不允许滑动,则直接返回,交给ListView自身去处理*/
                if(this.mode == MOD_FORBID){
                    return super.onTouchEvent(ev);
                }

                // 如果处于侧滑完成状态,侧滑回去,并直接返回
                if (isSlided) {
                    scrollBack();
                    return false;
                }
                // 假如scroller滚动还没有结束,我们直接返回
                if (!scroller.isFinished()) {
                    return false;
                }
                downX = (int) ev.getX();
                downY = (int) ev.getY();

                slidePosition = pointToPosition(downX, downY);

                // 无效的position, 不做任何处理
                if (slidePosition == AdapterView.INVALID_POSITION) {
                    return super.onTouchEvent(ev);
                }

                // 获取我们点击的item view
                itemView = getChildAt(slidePosition - getFirstVisiblePosition());
                /*此处根据设置的滑动模式,自动获取左侧或右侧菜单的长度*/
                if(this.mode == MOD_BOTH){
                    this.leftLength = -itemView.getPaddingLeft();
                    this.rightLength = -itemView.getPaddingRight();
                }else if(this.mode == MOD_LEFT){
                    this.leftLength = -itemView.getPaddingLeft();
                }else if(this.mode == MOD_RIGHT){
                    this.rightLength = -itemView.getPaddingRight();
                }

                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("touch-->" + "move");

                if (!canMove
                        && slidePosition != AdapterView.INVALID_POSITION
                        && (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev
                        .getY() - downY) < mTouchSlop)) {
                    int offsetX = downX - lastX;
                    if(offsetX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){
               /*从右向左滑*/
                        canMove = true;
                    }else if(offsetX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){
               /*从左向右滑*/
                        canMove = true;
                    }else{
                        canMove = false;
                    }
            /*此段代码是为了避免我们在侧向滑动时同时触发ListView的OnItemClickListener时间*/
                    MotionEvent cancelEvent = MotionEvent.obtain(ev);
                    cancelEvent
                            .setAction(MotionEvent.ACTION_CANCEL
                                    | (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                    onTouchEvent(cancelEvent);
                }
                if (canMove) {
            /*设置此属性,可以在侧向滑动时,保持ListView不会上下滚动*/
                    requestDisallowInterceptTouchEvent(true);

                    // 手指拖动itemView滚动, deltaX大于0向左滚动,小于0向右滚
                    int deltaX = downX - lastX;
                    if(deltaX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){
               /*向左滑*/
                        itemView.scrollTo(deltaX, 0);
                    }else if(deltaX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){
               /*向右滑*/
                        itemView.scrollTo(deltaX, 0);
                    }else{
                        itemView.scrollTo(0, 0);
                    }
                    return true; // 拖动的时候ListView不滚动
                }
            case MotionEvent.ACTION_UP:
                System.out.println("touch-->" + "up");
                if (canMove){
                    canMove = false;
                    scrollByDistanceX();
                }
                break;
        }

        // 否则直接交给ListView来处理onTouchEvent事件
        return super.onTouchEvent(ev);
    }

    /**
     * 根据手指滚动itemView的距离来判断是滚动到开始位置还是向左或者向右滚动
     */
    private void scrollByDistanceX() {
      /*当前模式不允许滑动,则直接返回*/
        if(this.mode == MOD_FORBID){
            return;
        }
        if(itemView.getScrollX() > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){
         /*从右向左滑*/
            if (itemView.getScrollX() >= rightLength / 2) {
                scrollLeft();
            }  else {
                // 滚回到原始位置
                scrollBack();
            }
        }else if(itemView.getScrollX() < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){
         /*从左向右滑*/
            if (itemView.getScrollX() <= -leftLength / 2) {
                scrollRight();
            } else {
                // 滚回到原始位置
                scrollBack();
            }
        }else{
            // 滚回到原始位置
            scrollBack();
        }

    }
    /** 后加+
     * 添加用户的速度跟踪器
     *
     * @param event
     */
    private void addVelocityTracker(MotionEvent event) {
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }

        velocityTracker.addMovement(event);
    }

    /**后加+
     * 移除用户速度跟踪器
     */
    private void recycleVelocityTracker() {
        if (velocityTracker != null) {
            velocityTracker.recycle();
            velocityTracker = null;
        }
    }

    /**后加+
     * 获取X方向的滑动速度,大于0向右滑动,反之向左
     *
     * @return
     */
    private int getScrollVelocity() {
        velocityTracker.computeCurrentVelocity(1000);
        int velocity = (int) velocityTracker.getXVelocity();
        return velocity;
    }

    /**
     * 往右滑动,getScrollX()返回的是左边缘的距离,就是以View左边缘为原点到开始滑动的距离,所以向右边滑动为负值
     */
    private void scrollRight() {
        isSlided = true;
        final int delta = (leftLength + itemView.getScrollX());
        // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item
        scroller.startScroll(itemView.getScrollX(), 0, -delta, 0,
                Math.abs(delta));
        postInvalidate(); // 刷新itemView
    }

    /**
     * 向左滑动,根据上面我们知道向左滑动为正值
     */
    private void scrollLeft() {
        isSlided = true;
        final int delta = (rightLength - itemView.getScrollX());
        // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item
        scroller.startScroll(itemView.getScrollX(), 0, delta, 0,
                Math.abs(delta));
        postInvalidate(); // 刷新itemView
    }

    /**
     * 滑动会原来的位置
     */
    private void scrollBack() {
        isSlided = false;
        scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(),
                0, Math.abs(itemView.getScrollX()));
        postInvalidate(); // 刷新itemView
    }

    @Override
    public void computeScroll() {
        // 调用startScroll的时候scroller.computeScrollOffset()返回true,
        if (scroller.computeScrollOffset()) {
            // 让ListView item根据当前的滚动偏移量进行滚动
            itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());

            postInvalidate();
        }
    }

    /**
     * 提供给外部调用,用以将侧滑出来的滑回去
     */
    public void slideBack() {
        this.scrollBack();
    }

    public interface OnDeleteListener {

        void onDelete(int index);

        void onTop(int index);

    }



}

2.还是从item角度考虑,把item当作一个viewgroup,耦合性最低,没有冲突,滑动体验非常的棒,类似与iOS侧拉的阻塞式体验,也就是侧拉时候禁止上拉下拉,但是实际操作中并不能动态更换图标,所有也放弃了planB(控件没有问题,可能我自己没解决好)
这里是开源控件的地址SwipeDelMenuLayout
3.然后就选择了开源的控件使用
感谢侧拉listview控件SwipeMenuListView
3.1

compile 'com.baoyz.swipemenulistview:library:1.3.0'
布局

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swiperefreshlayout"
    android:layout_below="@+id/titlefragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.baoyz.swipemenulistview.SwipeMenuListView
        android:id="@+id/swiplistView"
        android:cacheColorHint="#00000000"
        android:listSelector="#00000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</android.support.v4.widget.SwipeRefreshLayout>

下拉刷新用的是v4包自带的swiperefreshlayout
3.2:然后先看adapter

//这里根据置顶字段来区别position
@Override
public int getItemViewType(int position) {
    int type = -1;
    data = list2.get(position);
    iszhiding = data.getStick();//置顶字段
    switch (iszhiding) {
        case 0:
            type = 0;
            break;
        case 1:
            type = 1;
            break;
    }
    return type;

}
//返回条目类型,侧拉置顶,侧拉取消置顶,-1
@Override
public int getViewTypeCount() {

    return 3;
}

就是正常的写法 ,这里是加了两个方法,就是实现多条目布局,getitemviewtype返回条目类型,getviewtypecount返回条目类型个数,然后侧拉出来置顶,和再次侧拉出来取消置顶,两个显示图标其实就是两种条目类型,根据服务器字段显示置顶或是取消置顶的图标,我这里只写了一种菜单,比如侧拉菜单要是多个,比如三个的话,就是6种条目类型,然后根据返回字段判断对应显示的图标,
3.3:然后用代码构造侧拉的菜单,可以设置图标,还有宽度

//侧拉swipmenulistview  构建侧拉菜单
SwipeMenuCreator creator1 = new SwipeMenuCreator() {
    @Override
    public void create(SwipeMenu menu) {

        switch (menu.getViewType()) {

            case 0:
                createMenu1(menu);
                break;
            case 1:
                createMenu2(menu);
                break;

        }
    }

    private void createMenu1(SwipeMenu menu) {
        //创建置顶项
        SwipeMenuItem zditem1 = new SwipeMenuItem(MainActivity.this);
        //设置item width
        zditem1.setWidth(dp2px(60));
        //设置背景
        zditem1.setBackground(R.color.listview_item_right_bg);
        //图标
        zditem1.setIcon(R.drawable.list_slide_but_stick2x);
        // 添加到菜单
        menu.addMenuItem(zditem1);
    }

    private void createMenu2(SwipeMenu menu) {
        //创建置顶项
        SwipeMenuItem zditem2 = new SwipeMenuItem(MainActivity.this);
        //设置item width
        zditem2.setWidth(dp2px(60));
        //设置背景
        zditem2.setBackground(R.color.listview_item_right_bg);
        //图标
        zditem2.setIcon(R.drawable.list_slide_but_canstick2x);
        // 添加到菜单
        menu.addMenuItem(zditem2);
    }
};

然后设置侧拉菜单的点击事件

//设置创建者
        swiplistView.setMenuCreator(creator1);
        //step 2. listener item click event
        swiplistView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                data1 = list1.get(position);
                taskid = data1.getTaskid();
                iszhiding1 = data1.getStick();//置顶
                //显示置顶
                if (iszhiding1 == 0) {
                    try {
                        OkHttpUtils.post(zhiding)
                                .params("userid", userid)
                                .params("taskid", taskid)
                                .execute(new StringCallback() {
                                    @Override
                                    public void onSuccess(String s, Call call, Response response) {
                                        Data_uploadBack_tag back_tag = JsonUtil.parseJsonToBean(s, Data_uploadBack_tag.class);
                                        if (back_tag != null) {
//                                            ToastUtil.showToast("置顶");
                                            Toast.makeText(MainActivity.this,"置顶",Toast.LENGTH_SHORT).show();
                                            showmore();//置顶服务器排序后从新获取数据刷新页面
                                        } else {
//                                            ToastUtil.showToast("置顶失败");
                                            Toast.makeText(MainActivity.this,"置顶失败",Toast.LENGTH_SHORT).show();
                                        }

                                    }

                                    @Override
                                    public void onError(Call call, Response response, Exception e) {
                                        super.onError(call, response, e);
//                                        ToastUtil.showToast("置顶失败,头皮发麻");
                                        Toast.makeText(MainActivity.this,"置顶失败,头皮发麻",Toast.LENGTH_SHORT).show();
                                    }
                                });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                } else if (iszhiding1 == 1) {
                    try {
                        OkHttpUtils.post(quxiaozd)
                                .params("userid", userid)
                                .params("taskid", taskid)
                                .execute(new StringCallback() {
                                    @Override
                                    public void onSuccess(String s, Call call, Response response) {
                                        Data_uploadBack_tag back_tag = JsonUtil.parseJsonToBean(s, Data_uploadBack_tag.class);

                                        if (back_tag != null) {
//                                            ToastUtil.showToast("取消置顶");
                                            Toast.makeText(MainActivity.this,"取消置顶",Toast.LENGTH_SHORT).show();
                                            showmore();
                                        } else {
//                                            ToastUtil.showToast("取消失败");
                                            Toast.makeText(MainActivity.this,"取消失败",Toast.LENGTH_SHORT).show();
                                        }
                                    }

                                    @Override
                                    public void onError(Call call, Response response, Exception e) {
                                        super.onError(call, response, e);
                                        Toast.makeText(MainActivity.this,"联网失败",Toast.LENGTH_SHORT).show();
                                    }
                                });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return false;
            }
        });

上面代码大体就是根据点位置响应点击事件,然后联网,告诉服务器是那个条目被置顶或者别的操作,服务器会重新排序,这是后根据回调,然后重新加载页面,刷新,这样置顶就变成了取消置顶,同时图标也更换了,而且条目位置也会有所改变(这里服务器排序,并非手动置顶)
手动:可以通过修改对应集合数据源,根据侧拉的potion,添加到第一个索引,然后移除当前位置条目,然后刷新adapter,删除的话就直接集合rmove掉对应索引数据然后刷新
这里还有一点需要注意,通过隐藏下拉控件解决侧拉和上拉的冲突

//解决listview与SwipeRefreshLayout下拉滑动和侧拉冲突问题
swiplistView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
    @Override
    public void onMenuOpen(int position) {
        swipeRefreshLayout.setEnabled(false);
    }

    @Override
    public void onMenuClose(int position) {

    }
});
下拉和listview下拉冲突
           mListView1.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view, int scrollState) {
                    if (scrollState == SCROLL_STATE_IDLE) {
                        int lastposition = mListView1.getLastVisiblePosition();//最后一个item的位置
                //        if (lastposition == mListView1.getCount() - 1) {
                   //         isloadMore = true;
                    //        footview.setPadding(0, 0, 0, footheight);
                   //         Handler handler = new Handler();
                    //        handler.postDelayed(new Runnable() {
                                @Override
                  //              public void run() {
                  //                  onLoadMore();
                  //                  footview.setPadding(0, -footheight, 0, 0);
                    //                ToastUtil.showToast("加载完成");
                    //            }
                  //          }, 2000);
                  //      }
                //    }
                   if (mListView1 != null && mListView1.getChildCount() > 0
                           &&mListView1.getFirstVisiblePosition() == 0
                           &&mListView1.getChildAt(0).getTop() >=mListView1.getPaddingTop()) {
                       swipeRefreshLayout.setEnabled(true);
                   }else {
                       swipeRefreshLayout.setEnabled(false);
                   }


                }

                @Override
                public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

                boolean enable = false;
                    if (mListView1 != null && mListView1.getChildCount() > 0) {
                      // check if the first item of the list is visible
                       boolean firstItemVisible = mListView1.getFirstVisiblePosition() == 0;
                       // check if the top of the first item is visible
                       boolean topOfFirstItemVisible = mListView1.getChildAt(0).getTop() == 0;
                      // enabling or disabling the refresh layout
                       enable = firstItemVisible && topOfFirstItemVisible;
                   }
                    swipeRefreshLayout.setEnabled(enable);

                }
            });

3.4:然后就是上拉加载更多和下拉刷新

swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_green_light,
        android.R.color.holo_orange_light);
//下拉刷新
try {
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            swipeRefreshLayout.setRefreshing(true);
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    showmore();
                    Toast.makeText(MainActivity.this,"刷新完成",Toast.LENGTH_SHORT).show();
                    swipeRefreshLayout.setRefreshing(false);
                }
            },2000);
        }
    });
} catch (Exception e) {
    e.printStackTrace();
}

联网操作

//下拉刷新
private void showmore() {
    //联网刷新listview
    try {
        OkHttpUtils.get(Sever)
                .params("pn", 1)
                .params("size", sizeup)
                .params("userid", userid)
                .params("status", 3)
                .params("sort", 1)
                .params("type",1)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        shoudaorenwu = JsonUtil.parseJsonToBean(s, Data_chaxunliebiao_shoudaorenwu.class);
                        if (shoudaorenwu != null) {
                            if (list1 != null) {//还有数据
                                list1.clear();
                            }
                            list1 = shoudaorenwu.getList();
                            slideAdapter1 = new SlideAdapter1(MainActivity.this, list1);
                            swiplistView.setAdapter(slideAdapter1);
                            slideAdapter1.notifyDataSetChanged();
                        }else {
                            Toast.makeText(MainActivity.this,"对不起,没有最新数据了",Toast.LENGTH_SHORT).show();
                        }
                    }

                });
    } catch (Exception e) {
        e.printStackTrace();
    }

上拉就是添加脚布局
开始设成负的,拉的时候判断是否是底部,是就显示脚布局,然后分页加载,加载完,隐藏脚布局

footview = View.inflate(MainActivity.this, R.layout.listview_footer, null);

        footview.measure(0, 0);
        footheight = footview.getMeasuredHeight();
//        bootm = dp2px(45);
        footview.setPadding(0, -footheight, 0, 0);

        swiplistView.addFooterView(footview);
 swiplistView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == SCROLL_STATE_IDLE) {
                    int lastposition = swiplistView.getLastVisiblePosition();//最后一个item的位置
                    if (lastposition == swiplistView.getCount() - 1) {
                        footview.setPadding(0, 0, 0, footheight);
                        Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                onLoadMore();
                                footview.setPadding(0, -footheight, 0, 0);
//                                Toast.makeText(MainActivity.this,"加载完成",Toast.LENGTH_SHORT).show();
                            }
                        }, 2000);
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                boolean enable = false; //这里做判断,只有滑到顶部才出来下拉进度条
                if (swiplistView != null && swiplistView.getChildCount() > 0) {
                    // check if the first item of the list is visible
                    boolean firstItemVisible = swiplistView.getFirstVisiblePosition() == 0;
                    // check if the top of the first item is visible
                    boolean topOfFirstItemVisible = swiplistView.getChildAt(0).getTop() == 0;
                    // enabling or disabling the refresh layout
                    enable = firstItemVisible && topOfFirstItemVisible;
                }
                swipeRefreshLayout.setEnabled(enable);

            }
        });
 /**上拉加载更多
     *
     * 分页加载主要逻辑
     * 两个集合,一个用来接收最新的数据,他是小集合,因为每次联网对集合长度做了限制,最多10条,
     * 然后服务器有单独一个字段是服务器总共有多少数据,每次把小集合addll到大集合里,
     * 再判断大集合的长度是否小于服务器返回总条目数,小于就继续添加,等于或大于,就提示没有更多数据了
     *
     *
     * */
    int m = 1;
    private void onLoadMore() {
        //联网刷新listview
        m++;
        try {
            OkHttpUtils.get(Sever)
                    .params("pn", m)
                    .params("size", sizedown)
                    .params("userid", userid)
                    .params("status", 3)
                    .params("sort", 1)
                    .params("type",1)
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(String s, Call call, Response response) {
                            shoudaorenwu = JsonUtil.parseJsonToBean(s, Data_chaxunliebiao_shoudaorenwu.class);
                            if (shoudaorenwu.getList()!= null){
                                list2.clear();
                            }
                            list2 = shoudaorenwu.getList();
                            int totle = shoudaorenwu.getTotal();//服务器返回总数
                            int totle2 =  list1.size();//加载的数据
                            if (totle2 < totle) {
                                list1.addAll(list2);
                                slideAdapter1.notifyDataSetChanged();
                            } else {
                                m = 1;
//                                Toast.makeText(MainActivity.this,"没有更多数据了",Toast.LENGTH_SHORT).show();
                            }

                        }


                    });
        } catch (Exception e) {
            e.printStackTrace();
        }

最后 感谢阅读
demo地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容