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

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM