Android——自带侧滑菜单DrawerLayout的使用方法

DrawerLayout介绍

1、在Android的support库中增加了一个专门用于创建侧滑菜单的组件DrawerLayout,接下来我们就讲解一下怎样使用这个原生的组件创建一个仿推酷的应用

2、先来看看使用DrawerLayout的步骤:

①在布局文件中添加<android.support.v4.widget.DrawerLayout> 根元素

②在这个根元素中首先添加一个 内容视图组件,比如:我们添加一个容器

③再在这个根元素中添加侧滑菜单视图组件,一般来说就是一个ListView组件

④为ListView设定Adapter,和点击事件监听器

⑤为DrawerLayout添加 开、关 状态监听器

3、只要遵循上面的几步就能够完成一个侧滑菜单的创建,非常的简单,下面我们就通过模仿推酷客户端,一步一步的说明怎样创建侧滑菜单

效果示例图

在这里插入图片描述
在这里插入图片描述

功能描述

1、打开应用的时候,主界面如图1,ActionBar没有显示应用图标,只显示“推酷”两个字

2、ActionBar右边有一个绿色的图标是一个action菜单,当我们打开侧滑菜单的时候这个菜单图标就会隐藏,如图1
3、当我们点击了侧滑菜单中的某项时,ActionBar中的标题内容显示为当前选中的项目的标题

4、同时,如果我们已经选中了某一项,达到了图3所示的状态,这时我们在打开侧滑菜单,这时ActionBar中的标题内容改为“推酷”,也就是说,当侧滑菜单给关闭的时候,ActionBar中的标题是选中的项目的标题,当侧滑菜单处于打开状态的时候,ActionBar上的标题显示为全局的“推酷”,同事那个绿色的action菜单图标被隐藏

5、当侧滑菜单处于打开状态的时候,如果我么单击了手机上的“返回”物理按键的话,侧滑菜单关闭

创建步骤

步骤一、在主布局文件中创建DrawerLayout根元素布局——avtivity_main.xml文件

<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">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/content"/>
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="#33333333"
        android:dividerHeight="0dp"
        android:background="#ffeeeeee"
        android:scrollbars="none"/>
</android.support.v4.widget.DrawerLayout>

注意事项:
1、必须指定菜单视图组件ListView必须指定 android:layout_gravity属性,当属性值设为left的话侧滑菜单位于左边,否则位于右面,由于有的语言是从右到左写,那么只要指定属性值为 start 的话,android 会自行将侧滑菜单放在书写起始的一边
2、android:layout_width 指定了侧滑菜单的宽度,但是不能够超过320dp,否则会覆盖整个视图,就不好看了
3、必须先放内容视图的控件,之后放侧滑菜单视图控件

步骤二:创建侧滑菜单ListView的Adapter——DrawerAdapter.java

DrawerAdapter.java文件
package com.example.navigaterdrawer;

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

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

/**定义菜单项类*/
class TuiCoolMenuItem {
    String menuTitle ;
    int menuIcon ;
    
    //构造方法
    public TuiCoolMenuItem(String menuTitle , int menuIcon ){
        this.menuTitle = menuTitle ;
        this.menuIcon = menuIcon ;
    }
    
}
/**自定义设置侧滑菜单ListView的Adapter*/
public class DrawerAdapter extends BaseAdapter{
    
    //存储侧滑菜单中的各项的数据
    List<TuiCoolMenuItem> MenuItems = new ArrayList<TuiCoolMenuItem>( ) ;
    //构造方法中传过来的activity
    Context context ;
    
    //构造方法
    public DrawerAdapter( Context context ){
        
        this.context = context ;
        
        MenuItems.add(new TuiCoolMenuItem("", R.drawable.peng)) ;
        MenuItems.add(new TuiCoolMenuItem("推荐", R.drawable.advise)) ;
        MenuItems.add(new TuiCoolMenuItem("发现", R.drawable.find)) ;
        MenuItems.add(new TuiCoolMenuItem("主题", R.drawable.theme)) ;
        MenuItems.add(new TuiCoolMenuItem("站点", R.drawable.point)) ;
        MenuItems.add(new TuiCoolMenuItem("搜索", R.drawable.search)) ;
        MenuItems.add(new TuiCoolMenuItem("离线", R.drawable.leave)) ;
        MenuItems.add(new TuiCoolMenuItem("设置", R.drawable.set)) ;
    }

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

    }

    @Override
    public TuiCoolMenuItem getItem(int position) {
        
        return MenuItems.get(position) ;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        
        View view = convertView ;
        if(view == null){
            view =LayoutInflater.from(context).inflate(R.layout.menudrawer_item, parent, false);
            ((TextView) view).setText(getItem(position).menuTitle) ;
            ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(getItem(position).menuIcon, 0, 0, 0) ;
        }
        return view ;
    }

}
menudrawer_item.xml文件
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/item_style">
    
</TextView>
styles.xml文件
<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>
    <style name="item_style">
        <item name="android:textAppearance">?android:attr/textAppearance</item>
        <item name="android:textSize">18sp</item>
        <item name="android:paddingLeft">16dp</item>
        <item name="android:paddingRight">32dp</item>
        <item name="android:paddingTop">10dp</item>
        <item name="android:paddingBottom">10dp</item>
        <item name="android:drawablePadding">16dp</item>        
        <item name="android:gravity">center_vertical</item>
    </style>

</resources>

步骤三:主Activity文件——MainActivity.java

1、非常明显的是:接下来我们要为ListView设定 Adapter 以及 设定点击事件监听器,在单击事件监听器中我们实现的是:用Fragment来替换FrameLayout

这些都非常的简单,不再赘述

2、之后,我们就要为DrawerLayout添加菜单开、关状态监听器,为的是能够动态的改变ActionBar中的显示内容,这里面就要注意一下:

①为了能够监听侧滑菜单的开关状态我们需要调用DrawerLayout的setDrawerListener()方法,之后将实现了DrawerLayout.DrawerListener接口的实例对象当做参数,传进去,这个DrawerLayout.DrawerListener监听器中有两个方法onDrawerOpened()和DrawerClosed(),当侧滑菜单开、关时,会回调他们之中的某一个

②如果你监听侧滑菜单的开、关事件,并不是为了和ActionBar发生关系,是为了处理其他的事件,那么使用上面的方法就行了

③如果你监听侧滑菜单的开、关事件,就是为了和ActionBar发生关系,动态的更改ActionBar的内容,那么鼓励使用ActionBarDrawerToggle类 ,这个类继承了上面的DrawerLayout.DrawerListener接口,所以你依然能够重写上面的两个回调方法,之后调用DrawerLayout的setDrawerListener()方法,与此同时,正如你下面将会看到的那样:使用ActionBarDrawerToggle类作为监听器是因为:它已经将ActionBar上的应用图标单击事件和侧滑菜单的开关绑定好了,无需在人为的进行这方面的逻辑控制;而且使用它能够非常方便的进行“指示图标”的更换,只需要在创建这个类的对象的时候,将要使用的图标作为构造参数传进去即可

④当然,一般我们就使用google自带的默认的“指示图标”——三横

⑤需要注意的是:为了使ActionBarDrawerToggle监听器能够适应于Activity的生命周期,我们需要在Activity中的几个方法中添加一些语句,在下面的程序中我们会提到,非常的简单

MainActivity.java
package com.example.navigaterdrawer;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
    
    ListView menuDrawer ; //侧滑菜单视图
    DrawerAdapter menuDrawerAdapter ; // 侧滑菜单ListView的Adapter
    DrawerLayout mDrawerLayout ; // DrawerLayout组件
    //当前的内容视图下(即侧滑菜单关闭状态下),ActionBar上的标题,
    String currentContentTitle ;
    ActionBarDrawerToggle mDrawerToggle ; //侧滑菜单状态监听器
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //开始时显示全局标题“推酷”
        currentContentTitle = getResources().getString(R.string.global_title) ; 

        //为侧滑菜单设置Adapter,并为ListView添加单击事件监听器
        menuDrawer = (ListView)findViewById(R.id.left_drawer) ;
        menuDrawerAdapter = new DrawerAdapter(this) ;
        menuDrawer.setAdapter(menuDrawerAdapter);
        menuDrawer.setOnItemClickListener(new DrawerItemClickListener());
        
        //为DrawerLayout注册状态监听器
        mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
        mDrawerToggle = new DrawerMenuToggle(
                this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) ;
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        
        //设置ActionBar的指示图标可见,设置ActionBar上的应用图标位置处可以被单击        
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
        getActionBar().setTitle(currentContentTitle);
        //隐藏ActionBar上的应用图标,只显示文字label
        getActionBar().setDisplayShowHomeEnabled(false);

    }

    
    /**侧滑菜单单击事件监听器*/
    private class DrawerItemClickListener implements ListView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            
            selectItem(position);
            
        }
        
        public void selectItem(int position){
            
            //为内容视图加载新的Fragment
            Bundle bd = new Bundle() ;
            bd.putString(ContentFragment.SELECTED_ITEM,menuDrawerAdapter.getItem(position).menuTitle);
            
            Fragment contentFragment = new ContentFragment( ) ;
            contentFragment.setArguments(bd);
            
             FragmentManager fragmentManager =getFragmentManager();
             FragmentTransaction transaction = fragmentManager.beginTransaction();
             transaction.replace(R.id.content_frame, contentFragment).commit();
             
             //将选中的菜单项置为高亮
             menuDrawer.setItemChecked(position, true);
             //将ActionBar中标题更改为选中的标题项
             setTitle(menuDrawerAdapter.getItem(position).menuTitle);
             //将当前的侧滑菜单关闭,调用DrawerLayout的closeDrawer()方法即可
             mDrawerLayout.closeDrawer(menuDrawer);
        }
        
        public void setTitle( String title ){
            currentContentTitle = title ; // 更改当前的CurrentContentTitle标题内容
            getActionBar().setTitle(title);
            
        }
    }
    
    /**侧滑菜单状态监听器(开、关),通过继承ActionBarDrawerToggle实现*/
    private class DrawerMenuToggle extends ActionBarDrawerToggle{

        /**
         * @param drawerLayout :就是加载的DrawerLayout容器组件
         * @param drawerImageRes : 要使用的ActionBar左上角的指示图标
         * @param openDrawerContentDescRes 、closeDrawerContentDescRes:开启和关闭的两个描述字段,没有太大的用处
         * 
         * */
        public DrawerMenuToggle(Activity activity, DrawerLayout drawerLayout,
                int drawerImageRes, int openDrawerContentDescRes,
                int closeDrawerContentDescRes) {
            
            super(activity, drawerLayout, drawerImageRes, openDrawerContentDescRes,closeDrawerContentDescRes);
            
        }
        
        /** 当侧滑菜单达到完全关闭的状态时,回调这个方法 */
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
          //当侧滑菜单关闭后,显示ListView选中项的标题,如果并没有点击ListView中的任何项,那么显示原来的标题
            getActionBar().setTitle(currentContentTitle);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }

        /** 当侧滑菜单完全打开时,这个方法被回调 */
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            getActionBar().setTitle(R.string.global_title); //当侧滑菜单打开时ActionBar显示全局标题"推酷"
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }
    };
    
    /**为了能够让ActionBarDrawerToggle监听器
     * 能够在Activity的整个生命周期中都能够以正确的逻辑工作
     * 需要添加下面两个方法*/
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
 
    /**最后做一些菜单上处理*/
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        //第一个if 要加上,为的是让ActionBarDrawerToggle以正常的逻辑工作
        if (mDrawerToggle.onOptionsItemSelected(item)) {
              return true;
            }
        if (id == R.id.action_settings) {
            return true;
        }
        if(id == R.id.action_websearch){
            Toast.makeText(this, "webSearch 菜单项被单击", Toast.LENGTH_SHORT).show();
        }
        return super.onOptionsItemSelected(item);
    }
    
    /**每次调用 invalidateOptionsMenu() ,下面的这个方法就会被回调*/
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        
        // 如果侧滑菜单的状态监听器在侧滑菜单打开和关闭时都调用了invalidateOptionsMenu()方法,
        //当侧滑菜单打开时将ActionBar上的某些菜单图标隐藏起来,使得这时仅显示“推酷”这个全局标题
        //本应用中是将ActiongBar上的action菜单项隐藏起来
        
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(menuDrawer);//判定当前侧滑菜单的状态
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
    
  /**《当用户按下了"手机上的返回功能按键"的时候会回调这个方法》*/
         @Override
         public void onBackPressed() {
            boolean drawerState =  mDrawerLayout.isDrawerOpen(menuDrawer);
             if (drawerState) {
                 mDrawerLayout.closeDrawers();
                 return;
             }
             //也就是说,当按下返回功能键的时候,不是直接对Activity进行弹栈,而是先将菜单视图关闭
             super.onBackPressed();
         }

        
        
}
Fragment文件的创建——ContentFragment.java
package com.example.navigaterdrawer;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class ContentFragment extends Fragment {
    
    public static final String  SELECTED_ITEM = "selected_item" ;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        
        Bundle bd = getArguments( ) ;
        
        View view = inflater.inflate(R.layout.fragment_content, null) ;
        ( (TextView ) view ).setText(bd.getString(SELECTED_ITEM)) ;
        return view ;
    }

}
fragment_content.xml文件
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</TextView>
主菜单的创建—— main.xml文件
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.navigaterdrawer.MainActivity" >

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/action_settings"/>
    <!-- 添加一个action菜单项 ,显示一张图片,标题设为空-->
    <item
        android:id="@+id/action_websearch"
        android:showAsAction="withText|ifRoom"
        android:icon="@drawable/find"
        android:title= ""/>

</menu>
string.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">NavigaterDrawer</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="drawer_open"> Drawer is opened </string>
    <string name="drawer_close">Drawer is closed </string>
    <string name="global_title">推酷</string>
</resources>
配置文件——Mainfest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.navigaterdrawer"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.DeviceDefault.Light">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

文章参考链接:添加链接描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值