如何在操作栏应用图标旁添加“菜单”指示器?

23

至少 Gmail 和 Youtube Android 应用程序使用侧边菜单(导航抽屉?),通过滑动或点击应用程序图标(主页按钮)打开:

enter image description here

上面截图中的菜单指示符 / 图标是Android SDK的现成部分吗?(还是Google在其应用程序中使用的自定义图标?)无论如何,让您的主页按钮看起来像那样并打开一个菜单的最简单方法是什么

targetSdkVersion 18;minSdkVersion 14)

解决方法

最后搞定了。对我而言缺少的是 1)实际图标和 2)在 ActionBarDrawerToggle 上延迟调用 syncState()


你打算使用 NavigationDrawer 还是只是想要与图片中相同的外观?抽屉指示器是一个自定义图标,不仅谷歌使用它来表示从 ActionBar 按下主页按钮将打开菜单。 - hardartcore
我已经在使用NavigationDrawer并且我想要与图片中相同的外观。 :) - Jonik
3个回答

33
要在你的应用程序中创建类似的实现/外观,你应该使用 ActionBarDrawerToggle,并将你的自定义图标设置为 ActionBar 主页按钮旁边的指示器。例如:
import android.app.ActionBar;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;

private void setUpDrawerToggle(){
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the navigation drawer and the action bar app icon.
    mDrawerToggle = new ActionBarDrawerToggle(
            this,                             /* host Activity */
            mDrawerLayout,                    /* DrawerLayout object */
            R.drawable.ic_drawer,             /* nav drawer image to replace 'Up' caret */
            R.string.navigation_drawer_open,  /* "open drawer" description for accessibility */
            R.string.navigation_drawer_close  /* "close drawer" description for accessibility */
    ) {
        @Override
        public void onDrawerClosed(View drawerView) {
            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }
    };

    // Defer code dependent on restoration of previous instance state.
    // NB: required for the drawer indicator to show up!
    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

R.drawable.ic_drawer 是用作指示器的图标。你可以在Android Asset Studio找到它;请参见导航抽屉指示器

参考文献

  1. ActionBarDrawerToggle
  2. 创建导航抽屉

好的,这很有帮助。我已经有了类似代码的 ActionBarDrawerToggle;现在我只是在寻找正确的图标来自 图标包 ... - Jonik
太好了!那正是我需要的。你能在答案本身编辑那一部分信息吗?我会接受它。 - Jonik
所以,虽然这看起来非常有前途,但至少在我的设备上,这还不足以使指示器出现。 :-/ 我找到了一种在API 18+上运行的方法,但在此之下仍然存在一个未解决的问题... - Jonik
请检查已编辑的答案。此代码已在API LEVEL 14上进行了测试并且可以正常工作。如果您正在使用Android Studio进行开发,您可以创建一个已实现“NavigationDrawer”的新项目并检查源代码。 - hardartcore
显示剩余4条评论

10

Android-DeveloperHpTerm帮我找对了方向:

  1. 指出这确实是导航抽屉(NavigationDrawer)的特定问题(我已经按照Google的示例在使用)
  2. 告诉我如何找到ic_drawer.png图标 (→ Android Asset Studio)

不幸的是,像下面这样创建ActionBarDrawerToggle似乎还不够,至少我的Nexus 7(API 18)测试设备上如此。

drawerToggle = new ActionBarDrawerToggle(this, 
                       drawerLayout, 
                       R.drawable.ic_navigation_drawer, 
                       R.string.side_menu_open, 
                       R.string.side_menu_closed) {
    // ...
};

部分解决方案(API级别18+)

我找到了一种让这个指示器出现的方法: setHomeAsUpIndicator()。但是不足之处是,该方法是在API级别18中添加的。

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    getActionBar().setDisplayHomeAsUpEnabled(true); // also required
    if (Build.VERSION.SDK_INT >= 18) {
        getActionBar().setHomeAsUpIndicator(
            getResources().getDrawable(R.drawable.ic_navigation_drawer));
    }
}

现在问题仍然存在:如何使这在API 14到17的级别中工作(在我的情况下)?

我在一个4.1.2(API 16)设备上验证了ic_drawer图标没有显示。使用 setDisplayHomeAsUpEnabled(true)会得到正常的“主页”图标(一个指向左的小箭头),如果没有它,我的应用程序图标左侧的空间将保持空白。

最终解决方案

使用编辑过的Android开发者的答案的版本让它工作起来了。

非常奇怪的是,我的ActionBarDrawerToggle初始化代码中缺少了这一点:

   // Defer code dependent on restoration of previous instance state.
   drawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

在这种情况下,调用setHomeAsUpIndicator()不必要的


2
这里的关键词是{{link1:NavigationDrawer}};在Android开发者网站上有一个完整的可工作代码示例。 请阅读所提供链接的末尾:使用应用程序图标打开和关闭。
下面的代码是从那里复制的。
public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    ...

    public void onCreate(Bundle savedInstanceState) {
        ...

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
                ) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
    }

    @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 onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
          return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    ...
}

一些文件可以下载,带有动画效果的三条小线也完全被演示了。
您需要将这些文件复制到相应的“drawable”文件夹中。根据您使用的主题,黑色或白色,您将拥有不同的图标集。
在我的情况下,我只是将“drawer_shadow.9.png”和“ic_drawer.png”复制到drawable文件夹中,并按照示例操作,一切都很正常。
这些图标可以在我提供的链接中找到,但它们不在“操作栏图标包”中它们在样本应用程序中相应res/drawable文件夹中

我已经在使用 NavigationDrawer。我正在寻找关于如何最简单地添加菜单图标/指示器的具体说明。 - Jonik
正如我所说,链接中给出的示例提供了所有细节。只需复制粘贴示例即可运行。您是否看过Android开发人员提供的示例?我可以在此处复制粘贴它,但所有内容都在可下载的示例中。 - HpTerm
你在哪里找到了 drawer_shadow.9.png / ic_drawer.png 文件?导航抽屉文档中链接的 Action Bar Icon Pack 似乎没有包含这些文件。 - Jonik
1
我的错误,它们在“示例应用程序”中,而不是在操作栏图标包中。如果你下载了示例应用程序,请进入res/drawable文件夹。你会在那里找到这些图标。 - HpTerm
谢谢!我确实在示例应用程序中找到了它们。(虽然我不确定drawer_shadow.9.png在我的情况下是否相关。)指示器也可以在这里找到:http://android-ui-utils.googlecode.com/hg/asset-studio/dist/icons-nav-drawer-indicator.html#theme=light&color=33b5e5%2C40 - Jonik
感谢您的反馈。我花了很长时间才找到这些图标,最终在示例应用程序中找到了它们。因此,@Android-Developer提供的链接非常有用。 - HpTerm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接