Android自定义ListView实现侧滑子菜单

这篇博客介绍了如何在Android中实现ListView的侧滑子菜单功能。通过自定义ListView和ItemView,博主详细讲解了如何处理触摸事件,以及如何确保ItemView的宽度与ListView相匹配,以达到侧滑效果。内容包括自定义ListView、ItemView的实现细节以及所需注意事项。

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

惯例,先放效果图,DEMO在最后



想当年博主刚接触Android的时候,看到这个效果心中只有膜拜啊,如果慢慢的自己水平也上来了,就把当年的一个想法给圆满了吧。

好了,废话不多说,先总结总结这个效果:

  • 首先是需要自定义ListView,这点是必须的,然后在ListView的onTouchEvent方法中对事件进行处理
  • 普通的Item的话,是没办法实现这样侧滑的,即使你塞一个HorizontalScrollView进去都不行,所以也必须自定义一个ItemView实现左右侧滑
  • 由于ListView的layout_width不一定是MATCH_PARENT,也可能是定值比如300dp,这个时候我们就需要建立一种机制来保证ItemView的宽度和ListView的宽度匹配,毕竟ItemView包含了两个View,一个是正文的ContentView,一个是菜单的MenuView。
首先我从自定义ListView开始讲起,这个ListView需要完成两件事:事件分发和高度匹配。首先来看高度匹配:
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        //宽度适配,改变ItemView的宽度
        SlideItemView.Width = width;
        for(int i = 0; i < getChildCount(); i++){
            SlideItemView item = (SlideItemView) getChildAt(i);
            item.resetWidth();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

这个方法并没有什么难度,得到了ListView的宽度,并且将所有在内存中的ItemView的宽度进行重设。这一步是非常必要的,上面也说了,因为你并不知道实际ListView的宽度,那么还谈什么左右滑动。SlideItemView的resetWidth方法我们放在后面讲解。这里就大概了解一下。
然后是ListView的事件分发,这里就比较重要了:
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        float dx = 0;
        float dy = 0;
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mTouchX = ev.getX();
                mTouchY = ev.getY();
                mMoveX = ev.getX();
                mMoveY = ev.getY();
                mTouchPosition = pointToPosition((int)ev.getX(), (int)ev.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                dx = ev.getX() - mMoveX;
                dy = ev.getY() - mMoveY;
                if(Math.abs(dx) > Math.abs(dy)){
                    //根据坐标点得到索引值
                    int position = pointToPosition((int)ev.getX(), (int)ev.getY());
                    if(mTouchPosition != ListView.INVALID_POSITION && position == mTouchPosition){
                        //得到内存中真实的Item
                        SlideItemView itemView = (SlideItemView) getChildAt(position - getFirstVisiblePosition());
                        itemView.scroll((int) dx);
                    }
                }
                mMoveX = ev.getX();
                mMoveY = ev.getY();
                break;
            case MotionEvent.ACTION_UP:
                dx = ev.getX() - mTouchX;
                dy = ev.getY() - mTouchY;
                if(Math.abs(dx) > Math.abs(dy) && Math.abs(dx) >= mTouchSlop){
                    int position = pointToPosition((int)ev.getX(), (int)ev.getY());
                    if(mTouchPosition != ListView.INVALID_POSITION && position == mTouchPosition){
                        //得到真正在内存中的Item
                        SlideItemView itemView = (SlideItemView) getChildAt(position - getFirstVisiblePosition());
                        //根据当前scrollX以及dx判断是否显示正文内容
                        if (itemView.shouldShowContent((int) dx)){
                            itemView.showContent();
                        }else{
                            itemView.showMenu();
                 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值