Android中仿QQ左滑删除

最近对View的可定制化十分感兴趣,发现网络上的资源很少能够有实现QQ最新左滑策略的demo,自己想着做一个仿QQ左滑控件温习一下View的onTouchEvent事件处理机制。

目的:在ListView中添加删除、置顶和已未读按钮,功能比较简单,希望有需要的小伙伴直接可用,扩展功能自己去添加,有些需要注意的地方我会标注出来,节省大家一些宝贵的时间。

实现步骤:

1.实现一个简单的ListView控件

2.ListView的Item中根据用户类型来添加不同的按钮,并且将按钮的点击事件回调到Activity界面中

实现效果如下视频:

左滑删除ListView录屏

实现代码:

首先是自定义ListView的代码:

package com.example.qqlistviewdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Scroller;

import java.util.List;

/**
 * 自定义ListView Item中可以左滑删除
 */
public class CustomListView extends ListView {

    private static final String TAG = "CustomListView";

    private Context mContext;
    /**
     * 设置的最小滑动距离
     */
    private int touchSlop;
    /**
     * 记录是否点击事件的标识
     */
    private boolean isPerformClick;

    /**
     * 上次手指按下点的x坐标
     */
    private int lastX;
    /**
     * 上次手指按下点的y坐标
     */
    private int lastY;

    /**
     * 当前手指按下的item的view
     */
    private View mCurrentView;
    /**
     * 当前手指按压的item的position
     */
    private int currentPosition;

    /**
     * 记录item是否已经开始滑动
     */
    private boolean isStartScroll;

    private Scroller mScroller;
    /**
     * 当前item是否正在滑动打开删除和指定按钮
     */
    private boolean isCurrentItemMoving;

    private boolean isDragging;

    /**
     * 指定按钮和删除按钮的宽度
     */
    private int mMaxLength;
    /**
     * 删除和指定menu的状态:0 关闭;1 将要关闭;2 打开;3 将要打开
     */
    private int menuStatus = 0;
    private static final int MENU_CLOSE = 0;
    private static final int MENU_WILL_CLOSE = 1;
    private static final int MENU_OPEN = 2;
    private static final int MENU_WILL_OPEN = 3;

    private OnItemActionListener mListener;

    /**
     * 显示按钮的个数 0 一个;1 两个; 2 三个。对应用户类型
     */
    private static final int ONE_BUTTON = 0;
    private static final int TWO_BUTTONS = 1;
    private static final int THREE_BUTTONS = 2;

    private List<QQBean> mDatas;

    public CustomListView(Context context) {
        super(context);
        mContext = context;
        initView();
    }

    public CustomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initView();
    }

    public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }

    public void initView() {
        mScroller = new Scroller(mContext, new LinearInterpolator());
        touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        //判断scroller是否完成滑动
        if (mScroller.computeScrollOffset()) {
            mCurrentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            //这个很重要
            invalidate();
            //如果已经完成就改变状态
        } else if (isStartScroll) {
            isStartScroll = false;
            if (menuStatus == MENU_WILL_CLOSE) {
                menuStatus = MENU_CLOSE;
            }
            if (menuStatus == MENU_WILL_OPEN) {
                menuStatus = MENU_OPEN;
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        int x = (int) ev.getX();//触摸点到屏幕左边缘的距离 越往右值越大
        int y = (int) ev.getY();//触摸点到view控件上边界的距离 越往下值越大
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (menuStatus == MENU_CLOSE) {//如果删除按钮是关闭状态 正常逻辑 也就是点击事件
                    //根据坐标点所在获取当前item的布局
                    //获取当前按下的点所在item的位置 也就是list中的position
                    currentPosition = pointToPosition(x, y);
                    mCurrentView = getChildAt(currentPosition - getFirstVisiblePosition());//使用当前按下点所在的position-最上面显示的item的position
                    //初始化需要显示的内容
                    Button btnDelete = mCurrentView.findViewById(R.id.btn_delete);
                    Button btnTop = mCurrentView.findViewById(R.id.btn_top);
                    Button btnRead = mCurrentView.findViewById(R.id.btn_read);
                    switch (mDatas.get(currentPosition).getUserType()) {
                        case ONE_BUTTON:
                            mMaxLength = btnDelete.getWidth();//删除按钮的宽度
                            btnTop.setVisibility(GONE);
                            btnRead.setVisibility(GONE);
                            break;
                        case TWO_BUTTONS:
                            mMaxLength = btnDelete.getWidth() + btnTop.getWidth();//删除按钮和置顶按钮的宽度
                            btnTop.setVisibility(VISIBLE);
                            btnRead.setVisibility(GONE);
                            break;
                        case THREE_BUTTONS:
                            mMaxLength = btnDelete.getWidth() + btnTop.getWidth() + btnRead.getWidth();//删除按钮、置顶和标记已读未读按钮的宽度
                            btnTop.setVisibility(VISIBLE);
                            btnRead.setVisibility(VISIBLE);
                            break;
                    }
                    //在不显示删除和置顶按钮的时候设置 删除和置顶按钮的点击事件
                    btnDelete.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mCurrentView.scrollTo(0, 0);
                            menuStatus = MENU_CLOSE;
                            if (mListener != null) {
                                mListener.OnItemDelete(currentPosition);
                            }
                        }
                    });
                    btnTop.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mCurrentView.scrollTo(0, 0);
                            menuStatus = MENU_CLOSE;
                            if (mListener != null) {
                                mListener.OnItemTop(currentPosition);
                            }
                        }
                    });
                    btnRead.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mCurrentView.scrollTo(0, 0);
                            menuStatus = MENU_CLOSE;
                            if (mListener != null) {
                                mListener.OnItemRead(currentPosition);
                            }
                        }
                    });
                } else if (menuStatus == MENU_OPEN) {//如果删除按钮是打开状态 通过动画的方式滑动至删除按钮消失,并且return false
                    //原点(0,0)x轴坐标减去移动后的View视图左上角x轴坐标的值
                    mScroller.startScroll(mCurrentView.getScrollX(), 0, -mMaxLength, 0, 200);
                    //mCurrentView.scrollTo(0, 0);//如果用scrollTo方法那么没有一个动画效果,在用户看来会不友好
                    isStartScroll = true;
                    menuStatus = MENU_WILL_CLOSE;
                    invalidate();
                    return false;
                } else {
                    return false;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int dx = lastX - x;
                int dy = lastY - y;
                //如果是上下滚动,就直接忽略这次手势
                if (isDragging) {
                    lastX = x;
                    lastY = y;
                    return super.onTouchEvent(ev);
                }
                int scrollX = mCurrentView.getScrollX();//往左滑该值为正,往右滑该值为负值
                if (Math.abs(dx) > Math.abs(dy)) {//表明是正在横向滑动
                    isCurrentItemMoving = true;

                    if (scrollX + dx <= 0) {//item的布局原始位置,也就是item的布局不能再向右滑动了
                        mCurrentView.scrollTo(0, 0);
                        return false;
                    }
                    if (scrollX + dx >= mMaxLength) {//item的布局已经完全显示出来删除和置顶按钮了,没必要再向左边滑动了
                        mCurrentView.scrollTo(mMaxLength, 0);
                        return false;
                    }
                    mCurrentView.scrollBy(dx, 0);
                } else {
                    isDragging = true;
                }
                if (isCurrentItemMoving) {
                    lastX = x;
                    lastY = y;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!isCurrentItemMoving && !isDragging && mListener != null && Math.abs(lastX - x) < touchSlop) {//没有在移动中
                    //满足item的点击事件
                    mListener.OnItemClick(currentPosition);
                }
                int upScrollX = mCurrentView.getScrollX();
                int deltaX = 0;
                //对于滑动过程中的情况需要自动滑动到初始位置或者删除、置顶按钮显示的状态
                if (upScrollX < mMaxLength / 2) {
                    //mCurrentView.scrollTo(0, 0);//如果用scrollTo方法那么没有一个动画效果,在用户看来会不友好
                    deltaX = -upScrollX;
                    menuStatus = MENU_WILL_CLOSE;
                } else {
                    //mCurrentView.scrollTo(mMaxLength, 0);
                    deltaX = mMaxLength - upScrollX;
                    menuStatus = MENU_WILL_OPEN;
                }
                mScroller.startScroll(upScrollX, 0, deltaX, 0, 200);
                isDragging = false;
                isCurrentItemMoving = false;
                isStartScroll = true;
                //刷新界面
                invalidate();
                break;
        }
        lastX = x;
        lastY = y;
        return super.onTouchEvent(ev);
    }

    public void setActionListener(OnItemActionListener listener) {
        this.mListener = listener;
    }

    /**
     * 给左滑出来的布局设置需要显示的内容
     */
    public void setData(List<QQBean> data) {
        mDatas = data;
    }
}

之后是MainActivity中的代码实现:

package com.example.qqlistviewdemo;

import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private CustomListView mCustomListView;
    private List<String> mNameDatas;
    private List<QQBean> qqDataBeans;
    private CustomListViewAdapter adapter;

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

        mCustomListView = findViewById(R.id.listView);
        mNameDatas = new ArrayList<>(Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu", "tianqi", "heiba", "qinjiu", "hushi", "ashiyi", "bshier", "cshisan", "dshisi", "eshiwu", "fshiliu", "gshiqi", "hshiba", "ishijiu", "jershi"));
        adapter = new CustomListViewAdapter(this);
        mCustomListView.setActionListener(new OnItemActionListener() {
            @Override
            public void OnItemClick(int position) {
                Toast.makeText(MainActivity.this, "点击了第" + position + "条item", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void OnItemTop(int position) {
                QQBean qqBean = qqDataBeans.get(position);
                if (qqBean.isTop()) {
                    Collections.swap(qqDataBeans, position, qqBean.getOldPosition());
                } else {
                    Collections.swap(qqDataBeans, position, 0);
                }
                qqBean.setTop(!qqBean.isTop());
                adapter.setData(qqDataBeans);
            }

            @Override
            public void OnItemRead(int position) {
                QQBean qqBean = qqDataBeans.get(position);
                if (qqBean.isRead()) {
                    //TODO 取消显示消息条数的图标,此处不做赘述
                    Toast.makeText(MainActivity.this, "标为未读", Toast.LENGTH_SHORT).show();
                } else {
                    //TODO 显示消息条数的图标,此处不做赘述
                    Toast.makeText(MainActivity.this, "标为已读", Toast.LENGTH_SHORT).show();
                }
                qqBean.setRead(!qqBean.isRead());
                adapter.setData(qqDataBeans);
            }

            @Override
            public void OnItemDelete(int position) {
                qqDataBeans.remove(position);
                //更改oldPosition的值
                for (int i = 0; i < qqDataBeans.size(); i++) {
                    qqDataBeans.get(i).setOldPosition(i);
                }
                adapter.setData(qqDataBeans);
            }
        });
        mCustomListView.setAdapter(adapter);
        //造一些假数据
        qqDataBeans = new ArrayList<>();
        QQBean bean = null;
        for (int i = 0; i < mNameDatas.size(); i++) {
            bean = new QQBean();
            bean.setName(mNameDatas.get(i));
            bean.setContent("消息内容" + i);
            if (i == 0) {
                bean.setDate("2020-03-31" + (i < 10 && i > 0 ? "0" + i : ""));
            } else {
                bean.setDate("2020-04-" + (i < 10 ? "0" + i : i));
            }
            if (i % 3 == 0) {
                bean.setUserType(CustomListViewAdapter.NORMAL_USER);
            }
            if (i % 3 == 1) {
                bean.setUserType(CustomListViewAdapter.GROUP_USER);
            }
            if (i % 3 == 2) {
                bean.setUserType(CustomListViewAdapter.COMPANY_USER);
            }
            bean.setOldPosition(i);
            bean.setTop(false);
            bean.setDelete(false);
            bean.setRead(false);
            qqDataBeans.add(bean);
        }
        mCustomListView.setData(qqDataBeans);
        adapter.setData(qqDataBeans);
    }
}

删除按钮等点击事件的回调接口OnItemActionListener代码:

package com.example.qqlistviewdemo;

/**
 * 点击事件的回调接口
 */
public interface OnItemActionListener {
    void OnItemClick(int position);

    void OnItemTop(int position);

    void OnItemRead(int position);

    void OnItemDelete(int position);
}

activity_main.xml中的代码:

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

    <com.example.qqlistviewdemo.CustomListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

ListView的adapter代码CustomListViewAdapter:

package com.example.qqlistviewdemo;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义ListView的 仿QQ左滑删除列表的adapter
 */
public class CustomListViewAdapter extends BaseAdapter {

    public static final int NORMAL_USER = 0;//普通用户
    public static final int GROUP_USER = 1;//QQ群
    public static final int COMPANY_USER = 2;//企业号

    private Context mContext;
    private List<QQBean> mDatas;

    public CustomListViewAdapter(Context context) {
        mContext = context;
        mDatas = new ArrayList<>();
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_custom_listview, null);
            holder.btnDelete = convertView.findViewById(R.id.btn_delete);
            holder.btnTop = convertView.findViewById(R.id.btn_top);
            holder.btnRead = convertView.findViewById(R.id.btn_read);
            holder.tvName = convertView.findViewById(R.id.tv_name);
            holder.tvContent = convertView.findViewById(R.id.tv_content);
            holder.tvDate = convertView.findViewById(R.id.tv_date);
            holder.ivIcon = convertView.findViewById(R.id.iv_icon);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        QQBean bean = mDatas.get(position);
        //如果是获取的在线数据,最好判空
        holder.tvName.setText(bean.getName());
        holder.tvContent.setText(bean.getContent());
        holder.tvDate.setText(bean.getDate());
        holder.btnDelete.setText("删除");
        if (bean.isTop()) {
            convertView.setBackgroundColor(Color.GRAY);
            holder.btnTop.setText("取消置顶");
        } else {
            convertView.setBackgroundColor(Color.WHITE);
            holder.btnTop.setText("置顶聊天");
        }
        if (bean.isRead()) {
            holder.btnRead.setText("标为未读");
        } else {
            holder.btnRead.setText("标为已读");
        }
        holder.ivIcon.setImageResource(R.mipmap.ic_launcher_round);
        return convertView;
    }

    public void setData(List<QQBean> data) {
        mDatas.clear();
        mDatas.addAll(data);
        notifyDataSetChanged();
    }

    static class ViewHolder {
        TextView tvName;
        TextView tvContent;
        TextView tvDate;
        ImageView ivIcon;
        Button btnDelete;
        Button btnTop;
        Button btnRead;
    }
}

adapter的item布局item_custom_listview.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="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/linear_show"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:paddingStart="5dp">

        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:contentDescription="@null"
            android:scaleType="centerInside" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:orientation="vertical"
            android:paddingStart="5dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="25dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_name"
                    android:layout_width="0dp"
                    android:layout_height="25dp"
                    android:layout_weight="3"
                    android:gravity="center_vertical"
                    android:text="name"
                    android:textColor="#000"
                    android:textSize="20sp" />

                <TextView
                    android:id="@+id/tv_date"
                    android:layout_width="0dp"
                    android:layout_height="25dp"
                    android:layout_weight="1"
                    android:gravity="center"
                    android:text="2020-04-17"
                    android:textSize="14sp" />

            </LinearLayout>

            <TextView
                android:id="@+id/tv_content"
                android:layout_width="match_parent"
                android:layout_height="25dp"
                android:gravity="center_vertical"
                android:text="content"
                android:textSize="14sp" />

        </LinearLayout>

    </LinearLayout>

    <Button
        android:id="@+id/btn_top"
        android:layout_width="80dp"
        android:layout_height="50dp"
        android:background="#999"
        android:text="置顶聊天"
        android:textColor="#fff" />

    <Button
        android:id="@+id/btn_read"
        android:layout_width="80dp"
        android:layout_height="50dp"
        android:background="#f80"
        android:text="标为已读"
        android:textColor="#fff" />

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="80dp"
        android:layout_height="50dp"
        android:background="#f00"
        android:text="删除"
        android:textColor="#fff" />

</LinearLayout>

bean类代码QQBean:

package com.example.qqlistviewdemo;

public class QQBean {

    private boolean isTop;//是否置顶
    private boolean isDelete;//是否删除
    private boolean isRead;//是否置顶
    private int oldPosition;//记录置顶前item的position
    private int messageCount;//记录消息的条数
    private int userType;//用户类型 普通用户 0 显示删除、置顶和已读按钮;QQ群 1 显示删除、置顶按钮;企业号 2 显示删除按钮
    private String name;//内容
    private String imageUrl;//图片
    private String content;//显示的内容
    private String date;//日期

    public boolean isTop() {
        return isTop;
    }

    public void setTop(boolean top) {
        isTop = top;
    }

    public boolean isDelete() {
        return isDelete;
    }

    public void setDelete(boolean delete) {
        isDelete = delete;
    }

    public int getOldPosition() {
        return oldPosition;
    }

    public void setOldPosition(int oldPosition) {
        this.oldPosition = oldPosition;
    }

    public void setRead(boolean read) {
        isRead = read;
    }

    public int getMessageCount() {
        return messageCount;
    }

    public void setMessageCount(int messageCount) {
        this.messageCount = messageCount;
    }

    public int getUserType() {
        return userType;
    }

    public void setUserType(int userType) {
        this.userType = userType;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isRead() {
        return isRead;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}

到此仿QQ左滑删除ListView功能基本实现,主要通过本篇文章复习一下自定义View的实现方式。

参考文章:https://www.jb51.net/article/100149.htm

github代码所在地址:https://github.com/cainiaobukeyi/QQListViewDemo

如有疑问可以微信:cai-niao-bu-ke-yi; QQ:1125325256 留言 个人网站:www.sevenyoung.net(不日即将开启,欢迎大家访问)

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现 Android 仿QQ左滑显示删除按钮的方法是使用 RecyclerView 的 ItemTouchHelper 类,它提供了拖动和滑动 Item 的处理逻辑。具体实现步骤如下: 1. 在 RecyclerView 的 adapter 中,实现 ItemTouchHelper.Callback 接口,该接口中有三个方法:onMove()、onSwiped() 和 getMovementFlags()。 2. 在 getMovementFlags() 方法中,设置支持的滑动方向为左滑。 3. 在 onSwiped() 方法中,处理滑动事件,比如删除 Item。 4. 在 Item 的 ViewHolder 中,添加一个删除按钮,并设置其可见性为不可见。 5. 在 ItemTouchHelper.Callback 的 onChildDraw() 方法中,处理左滑时的视觉效果,比如将删除按钮设置为可见,实现左滑删除的效果。 6. 在 RecyclerView 的 ItemDecoration 中,设置左滑时的背景颜色和阴影效果,使左滑效果更加美观。 代码示例: ```java public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements ItemTouchHelper.Callback { private List<String> mData; @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int swipeFlags = ItemTouchHelper.LEFT; return makeMovementFlags(0, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { // 拖动事件 return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { // 左滑事件 int position = viewHolder.getAdapterPosition(); mData.remove(position); notifyItemRemoved(position); } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { // 滑动时的视觉效果 if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { View itemView = viewHolder.itemView; int buttonWidth = itemView.getHeight(); Paint paint = new Paint(); paint.setColor(Color.parseColor("#D32F2F")); RectF background = new RectF(itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); c.drawRect(background, paint); Drawable icon = ContextCompat.getDrawable(mContext, R.drawable.delete_icon); int intrinsicWidth = icon.getIntrinsicWidth(); int intrinsicHeight = icon.getIntrinsicHeight(); int iconTop = itemView.getTop() + (itemView.getHeight() - intrinsicHeight) / 2; int iconMargin = (itemView.getHeight() - intrinsicHeight) / 2; int iconLeft = itemView.getRight() - iconMargin - intrinsicWidth; int iconRight = itemView.getRight() - iconMargin; int iconBottom = iconTop + intrinsicHeight; icon.setBounds(iconLeft, iconTop, iconRight, iconBottom); icon.draw(c); } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } static class ViewHolder extends RecyclerView.ViewHolder { Button mDeleteButton; public ViewHolder(View itemView) { super(itemView); mDeleteButton = itemView.findViewById(R.id.delete_button); mDeleteButton.setVisibility(View.GONE); } } } ``` 以上是一个简单的实现 Android 仿QQ左滑显示删除按钮的示例代码,可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值