欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android使用DrawerLayout实现仿QQ双向侧滑菜单

程序员文章站 2023-12-20 10:00:22
1、概述 之前写了一个android 高仿 qq5.0 侧滑菜单效果 自定义控件来袭 ,恰逢qq5.2又加了一个右侧菜单,刚好看了下drawerlayout,一方面官...

1、概述

之前写了一个android 高仿 qq5.0 侧滑菜单效果 自定义控件来袭 ,恰逢qq5.2又加了一个右侧菜单,刚好看了下drawerlayout,一方面官方的东西,我都比较感兴趣;另一方面,这玩意用起来的确方便,于是简单写了个demo,高仿qq5.2双向侧滑,分享给大家。

首先看看效果图:

Android使用DrawerLayout实现仿QQ双向侧滑菜单

drawerlayout用起来真的很方便,下面一起看看用法~

2、drawerlayout的使用

直接将drawerlayout作为根布局,然后其内部第一个view为内容区域,第二个view为左侧菜单,第三个view为右侧侧滑菜单,当前第三个是可选的。

第一个view的宽高应当设置为match_parent,当然了,这也理所当然。

第二、三个view需要设置android:layout_gravity="left",和android:layout_gravity="right"且一搬高度设置为match_parent,宽度为固定值,即侧滑菜单的宽度。

按照上面的描述写个布局文件,然后设置给activity就添加好了左右侧滑了,是不是很简单~~~

比如我们的布局文件:

<android.support.v4.widget.drawerlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  android:id="@+id/id_drawerlayout" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:background="@drawable/img_frame_background" > 
 
  <relativelayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@drawable/qq" > 
 
    <button 
      android:layout_width="40dp" 
      android:layout_height="30dp" 
       android:layout_margintop="10dp" 
      android:layout_alignparentright="true" 
      android:background="@drawable/youce" 
      android:onclick="openrightmenu" /> 
  </relativelayout> 
 
  <fragment 
    android:id="@+id/id_left_menu" 
    android:name="com.zhy.demo_zhy_17_drawerlayout.menuleftfragment" 
    android:layout_width="200dp" 
    android:layout_height="match_parent" 
    android:layout_gravity="left" 
    android:tag="left" /> 
 
  <fragment 
    android:id="@+id/id_right_menu" 
    android:name="com.zhy.demo_zhy_17_drawerlayout.menurightfragment" 
    android:layout_width="100dp" 
    android:layout_height="match_parent" 
    android:layout_gravity="right" 
    android:tag="right" /> 
 
</android.support.v4.widget.drawerlayout> 

这里我们的主内容区域为relativelayout

菜单用的两个fragment,左侧为200dp,右侧为100dp;

好了,看了我们的布局文件,接下来看下我们的详细代码。

3、代码是最好的老师

1、menuleftfragment

package com.zhy.demo_zhy_17_drawerlayout; 
 
import android.os.bundle; 
import android.support.v4.app.fragment; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
 
public class menuleftfragment extends fragment 
{ 
 
  @override 
  public view oncreateview(layoutinflater inflater, viewgroup container, 
      bundle savedinstancestate) 
  { 
    return inflater.inflate(r.layout.layout_menu, container, false); 
  } 
} 

对应的布局文件:

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:background="#00000000" > 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centervertical="true" 
    android:orientation="vertical" > 
 
    <relativelayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" > 
 
      <imageview 
        android:id="@+id/one" 
        android:layout_width="50dp" 
        android:layout_height="50dp" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_margintop="20dp" 
        android:src="@drawable/img_1" /> 
 
      <textview 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_torightof="@id/one" 
        android:text="第1个item" 
        android:textcolor="#f0f0f0" 
        android:textsize="20sp" /> 
    </relativelayout> 
 
    <relativelayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" > 
 
      <imageview 
        android:id="@+id/two" 
        android:layout_width="50dp" 
        android:layout_height="50dp" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_margintop="20dp" 
        android:src="@drawable/img_2" /> 
 
      <textview 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_torightof="@id/two" 
        android:text="第2个item" 
        android:textcolor="#f0f0f0" 
        android:textsize="20sp" /> 
    </relativelayout> 
 
    <relativelayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" > 
 
      <imageview 
        android:id="@+id/three" 
        android:layout_width="50dp" 
        android:layout_height="50dp" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_margintop="20dp" 
        android:src="@drawable/img_3" /> 
 
      <textview 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_torightof="@id/three" 
        android:text="第3个item" 
        android:textcolor="#f0f0f0" 
        android:textsize="20sp" /> 
    </relativelayout> 
 
    <relativelayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" > 
 
      <imageview 
        android:id="@+id/four" 
        android:layout_width="50dp" 
        android:layout_height="50dp" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_margintop="20dp" 
        android:src="@drawable/img_4" /> 
 
      <textview 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_torightof="@id/four" 
        android:text="第4个item" 
        android:textcolor="#f0f0f0" 
        android:textsize="20sp" /> 
    </relativelayout> 
 
    <relativelayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" > 
 
      <imageview 
        android:id="@+id/five" 
        android:layout_width="50dp" 
        android:layout_height="50dp" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_margintop="20dp" 
        android:src="@drawable/img_5" /> 
 
      <textview 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_centervertical="true" 
        android:layout_marginleft="20dp" 
        android:layout_torightof="@id/five" 
        android:text="第5个item" 
        android:textcolor="#f0f0f0" 
        android:textsize="20sp" /> 
    </relativelayout> 
  </linearlayout> 
 
</relativelayout> 

其实就是堆出来的布局~~没撒意思~

2、menurightfragment

package com.zhy.demo_zhy_17_drawerlayout; 
 
import android.os.bundle; 
import android.support.v4.app.fragment; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
 
public class menurightfragment extends fragment 
{ 
 
  @override 
  public view oncreateview(layoutinflater inflater, viewgroup container, 
      bundle savedinstancestate) 
  { 
    return inflater.inflate(r.layout.menu_layout_right, container, false); 
  } 
} 

对应布局文件:

<?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="match_parent" 
  android:gravity="center_vertical" 
  android:orientation="vertical" > 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centervertical="true" 
    android:layout_gravity="center_vertical" 
    android:layout_marginbottom="20dp" 
    android:orientation="vertical" > 
 
    <imageview 
      android:layout_width="60dp" 
      android:layout_height="60dp" 
      android:layout_gravity="center" 
      android:src="@drawable/wode" /> 
 
    <textview 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:gravity="center" 
      android:text="扫一扫" 
      android:textcolor="#ffffff" /> 
  </linearlayout> 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centervertical="true" 
    android:layout_gravity="center_vertical" 
    android:layout_marginbottom="20dp" 
    android:orientation="vertical" > 
 
    <imageview 
      android:layout_width="60dp" 
      android:layout_height="60dp" 
      android:layout_gravity="center" 
      android:src="@drawable/saoma" /> 
 
    <textview 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:gravity="center" 
      android:text="讨论组" 
      android:textcolor="#ffffff" /> 
  </linearlayout> 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centervertical="true" 
    android:layout_gravity="center_vertical" 
    android:layout_marginbottom="20dp" 
    android:orientation="vertical" > 
 
    <imageview 
      android:layout_width="60dp" 
      android:layout_height="60dp" 
      android:layout_gravity="center" 
      android:src="@drawable/wode" /> 
 
    <textview 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:gravity="center" 
      android:text="扫一扫" 
      android:textcolor="#ffffff" /> 
  </linearlayout> 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centervertical="true" 
    android:layout_gravity="center_vertical" 
    android:layout_marginbottom="20dp" 
    android:orientation="vertical" > 
 
    <imageview 
      android:layout_width="60dp" 
      android:layout_height="60dp" 
      android:layout_gravity="center" 
      android:src="@drawable/saoma" /> 
 
    <textview 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:gravity="center" 
      android:text="讨论组" 
      android:textcolor="#ffffff" /> 
  </linearlayout> 
 
</linearlayout> 

依旧很简单,除了图标比较难找以外~~

3、mainactivity
mainactivity的布局文件已经贴过了~~

package com.zhy.demo_zhy_17_drawerlayout; 
 
import android.os.bundle; 
import android.support.v4.app.fragmentactivity; 
import android.support.v4.widget.drawerlayout; 
import android.support.v4.widget.drawerlayout.drawerlistener; 
import android.view.gravity; 
import android.view.view; 
import android.view.window; 
 
import com.nineoldandroids.view.viewhelper; 
 
public class mainactivity extends fragmentactivity 
{ 
 
  private drawerlayout mdrawerlayout; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) 
  { 
    super.oncreate(savedinstancestate); 
    requestwindowfeature(window.feature_no_title); 
    setcontentview(r.layout.activity_main); 
 
    initview(); 
    initevents(); 
 
  } 
 
  public void openrightmenu(view view) 
  { 
    mdrawerlayout.opendrawer(gravity.right); 
    mdrawerlayout.setdrawerlockmode(drawerlayout.lock_mode_unlocked, 
        gravity.right); 
  } 
 
  private void initevents() 
  { 
    mdrawerlayout.setdrawerlistener(new drawerlistener() 
    { 
      @override 
      public void ondrawerstatechanged(int newstate) 
      { 
      } 
 
      @override 
      public void ondrawerslide(view drawerview, float slideoffset) 
      { 
        view mcontent = mdrawerlayout.getchildat(0); 
        view mmenu = drawerview; 
        float scale = 1 - slideoffset; 
        float rightscale = 0.8f + scale * 0.2f; 
 
        if (drawerview.gettag().equals("left")) 
        { 
 
          float leftscale = 1 - 0.3f * scale; 
 
          viewhelper.setscalex(mmenu, leftscale); 
          viewhelper.setscaley(mmenu, leftscale); 
          viewhelper.setalpha(mmenu, 0.6f + 0.4f * (1 - scale)); 
          viewhelper.settranslationx(mcontent, 
              mmenu.getmeasuredwidth() * (1 - scale)); 
          viewhelper.setpivotx(mcontent, 0); 
          viewhelper.setpivoty(mcontent, 
              mcontent.getmeasuredheight() / 2); 
          mcontent.invalidate(); 
          viewhelper.setscalex(mcontent, rightscale); 
          viewhelper.setscaley(mcontent, rightscale); 
        } else 
        { 
          viewhelper.settranslationx(mcontent, 
              -mmenu.getmeasuredwidth() * slideoffset); 
          viewhelper.setpivotx(mcontent, mcontent.getmeasuredwidth()); 
          viewhelper.setpivoty(mcontent, 
              mcontent.getmeasuredheight() / 2); 
          mcontent.invalidate(); 
          viewhelper.setscalex(mcontent, rightscale); 
          viewhelper.setscaley(mcontent, rightscale); 
        } 
 
      } 
 
      @override 
      public void ondraweropened(view drawerview) 
      { 
      } 
 
      @override 
      public void ondrawerclosed(view drawerview) 
      { 
        mdrawerlayout.setdrawerlockmode( 
            drawerlayout.lock_mode_locked_closed, gravity.right); 
      } 
    }); 
  } 
 
  private void initview() 
  { 
    mdrawerlayout = (drawerlayout) findviewbyid(r.id.id_drawerlayout); 
    mdrawerlayout.setdrawerlockmode(drawerlayout.lock_mode_locked_closed, 
        gravity.right); 
  } 
 
} 

嗯,代码基本没什么注释~~维撒呢?是因为的确没什么好注释的。

提几点:

1、为了模拟qq的右侧菜单需要点击才能出现,所以在初始化drawerlayout的时候,使用了mdrawerlayout.setdrawerlockmode(drawerlayout.lock_mode_locked_closed,gravity.right);意思是只有编程才能将其弹出。

然后在弹出以后,需要让手势可以滑动回去,所以在openrightmenu中又编写了:

mdrawerlayout.setdrawerlockmode(drawerlayout.lock_mode_unlocked,gravity.right); unlock了一下。

最后在ondrawerclosed回调中,继续设置mdrawerlayout.setdrawerlockmode(drawerlayout.lock_mode_locked_closed,gravity.right);

2、动画效果

动画用了nineoldandroids,关于动画各种偏移量、缩放比例的计算请参考android 高仿 qq5.0 侧滑菜单效果 自定义控件来袭 基本是一致的,唯一的不同的地方,给content设置了viewhelper.settranslationx(mcontent, mmenu.getmeasuredwidth() * (1 - scale));让content在菜单的右侧,默认情况下menu在菜单之上,所以我们根据菜单划出的距离给content设置x方向的偏移量。

好了,其实看到可以这么做,基本上任何的侧滑菜单效果都能写出来了。有兴趣的话,可以拿drawerlayout实现这篇博客的所有效果:android 实现形态各异的双向侧滑菜单 自定义控件来袭 。

3、setdrawerlistener

通过代码也能看出来,可以使用setdrawerlistener监听菜单的打开与关闭等等。这里对于当前操作是哪个菜单的判断是通过tag判断的,我觉得使用gravity应该也能判断出来~~

好了,没撒了,由于drawerlayout默认只能从边界划出菜单,但是qq划出菜单的手势区域比较大,大家有兴趣,可以重写activity的ontouchevent,在里面判断,如果是左右滑动手势神马的,弹出菜单,应该不麻烦~~~

上一篇:

下一篇: