前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android侧滑删除另一种实现,SwipeListView补充

Android侧滑删除另一种实现,SwipeListView补充

作者头像
xiangzhihong
发布2018-01-26 15:02:53
7161
发布2018-01-26 15:02:53
举报
文章被收录于专栏:向治洪向治洪

前不久在在做聊天删除功能的时候使用SwipeListView进行侧滑删除有一点小问题,因为SwipeListView嵌套在Fragment内的时候,会报一个转换错误,原因是SwipeListView是基于ListView实现的SwipeListView。 针对这个问题,首先想到的就是自定义View。首先看一下实现的效果。

这里写图片描述
这里写图片描述

自定义侧滑实现

实现的思路很简单,通过对onTouchEvent方法进行重写,判断滑动的距离来实现删除按钮的显示与隐藏。核心代码如下:

代码语言:javascript
复制
package com.shihui.butler.butler.msg.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Scroller;

import com.shihui.butler.R;


public class SwipeListView extends ListView {

    public static int MODE_FORBID = 0;
    public static int MODE_RIGHT = 1;
    private int mode = MODE_FORBID;
    private int rightLength = 0;
    private int slidePosition;
    private int downY;
    private int downX;
    private View itemView;
    private Scroller scroller;
    private int mTouchSlop;
    private boolean canMove = false;
    private boolean isSlided = false;

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

    public SwipeListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.SlideMode);
        mode = a.getInt(R.styleable.SlideMode_mode, 0);
    }

    public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.SlideMode);
        mode = a.getInt(R.styleable.SlideMode_mode, 0);
        scroller = new Scroller(context);
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }

    @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");
                if (this.mode == MODE_FORBID) {
                    return super.onTouchEvent(ev);
                }
                if (isSlided) {
                    scrollBack();
                    return false;
                }
                if (!scroller.isFinished()) {
                    return false;
                }
                downX = (int) ev.getX();
                downY = (int) ev.getY();
                slidePosition = pointToPosition(downX, downY);
                if (slidePosition == AdapterView.INVALID_POSITION) {
                    return super.onTouchEvent(ev);
                }
                itemView = getChildAt(slidePosition - getFirstVisiblePosition());
                if (this.mode == MODE_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 == MODE_RIGHT) {
                        canMove = true;
                    } else {
                        canMove = false;
                    }
                    MotionEvent cancelEvent = MotionEvent.obtain(ev);
                    cancelEvent
                            .setAction(MotionEvent.ACTION_CANCEL
                                    | (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
                    onTouchEvent(cancelEvent);
                }
                if (canMove) {
                    requestDisallowInterceptTouchEvent(true);
                    int deltaX = downX - lastX;
                    if (deltaX > 0 && this.mode == MODE_RIGHT) {
                        itemView.scrollTo(deltaX, 0);
                    } else {
                        itemView.scrollTo(0, 0);
                    }
                    return true;
                }
            case MotionEvent.ACTION_UP:
                System.out.println("touch-->" + "up");
                if (canMove) {
                    canMove = false;
                    scrollByDistanceX();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    private void scrollByDistanceX() {
        if (this.mode == MODE_FORBID) {
            return;
        }
        if (itemView.getScrollX() > 0 && this.mode == MODE_RIGHT) {
            if (itemView.getScrollX() >= rightLength / 2) {
                scrollLeft();
            } else {
                scrollBack();
            }
        } else {
            scrollBack();
        }

    }

    private void scrollLeft() {
        isSlided = true;
        final int delta = (rightLength - itemView.getScrollX());
        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()));
        // 刷新itemView
        postInvalidate();
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());

            postInvalidate();
        }
    }

    public void slideBack() {
        this.scrollBack();
    }

}

然后我们在界面上引入上面的SwipeListView。

代码语言:javascript
复制
<SwipeListView
            android:id="@+id/msg_listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:animationCache="false"
            android:divider="#E4E4E4"
            android:dividerHeight="0.5px"
            android:scrollbars="none"
            android:scrollingCache="false"
            app:mode="right"/>

在Adapter的子布局中,通过对SwipeListView滑动监听即可。 下面是Adapter的子布局方面,相关代码:

代码语言:javascript
复制
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@color/white"
    android:paddingRight="-100dp"
    >

    //...省略部分代码
         android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="删除"
        android:textColor="@android:color/white"
        android:textSize="18sp" />
</LinearLayout>

为了实现点击删除按钮删除,我们需要在Adapter中给按钮绑定点击事件,并通过接口回传给页面进行刷新。 adapter代码

代码语言:javascript
复制
private void initItemClick(ViewHolder viewHolder, final int position) {
    viewHolder.itemDel.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        if (mRemoveListener != null)
          mRemoveListener.onRemoveItem(position);
      }
    });
  }

//声明接口监听
public void setRemoveListener(OnRemoveListener removeListener) {
    this.mRemoveListener = removeListener;
  }

  public interface OnRemoveListener {
    void onRemoveItem(int position);
  }

然后我们在Fragment中直接调用即可。

代码语言:javascript
复制
controller.getAdapter().setRemoveListener(new MsgAdapter.OnRemoveListener() {
       @Override
       public void onRemoveItem(int position) {
       //删除聊天逻辑
       
       }
     });

就写到这里吧,有任何问题欢迎留言。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016/09/05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义侧滑实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档