教你实现最简单的QQ消息item侧滑菜单

这次跟大家介绍怎么简单的实现类似QQ消息Item的左右滑动菜单的实现。首先见效果图先:

show.gif
这就实现了ListView或RecyclerView加载的item的View实现侧滑菜单。至于这么实现,很简单就是通过继承HorizontalScrollView,再判断滑动的距离以滑到对应的View或菜单。具体如下:
首先,在item的界面布局方面如下:

<?xml version="1.0" encoding="utf-8"?>
<com.example.jack.listviewitemscroll.widget.ScrollListViewItem
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <include layout="@layout/leftbutton"/>
        <include layout="@layout/context_view"/>
        <include layout="@layout/rightbutton"/>
    </LinearLayout>
</com.example.jack.listviewitemscroll.widget.ScrollListViewItem>

就是ScrollListViewItem包裹着LinearLayout里面的三个View,分别是左菜单,内容和右菜单对应的View。最为重点的就是ScrollListViewItem这个类,这就是我们继承HorizontalScrollView类所自定义的控制菜单滑动的类。
这个类的源码如下:

public class ScrollListViewItem extends HorizontalScrollView{

    private static int ScreenWidth=0;
    private static int MenuWidth=0;
    private static int HalfMenuWidth=0;
    private boolean  operateLeft=false;
    private boolean operateRight=false;
    private boolean once;

    ViewGroup left;
    ViewGroup centre;
    ViewGroup right;

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

    public ScrollListViewItem(Context context, AttributeSet attrs) {
        super(context, attrs,0);
    }

    public ScrollListViewItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr,0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       if(!once){
           LinearLayout linearLayout=(LinearLayout)getChildAt(0);
           left=(ViewGroup)linearLayout.getChildAt(0);
           centre=(ViewGroup)linearLayout.getChildAt(1);
           right=(ViewGroup)linearLayout.getChildAt(2);

           ScreenWidth= ScreenUtils.getScreenWidth(getContext());
           MenuWidth=ScreenWidth/4;
           HalfMenuWidth=MenuWidth/2;

           left.getLayoutParams().width=MenuWidth;
           centre.getLayoutParams().width=ScreenWidth;
           right.getLayoutParams().width=MenuWidth;
       }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed){
            this.scrollTo(MenuWidth,0);
            once=true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch(ev.getAction()){
            case MotionEvent.ACTION_UP:
                //在左侧
                if(operateLeft){
                    if(getScrollX()<HalfMenuWidth){
                        //滑到左最末尾
                        this.scrollTo(0, 0);
                    }else if(getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth){
                        //滑到中间
                        this.scrollTo(MenuWidth, 0);
                    }else{
                        this.scrollTo(MenuWidth * 2, 0);
                    }
                }
                //向右侧
                if(operateRight){
                    if(getScrollX()>MenuWidth+HalfMenuWidth){
                        //滑到最右
                        this.scrollTo(MenuWidth + MenuWidth, 0);
                    }else if(getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth){
                        //滑到中间
                        this.scrollTo(MenuWidth, 0);
                    }else{
                        //滑到最左
                        this.scrollTo(0, 0);
                    }
                }
                return true;
        }
        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if(l>MenuWidth){
            operateLeft=false;
            operateRight=true;
        }else{
            operateLeft=true;
            operateRight=false;
        }
    }
}

在onMeasure()这个自定义View的测量方法里,我们首先拿到左菜单,内容,右菜单所对用的view,即left,centre,right这三个View,然后获取屏幕的宽度,动态设定菜单的宽度为屏幕宽度的四分之一,而内容的宽度就是整个屏幕的宽度,即

 left.getLayoutParams().width=MenuWidth;
 centre.getLayoutParams().width=ScreenWidth;
 right.getLayoutParams().width=MenuWidth;

然后我们在onLayout()方法里对这三个View进行定位,即让他滑到内容的那个View。

然后回调onScrollChanged(int l, int t, int oldl, int oldt)方法,当l大于菜单宽度时是右侧,当l小于菜单宽度时是右侧。(注:l是屏幕最右边到整个View最右边的距离)

其次就是最重要的onTouchEvent(MotionEvent ev)方法了。(注:是屏幕最右边到整个View最右边的距离).当operateLeft==true的时候,滑动在操作在左侧,当getScrollX()<HalfMenuWidth,即在最左向右滑还不到菜单的二分之一宽度时,恢复原状,即this.scrollTo(0, 0);,当getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth,即最左向右滑大于菜单的二分之一宽度但却小于左菜单加右菜单一半的宽度,所以只能滑到内容区域,即this.scrollTo(MenuWidth, 0);,这两种情况除外都会滑到最后边的菜单,所以this.scrollTo(MenuWidth * 2, 0);

同样的道理,当operateRight==true时,getScrollX()>MenuWidth+HalfMenuWidth时,即在最右菜单但滑动的距离小于菜单宽度的一半,所以只能恢复原状即this.scrollTo(MenuWidth + MenuWidth, 0);,当getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth时,即滑动大于菜单一半但是却小于左菜单加右菜单一半的宽度,所以是内容区域,即滑动 this.scrollTo(MenuWidth, 0);,除这两种情况都是要滑到最左边的菜单,即 this.scrollTo(0, 0);。到此整个流程就讲完了。

最后奉上源码

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现Android侧滑菜单有多种方式,其中一种比较常见的实现方式是使用DrawerLayout和NavigationView。 步骤如下: 1. 在XML布局文件中添加DrawerLayout和NavigationView,其中NavigationView中可以添加菜单项。 ``` <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 主界面内容 --> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 侧滑菜单 --> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header" app:menu="@menu/nav_menu" /> </android.support.v4.widget.DrawerLayout> ``` 2. 在Activity中设置DrawerLayout和NavigationView的监听器,并在onOptionsItemSelected方法中处理菜单项点击事件。 ``` public class MainActivity extends AppCompatActivity { private DrawerLayout mDrawerLayout; private NavigationView mNavigationView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDrawerLayout = findViewById(R.id.drawer_layout); mNavigationView = findViewById(R.id.navigation_view); mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { // 处理菜单项点击事件 return false; } }); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mDrawerLayout.addDrawerListener(toggle); toggle.syncState(); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { mDrawerLayout.openDrawer(GravityCompat.START); return true; } return super.onOptionsItemSelected(item); } } ``` 3. 在NavigationView中添加菜单项,并为菜单项设置图标和标题。 ``` <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_home" android:icon="@drawable/ic_home" android:title="Home" /> <item android:id="@+id/nav_gallery" android:icon="@drawable/ic_gallery" android:title="Gallery" /> <item android:id="@+id/nav_slideshow" android:icon="@drawable/ic_slideshow" android:title="Slideshow" /> </group> </menu> ``` 至此,实现了一个简单Android侧滑菜单。如果要实现仿QQ侧滑删除功能,可以在ListView或RecyclerView中添加滑动删除的功能,并在删除时更新侧滑菜单中的未读消息数等信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值