android开发(38) 使用 DrawerLayou t实现左侧抽屉式导航菜单

最近流行 左侧抽屉式的导航条菜单,知乎,360,QQ都使用了这样的导航菜单,我们也了解下:

  Android Design 的流行趋势:Navigation Drawer 导航抽屉

参考这篇文章:http://www.geekpark.net/topics/183724

效果图:

                 

特点

  1.标题栏(或者actionBar) 做的有个 菜单图标按钮(三条线或者其他)。一般这样的标题栏左侧和右侧都会有图标按钮。如图1所示。

  2.点击图标按钮 从左侧向右 慢慢退出一个 菜单视图(View),遮盖在 内容页(首页)的视图上,同时,产生遮盖层。如图2所示。

怎么实现?

  官方示例

    参考自谷歌开发者网站的示例,在这个页面可以下载到示例。http://developer.android.com/training/implementing-navigation/nav-drawer.html

  引用类库

    需要android-support-v4.jar

  主要控件

    谷歌提供的抽屉控件: android.support.v4.widget.DrawerLayout

    参考这片文章的解释:http://blog.csdn.net/xiahao86/article/details/8995827

具体实现

  首页(比如叫:MainActivity)内容布局,写一个 android.support.v4.widget.DrawerLayout,它需要包含两个内容视图元素,第一个视图元素是 主显示内容页,第二个是要抽屉弹出的视图。

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

    <!--
         As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions.
    -->

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!--
         android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         The drawer is given a fixed width in dp and extends the full height of
         the container. A solid background is used for contrast
         with the content view.
    -->

    <zyf.demo.navigationdrawer.NavigationMenu
        android:id="@+id/navigation_menu"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" >
    </zyf.demo.navigationdrawer.NavigationMenu>

</android.support.v4.widget.DrawerLayout>

我在这里写了个自定义控件 “ zyf.demo.navigationdrawer.NavigationMenu " ,注意它的 android:layout_gravity="start" ,是 start 不是left。

MainActivity需要获得为DrawerLayout 注册一个回调事件接口ActionBarDrawerToggle ,这个事件的实现者监听器会获得 抽屉弹出(onDrawerOpened)和关闭(onDrawerClosed)的事件。

MainActivity 的代码

package zyf.demo.navigationdrawer;

import android.os.Bundle;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.graphics.drawable.ColorDrawable;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
    private NavigationMenu mNavigationMenu;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获得抽屉控件
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        // 获得菜单控件
        mNavigationMenu = (NavigationMenu) findViewById(R.id.navigation_menu);
        mNavigationMenu.attacthDrawer(mDrawerLayout);

        // enable ActionBar app icon to behave as action to toggle nav
        // drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        // 使actionbar 的logo图标透明不可见
        getActionBar().setIcon(
                new ColorDrawable(getResources().getColor(
                        android.R.color.transparent)));

        // 注册导航菜单抽屉 的弹出和关闭事件
        mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
        mDrawerLayout, /* DrawerLayout object */
        R.drawable.ic_notification_content, /*
                                             * nav drawer image to replace ‘Up‘
                                             * caret
                                             */
        R.string.drawer_open, /* "open drawer" description for accessibility */
        R.string.drawer_close /* "close drawer" description for accessibility */
        ) {
            // 当导航菜单抽屉 关闭后
            public void onDrawerClosed(View view) {
                // 显示当前内容页的标题
                getActionBar().setTitle(getTitle());
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }

            // 当导航菜单抽屉 打开后
            public void onDrawerOpened(View drawerView) {
                // 显示导航菜单的标题
                getActionBar().setTitle(mNavigationMenu.getTitle());
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // 显示首页的内容
        showFragment(new HomeFragment());

        // 当更换主页内的 子页面(fragment)时,隐藏导航菜单
        mNavigationMenu.hide();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content
        // view
        // 当弹出导航菜单时,使 actionbar的扩展按钮不可见
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mNavigationMenu);
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle action buttons
        switch (item.getItemId()) {
        case R.id.action_websearch:
            Toast.makeText(this, "你点击了搜索按钮", Toast.LENGTH_LONG).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void showFragment(Fragment fragment) {
        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment).commit();
    }

    @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);
        // Pass any configuration change to the drawer toggls
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

}

下面给出我写的自定义控件的实现:

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

 <ListView
        android:id="@+id/listView1"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"

        android:background="#FFFFFF"/>
</RelativeLayout>
package zyf.demo.navigationdrawer;

import android.content.Context;
import android.support.v4.widget.DrawerLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class NavigationMenu extends RelativeLayout {
    LayoutInflater mLayoutInflater;
    ListView mlistView1;
    String[] menuItemsDataSource;
    private DrawerLayout mDrawerLayout;// 关联到的抽屉控件

    public NavigationMenu(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initLayout(context);
    }

    public NavigationMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        initLayout(context);
    }

    public NavigationMenu(Context context) {
        super(context);
        initLayout(context);
    }

    private void initLayout(Context context) {
        mLayoutInflater = LayoutInflater.from(context);
        View contentView = mLayoutInflater.inflate(R.layout.navigation_menu,
                null);
        RelativeLayout.LayoutParams lp = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        this.addView(contentView, lp);

        mlistView1 = (ListView) contentView.findViewById(R.id.listView1);
        menuItemsDataSource = getResources().getStringArray(
                R.array.navigation_menu_items_array);

        mlistView1.setAdapter(new ArrayAdapter<String>(context,
                R.layout.navaigation_menu_list_view_item, menuItemsDataSource));
        mlistView1.setOnItemClickListener(new DrawerItemClickListener());
    }

    /**
     * 包含 的 listView的点击事件
     * @author yunfei
     *
     */
    private class DrawerItemClickListener implements
            ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            // selectItem(position);

            mlistView1.setItemChecked(position, true);
            hide();

            Toast.makeText(getContext(), "你选择了" + position, 0).show();
        }
    }

    public CharSequence getTitle() {
        return "导航菜单";
    }

    /**
     * 关联到 drawerLayout
     * @param drawerLayout
     */
    public void attacthDrawer(DrawerLayout drawerLayout) {
        mDrawerLayout = drawerLayout;
    }

    /**
     * 隐藏
     */
    public void hide() {
        if (mDrawerLayout != null)
            mDrawerLayout.closeDrawer(NavigationMenu.this);
    }

    /**
     * 出现
     */
    public void show() {
        if (mDrawerLayout != null)
            mDrawerLayout.openDrawer(NavigationMenu.this);
    }

}

代码下载: http://yunpan.cn/cggiDkFNCp2Jw 访问密码 c3ed

参考:

http://blog.csdn.net/xiahao86/article/details/8995827
http://developer.android.com/training/implementing-navigation/nav-drawer.html
http://www.geekpark.net/topics/183724

  

  

时间: 2024-10-06 01:50:37

android开发(38) 使用 DrawerLayou t实现左侧抽屉式导航菜单的相关文章

android开发步步为营之64:PopupWindow实现自定义弹出菜单

打开PopupWindow的源码,你会发现它其实也是通过WindowManager来添加view的. private void invokePopup(WindowManager.LayoutParams p) { if (mContext != null) { p.packageName = mContext.getPackageName(); } mPopupView.setFitsSystemWindows(mLayoutInsetDecor); setLayoutDirectionFro

Android开发技巧——使用Dialog实现仿QQ的ActionSheet菜单

最近看到有人用Dialog来实现QQ的仿ActionSheet的自定义菜单,对于自己没实现过的一些控件,看着也想实现一下.于是动手了一下,发现也不难,和大家分享一下.本文原创,转载请注明出处:在这里我也是用Dialog来实现,代码不多,这里说一下实现的过程.菜单的布局文件首先我们写先一下菜单的布局文件,很明显,是一个ListView菜单再加一个取消的Button.<?xml version...http://www.douban.com/group/topic/75787270/ http://

Android开发技巧——实现可复用的ActionSheet菜单

在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: http://blog.csdn.net/maosidiaoxian/article/details/46324941 对于要实现的可复用的控件库,我需要它具备以下两点: 可添加远程依赖(不考虑Eclipse中的使用) 可灵活配置 分离库的实现代码 对于第一点,需要做的就是在Android Studio中新建一

【转】Android开发笔记(序)写在前面的目录

原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入门上:其次是想拾缺补漏,写写虽然小众却又用得着的东西:另外就是想以实用为主,不求大而全,但求小而精:还有就是有的知识点是java的,只是Android开发也会经常遇上,所以蛮记下来.个人的经

android.support.v4.widget.DrawerLayout 抽屉效果导航菜单

抽屉效果导航菜单图示 如图所示,抽屉效果的导航菜单不用切换到另一个页面,也不用去按菜单的硬件按钮,直接在界面左上角的一个按钮点击,菜单就滑出来,而且感觉能放很多东西 概况:实现上图所示的抽屉效果的导航菜单有以下两种方式 方式1.用SlidingDrawer: http://developer.android.com/reference/android/widget/SlidingDrawer.html 但是不知道为什么这个类官方不建议再继续用了: Deprecated since API lev

easyui左侧导航菜单右侧载入百度地图项目框架

代码下载 http://pan.baidu.com/s/1cDht7K 一个左侧是导航菜单,右侧是百度地图的应用: 一 左侧菜单 使用jquery easyui框架:网上下的资源:运行后如下: 二 修改菜单 修改后如下:标注,地理要素,数据管理:这些是GIS功能: 三 jquery  easyui框架是这么用的: 单击左侧不同菜单:链接到不同html文档:就会在右侧显示相应文档: 四 载入百度地图 在其中一个demo2.html中,载入百度地图:效果如下:以后可点击左侧菜单,在右侧增加百度地图应

Android 滑动导航菜单的快速构建(二) Material Design

原创文章,转载请注明 ( 来自:http://blog.csdn.net/leejizhou/article/details/52046748 李济洲的博客 ) 上一篇 http://blog.csdn.net/leejizhou/article/details/52013343 介绍了几个滑动导航菜单效果的快速构建,这篇文章来总结"当下"如何按照Android的设计标准去设计滑动导航菜单,我为什么说的"当下"呢?因为这个设计标准是会变的. 在material de

android开发开源宝贝——持续更新。。。

2016年11月11日更新 http://www.apkbus.com/forum-417-1.html http://p.codekk.com/detail/Android/hejunlin2013/LivePlayback www.codekk.com https://github.com/Trinea/android-open-project Android 开源项目分类汇总 我们的微信公众号:codekk.二维码如下: 专注于 Android 开源分享.源码解析.框架设计.Android

Android开发优化建议

1.找一些与你想开发的功能类似的代码 2.调整它,尝试让它变成你想要的 3.回顾开发中遇到的问题 4.使用StackOverflow来解决遇到的问题 对每个你想实现的东西重复上述过程.采用这种方法能够激励你,因为你在保持不断迭代更新,在这个过程里面你会学到很多.当然,当你发布应用的时候你还要去做一些更深入的东西. 从一些能够正常编译的代码到成为一个应用程序,这是一个质的飞跃,比起iOS,Android则表现的更加明显.当iOS应用发布的时候,实际上只是在一种设备之间跳跃,对iOS很多机型而言都很