SwipeMenuListView(左滑出菜单)

这篇博客介绍了如何在Android Studio(AS)中使用SwipeMenuListView控件创建左滑菜单,展示了效果,并提醒注意设置合适的item高度以避免菜单显示不全的问题。同时,文章提到了源码中存在一个bug,当左滑打开菜单后,滑动其他条目到顶部或底部时会出现异常行为。作者分析了问题出现在SwipeMenuListView的onTouchEvent方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在https://github.com/中使用一个SwipeMenuListView(左滑出菜单)的控件,先上效果图:


感觉还挺好用,这里记录一下使用方法:

public class SwipeMenuListView extends ListView {
     //源码省略,请自行到github下载
}

可以看出直接使用这个控件即可,在xml中使用(记得把源码导入):

<RelativeLayout 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">

    <com.baoyz.swipemenulistview.SwipeMenuListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
接下来是在主函数中的使用方法,这里就是在每一条listview中去添加右边的菜单:

 mListView = (SwipeMenuListView) findViewById(R.id.listView);
        mListView.setAdapter(mAdapter);
        initSwipeMenu();
        initListener();
重要的方法就是 initSwipeMenu() initLisener() ,如下:

    public void initSwipeMenu(){

        // step 1. create a MenuCreator
        SwipeMenuCreator creator = new SwipeMenuCreator() {
            @Override
            public void create(SwipeMenu menu) {

                // create "share" item
                SwipeMenuItem shareItem = new SwipeMenuItem(getApplicationContext());
                // set item background
                shareItem.setBackground(getResources().getDrawable(R.color.blue_color));
                // set item width
                shareItem.setWidth(dp2px(80));  //这里设定宽度为80,可以改
                // set item title
                shareItem.setTitle("share");
                // set item title fontsize
                shareItem.setTitleSize(18);
                //set icon
                shareItem.setIcon(R.drawable.ic_action_share);
                // set item title font color
                shareItem.setTitleColor(Color.WHITE);
                // add to menu
                menu.addMenuItem(shareItem);
                // create "delete" item
                SwipeMenuItem openItem = new SwipeMenuItem(getApplicationContext());
                // set item background
                openItem.setBackground(getResources().getDrawable(R.color.red_color));
                // set item width
                openItem.setWidth(dp2px(80));//这里设定宽度为80,可以改

                // set item title
                openItem.setTitle("delete");
                // set item title fontsize
                openItem.setTitleSize(18);
                //set icon
                openItem.setIcon(R.drawable.ic_action_discard);
                // set item title font color
                openItem.setTitleColor(Color.WHITE);
                // add to menu
                menu.addMenuItem(openItem);
            }
        };
        // set creator
        mListView.setMenuCreator(creator);
        int count = mAppList.size();
        mListView.setTotalItemNum(count);
    }
    private void initListener(){

        // step 2. listener item click event
        mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                ApplicationInfo item = mAppList.get(position);
                switch (index) {
                    case 1:
                        // open
//                        open(item);
                        mAppList.remove(position);
                        mAdapter.notifyDataSetChanged();
                        break;
                }
                return false;
            }
        });

        // set SwipeListener
        mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {

            @Override
            public void onSwipeStart(int position) {
                // swipe start
            }

            @Override
            public void onSwipeEnd(int position) {
                // swipe end
            }
        });

        // set MenuStateChangeListener
        mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
            @Override
            public void onMenuOpen(int position) {
            }

            @Override
            public void onMenuClose(int position) {
            }
        });

        // other setting
//		listView.setCloseInterpolator(new BounceInterpolator());

        // test item long click
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view,
                                           int position, long id) {
                Toast.makeText(getApplicationContext(), position + " long click", Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }

以上就是使用方法,注意一点,你的item的高度要控制好,因为如果高度不够的话左滑显示的菜单会有显示不全的问题。最后说源码中的一个小bug,当你左滑出菜单后,如果此时竖向滑动其他条目到顶端或底端的时候会这样:


看了源码发现是如果滑动其他条目的时候,在SwipeMenuListView中的onTouchEvent方法中

MotionEvent.ACTION_MOVE
这了设置了break:

if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {   break;     }
那我们可以最简单的方法就是把这段代码注释掉就不会有这种划出界的现象了,如果说怕有问题,也可以自己加个标志位去判断,如下方法:
boolean letViewDispear  //用这个标志位

boolean letViewDispear = false; //此标志用于有菜单的时候
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //在拦截处处理,在滑动设置了点击事件的地方也能swip,点击时又不能影响原来的点击事件
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mDownX = ev.getX();
                mDownY = ev.getY();
                boolean handled = super.onInterceptTouchEvent(ev);
                mTouchState = TOUCH_STATE_NONE;
                mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
                View view = getChildAt(mTouchPosition - getFirstVisiblePosition());

                //只在空的时候赋值 以免每次触摸都赋值,会有多个open状态
                if (view instanceof SwipeMenuLayout) {
                    //如果有打开了 就拦截.
                    if (mTouchView != null && mTouchView.isOpen()) {
                        if(!inRangeOfView(mTouchView.getMenuView(), ev)){  //false 表示不在,true表示在
                             letViewDispear = true;    //有菜单时设为true
                            return true;  //true表示不往下执行了,false表示抛给父类去处理
                        }

                    }
                    mTouchView = (SwipeMenuLayout) view;
                    mTouchView.setSwipeDirection(mDirection);
                }
                //如果摸在另外个view
                if (mTouchView != null && mTouchView.isOpen() && view != mTouchView) {
                    handled = true;  //触摸在别的view就handle
                }

                if (mTouchView != null) {
                    mTouchView.onSwipe(ev);
                }
                return handled;
            case MotionEvent.ACTION_MOVE:
                //略,可以直接把这里的上述代码注释,也可以使用我们自己定义的标志位
            case MotionEvent.ACTION_UP:
                //略
        }
        return super.onInterceptTouchEvent(ev);
    }

然后在OnTouchEvent方法MotionEvent.ACTION_MOVE中根据这个改上面的代码:

if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {
                    //TODO 这个判断不能break,原因是break会导致ActionMove不往下执行,影响ActionUp的操作,最终导致滑动到顶端或底端出现超界现象
                    if(!letViewDispear){
                        break;
                    }else {
                        letViewDispear = false;
                    }
                }
好了,这样就不会因为break而影响到接下来MotionEvent.ACTION_UPd的处理了,以上就是对这个控件的学习心得,关于如何导入含源代码的第三方库类,可以参考文章:  

AS中第三方库类导入和问题




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值