Android開(kāi)發(fā)(37) 使用DrawerLayout實(shí)現(xiàn)抽屜式導(dǎo)航菜單

概述

最近流行 左側(cè)抽屜式的導(dǎo)航條菜單浅妆,知乎缀壤,360,QQ都使用了這樣的導(dǎo)航菜單典勇,我們也了解下:

Android Design 的流行趨勢(shì):Navigation Drawer 導(dǎo)航抽屜 參考這篇文章:http://www.geekpark.net/topics/183724

效果圖:


特點(diǎn)

1.標(biāo)題欄(或者actionBar) 做的有個(gè) 菜單圖標(biāo)按鈕(三條線或者其他)桅锄。一般這樣的標(biāo)題欄左側(cè)和右側(cè)都會(huì)有圖標(biāo)按鈕琉雳。如圖1所示。

2.點(diǎn)擊圖標(biāo)按鈕 從左側(cè)向右 慢慢退出一個(gè) 菜單視圖(View)友瘤,遮蓋在 內(nèi)容頁(yè)(首頁(yè))的視圖上翠肘,同時(shí),產(chǎn)生遮蓋層辫秧。如圖2所示束倍。

實(shí)

官方示例

參考自谷歌開(kāi)發(fā)者網(wǎng)站的示例,在這個(gè)頁(yè)面可以下載到示例盟戏。http://developer.android.com/training/implementing-navigation/nav-drawer.html

引用類(lèi)庫(kù)

需要android-support-v4.jar

主要控件

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

參考這片文章的解釋?zhuān)?a target="_blank" rel="nofollow">http://blog.csdn.net/xiahao86/article/details/8995827

具體實(shí)現(xiàn)

首頁(yè)(比如叫:MainActivity)內(nèi)容布局肌幽,寫(xiě)一個(gè) android.support.v4.widget.DrawerLayout,它需要包含兩個(gè)內(nèi)容視圖元素抓半,第一個(gè)視圖元素是 主顯示內(nèi)容頁(yè),第二個(gè)是要抽屜彈出的視圖格嘁。

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

我在這里寫(xiě)了個(gè)自定義控件 “ zyf.demo.navigationdrawer.NavigationMenu " 笛求,
注意它的 android:layout_gravity="start" ,是 start 不是left糕簿。

MainActivity需要 為DrawerLayout 注冊(cè)一個(gè)回調(diào)事件接口ActionBarDrawerToggle 探入,這個(gè)事件的實(shí)現(xiàn)者監(jiān)聽(tīng)器會(huì)獲得 抽屜彈出(onDrawerOpened)和關(guān)閉(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圖標(biāo)透明不可見(jiàn)
        getActionBar().setIcon(
                new ColorDrawable(getResources().getColor(
                        android.R.color.transparent)));

        // 注冊(cè)導(dǎo)航菜單抽屜 的彈出和關(guān)閉事件
        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 */
        ) {
            // 當(dāng)導(dǎo)航菜單抽屜 關(guān)閉后
            public void onDrawerClosed(View view) {
                // 顯示當(dāng)前內(nèi)容頁(yè)的標(biāo)題
                getActionBar().setTitle(getTitle());
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }

            // 當(dāng)導(dǎo)航菜單抽屜 打開(kāi)后
            public void onDrawerOpened(View drawerView) {
                // 顯示導(dǎo)航菜單的標(biāo)題
                getActionBar().setTitle(mNavigationMenu.getTitle());
                invalidateOptionsMenu(); // creates call to
                                            // onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // 顯示首頁(yè)的內(nèi)容
        showFragment(new HomeFragment());
        
        // 當(dāng)更換主頁(yè)內(nèi)的 子頁(yè)面(fragment)時(shí),隱藏導(dǎo)航菜單
        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
        // 當(dāng)彈出導(dǎo)航菜單時(shí)懂诗,使 actionbar的擴(kuò)展按鈕不可見(jiàn)
        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, "你點(diǎn)擊了搜索按鈕", 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);
    }

}

下面給出我寫(xiě)的自定義控件的實(shí)現(xiàn):

<?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;// 關(guān)聯(lián)到的抽屜控件

    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的點(diǎn)擊事件
     * @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 "導(dǎo)航菜單";
    }

    /**
     * 關(guān)聯(lián)到 drawerLayout
     * @param drawerLayout
     */
    public void attacthDrawer(DrawerLayout drawerLayout) {
        mDrawerLayout = drawerLayout;
    }

    /**
     * 隱藏
     */
    public void hide() {
        if (mDrawerLayout != null)
            mDrawerLayout.closeDrawer(NavigationMenu.this);
    }
    
    /**
     * 出現(xiàn)
     */
    public void show() {
        if (mDrawerLayout != null)
            mDrawerLayout.openDrawer(NavigationMenu.this);
    }
    
    
}

代碼下載:

http://yunpan.cn/cggiDkFNCp2Jw 訪問(wèn)密碼 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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蜂嗽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子殃恒,更是在濱河造成了極大的恐慌植旧,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件离唐,死亡現(xiàn)場(chǎng)離奇詭異病附,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)亥鬓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)完沪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嵌戈,你說(shuō)我怎么就攤上這事覆积√螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵宽档,是天一觀的道長(zhǎng)尉姨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雌贱,這世上最難降的妖魔是什么啊送? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮欣孤,結(jié)果婚禮上馋没,老公的妹妹穿的比我還像新娘。我一直安慰自己降传,他們只是感情好篷朵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著婆排,像睡著了一般声旺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上段只,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天腮猖,我揣著相機(jī)與錄音,去河邊找鬼赞枕。 笑死澈缺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炕婶。 我是一名探鬼主播姐赡,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼柠掂!你這毒婦竟也來(lái)了项滑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涯贞,失蹤者是張志新(化名)和其女友劉穎枪狂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體肩狂,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摘完,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傻谁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孝治。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谈飒,到底是詐尸還是另有隱情岂座,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布杭措,位于F島的核電站费什,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏手素。R本人自食惡果不足惜鸳址,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泉懦。 院中可真熱鬧稿黍,春花似錦、人聲如沸崩哩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)邓嘹。三九已至酣栈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汹押,已是汗流浹背矿筝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棚贾,地道東北人跋涣。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鸟悴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奖年,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容