前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >仿 iOS 列表的编辑功能 - 删除篇

仿 iOS 列表的编辑功能 - 删除篇

作者头像
NanBox
发布于 2019-07-09 12:25:05
发布于 2019-07-09 12:25:05
1K00
代码可运行
举报
文章被收录于专栏:NanBoxNanBox
运行总次数:0
代码可运行

iOS 的设置里面,有一种编辑的效果,进入编辑状态后,列表左边推出圆形的删除按钮,点击后再出现右边确认删除按钮,相当于给用户二次确认。看下在 Android 上如何实现。

iOS 的效果如下:

我实现的效果是这样的:

下面说说我是怎么做的吧。

EditLayout

我们自定义了一个 EditLayout 继承 FrameLayout。 可以看出,这个控件由左中右三部分组成,对应的,我在 EditLsyout 里创建了以下成员变量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private View mContentView;  //内容部分
private View mLeftView;     //左边圆形删除按键
private View mRightView;    //右边删除按键
private int mWidth;         //内容部分宽度
private int mHeight;        //内容部分高度
private int mLeftWidth;     //左边部分宽度
private int mRightWidth;    //右边部分宽度复制代码

获取控件及宽高

当 View 中所有的子控件 均被映射成 xml 后,会触发 onFinishInflate 方法,当 view 的大小发生变化时,会触发 onSizeChanged 方法,所以我们可以这样赋值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    mLeftView = getChildAt(0);
    mContentView = getChildAt(1);
    mRightView = getChildAt(2);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mWidth = w;
    mHeight = h;
    mRightWidth = mRightView.getMeasuredWidth();
    mLeftWidth = mLeftView.getMeasuredWidth();
}

摆放控件位置

获取到控件和宽高,我们就可以摆放它们的位置了。我们知道,View 是通过 onLayout 方法来摆放控件位置的。这里有两种摆放方式,编辑状态和非编辑状态,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    //判断是否为编辑模式,摆放每个子View的位置
    if (EditAdapter.isEdit) {
        mContentView.layout(mLeftWidth, 0, mLeftWidth + mWidth, mHeight);
        mRightView.layout(mWidth + mLeftWidth, 0, mRightWidth + mWidth + LeftWidth, mHeight);
        mLeftView.layout(0, 0, mLeftWidth, mHeight);
    } else {
        mContentView.layout(0, 0, mWidth, mHeight);
        mRightView.layout(mWidth, 0, mRightWidth + mWidth, mHeight);
        mLeftView.layout(-mLeftWidth, 0, 0, mHeight);
    }
}

滑动效果

滑动效果,我交给了 ViewDragHelper 处理。要使用 ViewDragHelper ,需要实现一个 ViewDragHelper.Callback,这是一个抽象类,我们这里只关注它的三个方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//返回值决定 child 是否可拖拽
public boolean tryCaptureView(View child, int pointerId)
//限定移动范围,返回值为对应控件的左边位置
public int clampViewPositionHorizontal(View child, int left, int dx)
//当 changedView 发生移动时的回调(可以用来更新其他子 View 的位置)
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)

我实现的 Callback 代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
        return false;
    }

    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
        if (child == mContentView) {
            if (left < -mRightWidth) {
                left = -mRightWidth;
            } else if (left > mLeftWidth) {
                left = mLeftWidth;
            }
        } else if (child == mRightView) {
            if (left < mWidth - mRightWidth) {
                left = mWidth - mRightWidth;
            } else if (left > mWidth) {
                left = mWidth;
            }
        } else if (child == mLeftView) {
            if (left < mWidth - mRightWidth) {
                left = mWidth - mRightWidth;
            } else if (left > -mLeftWidth) {
                left = 0 - mLeftWidth;
            }
        }
        return left;
    }

    @Override
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
        if (changedView == mContentView) {
            mRightView.offsetLeftAndRight(dx);
            mLeftView.offsetLeftAndRight(dx);
        } else if (changedView == mRightView) {
            mContentView.offsetLeftAndRight(dx);
            mLeftView.offsetLeftAndRight(dx);
        } else if (changedView == mLeftView) {
            mContentView.offsetLeftAndRight(dx);
            mRightView.offsetLeftAndRight(dx);
        }
        invalidate();
    }
};

mDragHelper = ViewDragHelper.create(this, mCallback);

对了,实现滑动还需要重写 computeScroll 方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public void computeScroll() {
    super.computeScroll();
    if (mDragHelper.continueSettling(true)) {
        ViewCompat.postInvalidateOnAnimation(this);
    }
}

三种状态

我们这个控件存在三种状态,分别是左边展开,右边展开,还有关闭。相应的,我们定义三个方法,用于滑动到不同的状态:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 展开左侧
 */
public void openLeft() {
    if (mOnStateChangeListener != null) {
        mOnStateChangeListener.onLeftOpen(this);
    }
    mDragHelper.smoothSlideViewTo(mContentView, mLeftWidth, 0);
    invalidate();
}

/**
 * 展开右侧
 */
public void openRight() {
    if (mOnStateChangeListener != null) {
        mOnStateChangeListener.onRightOpen(this);
    }
    mDragHelper.smoothSlideViewTo(mContentView, -mRightWidth, 0);
    invalidate();
}

/**
 * 关闭
 */
public void close() {
    if (mOnStateChangeListener != null) {
        mOnStateChangeListener.onClose(this);
    }
    mDragHelper.smoothSlideViewTo(mContentView, 0, 0);
    invalidate();
}

mOnStateChangeListener 是一个监听器,会在 EditLayout 状态改变的时候调用。我在回调方法里保存了当前向右展开的 EditLayout。

到这里,EditLayout 就完成了。

EditAdapter

接下来看下适配器 EditAdapter。

item 布局

item 的 xml 文件里面,最外层用我们的 EditLayout 包裹,然后里面的三个子布局,按顺序,对应我们左中右三个部分。

切换编辑模式

这里需要定义一个 EditLayout 的集合 allItems,在 onBindViewHolder 的时候将布局添加进去。 然后我们定义两个公开方法,用于切换所有 item 的状态,在切换编辑模式的时候调用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 关闭所有 item
 */
public void closeAll() {
    for (EditLayout layout : allItems) {
        editLayout.close();
    }
}

/**
 * 将所有 item 向左展开
 */
public void openLeftAll() {
    for (EditLayout layout : allItems) {
        editLayout.openLeft();
    }
}

EditRecyclerView

当列表有某一项是右边展开了,我希望在滑动列表的时候能将它关闭,变回向左展开的状态,所以我自定义了一个 RecyclerView。

可以重写了 onTouchEvent 方法,实现上面说的效果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public boolean onTouchEvent(MotionEvent e) {
    switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (getAdapter() instanceof EditAdapter) {
                rightOpenItem = ((EditAdapter) getAdapter()).getRightOpenItem();
            }
            if (EditAdapter.isEdit && rightOpenItem != null) {
                rightOpenItem.openLeft();
            }
    }
    return super.onTouchEvent(e);
}

当滑动列表的时候,先判断是否有向右展开项,有的话就将它变回向左展开。

这样就完成啦,妥妥的。

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
10.侧拉删除
* 应用场景: 聊天列表界面,邮件管理界面等条目管理(设为已读, 删除等) * 功能实现: 参考 侧滑面板 offsetLeftAndRight , offsetTopAndBottom activi
六月的雨
2018/05/14
7240
SwipeLayout一个展示条目底层菜单的侧滑控件
由于项目上的需要侧滑条目展示收藏按钮,记得之前代码家有写过一个厉害的开源控件 AndroidSwipeLayout 本来准备直接拿来使用,但是看过 issue 发现现在有不少使用者反应有不少的 bug ,而且代码家现在貌似也不进行维护了.故自己实现了一个所要效果的一个控件.因为只是实现我需要的效果,所以大家也能看到,代码里有不少地方我是写死的.希望对大家有些帮助.而且暂时也不需要 AndroidSwipeLayout 大而全的功能,算是变相给自己做的项目精简代码了.
夏洛克的猫
2018/10/18
6250
SwipeLayout一个展示条目底层菜单的侧滑控件
ViewDragHelper使用笔记及侧滑菜单实践
ViewDragHelper 一个拖拽实现的帮助类,存在于v4包中,对于实现简单的拖拽简直不要太简单;再也不用去重写onTouch()了; 官网API https://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.html 该类主要用于拖拽view的实现,例如侧滑菜单时候的左右拖拽或者上下拖拽 使用方法 创建 ViewDragHelper实例 ViewDragHelper create (ViewGroup
佛系编码
2018/05/22
1.4K0
android 仿音悦台页面交互效果
概述 新版的音悦台 APP 播放页面交互非常有意思,可以把播放器往下拖动,然后在底部悬浮一个小框,还可以左右拖动,然后回弹的时候也会有相应的效果,这种交互效果在头条视频和一些专注于视频的app也是很常
xiangzhihong
2018/02/05
1K0
android 仿音悦台页面交互效果
让你的ListView更炫酷,实现侧滑删除效果
又到了更新博客的时间了,今天给大家带来的是ListView侧滑出现删除等按钮的效果。相信大家在平时玩app的时候都接触过这种效果吧。比如说QQ聊天列表侧滑就会出现“置顶”、“标为已读”、“删除”等按钮。这篇博文将用ViewDragHelper这个神器来实现侧滑效果。友情链接一下之前写的博文使用ViewDragHelper来实现侧滑菜单的,点击此处跳转。如果你对ViewDragHelper不熟悉,你可以去看看鸿洋_的《Android ViewDragHelper完全解析 自定义ViewGroup神器》。
俞其荣
2022/07/28
1.2K0
让你的ListView更炫酷,实现侧滑删除效果
使用ViewDragHelper打造属于自己的DragLayout(抽屉开关 )
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/51935896
程序员徐公
2018/09/18
8610
使用ViewDragHelper打造属于自己的DragLayout(抽屉开关 )
7.侧滑、ViewDragHelper、属性动画
实现这样的效果: ## 侧滑面板(对ViewGroup的自定义) * 应用场景: 扩展主面板的功能 * 功能实现: > 1. ViewDragHelper: Google2013年IO大会提出的,
六月的雨
2018/05/14
1.2K0
Android自定义控件总结
自定义控件分类: 1、使用系统控件,实现自定义的效果 2、自己定义一个类继承View ,如textView、ImageView等,通过重写相关的方法来实现新的效果 3、自己定义一个类继承ViewGroup,实现相应的效果 继承view类或viewgroup类,来创建所需要的控件。一般来讲,通过继承已有的控件来自定义控件要简单一点。 介绍下实现一个自定义view的基本流程 1.明确需求,确定你想实现的效果。 2.确定是使用组合控件的形式还是全新自定义的形式,组合控件即使用多个系统控件来合成一个新控件,你比如t
六月的雨
2018/05/14
1.3K0
神奇的 ViewDragHelper,让你轻松定制拥有拖拽能力的 ViewGroup
相信这种效果大家都见过吧?我第一次见到这样的效果时,心里也痒痒的,急于想实现这种功能,后来因为拖延症的问题,就一直没有去弄这件事。现在这段时间,工作比较轻闲,所以对自己几年 Android 生涯所运用的技术做一些总结与思考。拖拽这种功能正好可以形成一个主题。如题目所示,今天博文的目标就是介绍与分析 ViewDragHelper 这个类。
Frank909
2019/01/14
3.6K0
Android ViewDragHelper及移动处理总结
概述 2013年谷歌i/o大会上介绍了两个新的layout: SlidingPaneLayout和DrawerLayout,现在这俩个类被广泛的运用。我们知道在我们实际的开发中往往会涉及到很多的拖动效果,而ViewDragHelper解决了android中手势处理过于复杂的问题。 其实ViewDragHelper并不是第一个用于分析手势处理的类,gesturedetector也是,但是在和拖动相关的手势分析方面gesturedetector只能说是勉为其难,其拓展性并不好。 为了方便大家的理解,我们
xiangzhihong
2018/02/05
1.5K0
Android ViewDragHelper及移动处理总结
Android滑动删除控件
Android滑动删除控件 效果展示 代码实现 静态布局 自定义一个ViewGroup,继承至FrameLayout,覆写其中的几个关键方法,用于给其中的两个子view设置布局位置。 priv
felix
2018/06/08
2.3K0
简单实现炫酷的滑动返回效果
前言 ====== 在如今 app 泛滥的年代里,越来越多的开发者注重用户体验这个方面了。其中,有很多的 app 都有一种功能,那就是滑动返回。比如知乎、百度贴吧等,用户在使用这一类的 app 都可以滑动返回上一个页面。不得不说这个设计很赞,是不是心动了呢?那就继续往下看吧!
俞其荣
2022/07/28
7950
简单实现炫酷的滑动返回效果
轻松实现右滑关闭当前Activity
常常可以看到,很多Android应用都有这么一个功能,就是滑动关闭Activity,比如微信,CSDN移动端,百度贴吧移动端等。我自己也想写个滑动关闭Activity,最近事情没有那么多,我就google了一下,查看了一下实现滑动关闭Activity的实现方法,其中,有个思路,我觉得很不错,因此,在这里,我通过别人的思路,自己实现了一下滑动关闭Activity的方法,在此记录一下。
蜻蜓队长
2018/08/03
1.4K0
轻松实现右滑关闭当前Activity
相关推荐
10.侧拉删除
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验