Android - 将ActionBar后退按钮切换到导航按钮

Ant*_*nio 40 android back-button android-actionbar navigation-drawer android-toolbar

我有以下问题:

我知道如何设置工具栏来显示后退按钮图标而不是汉堡按钮图标.

由此:
在此输入图像描述

对此:

在此输入图像描述

使用: getSupportActionBar().setDisplayHomeAsUpEnabled(true);


现在,我想做反向动作,我想从后退按钮图标转到汉堡图标:

在此输入图像描述

到这里:

在此输入图像描述

我怎样才能做到这一点?

更新:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setSupportActionBar(mToolbar);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
}

private void enableViews(boolean enable) {
    if(enable) {
        // Enables back button icon
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    } else {
        // TODO: Enables burger icon
    }
}
Run Code Online (Sandbox Code Playgroud)

ade*_*ede 115

如果我假设您android.support.v4.widget.DrawerLayout在布局中使用,那么这种方法可能适合您; 我只测试过,API 21但鉴于它主要使用支持库,它应该在较低或较高的目标上工作(着名的最后一个字).

import android.support.v7.app.ActionBarDrawerToggle
import android.support.v4.widget.DrawerLayout

    ActionBarDrawerToggle mDrawerToggle;
    DrawerLayout drawerLayout;
    private boolean mToolBarNavigationListenerIsRegistered = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        // Get DrawerLayout ref from layout
        drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
        // Initialize ActionBarDrawerToggle, which will control toggle of hamburger.
        // You set the values of R.string.open and R.string.close accordingly.
        // Also, you can implement drawer toggle listener if you want.
        mDrawerToggle = new ActionBarDrawerToggle (this, drawerLayout, mToolbar, R.string.open, R.string.close);
        // Setting the actionbarToggle to drawer layout
        drawerLayout.addDrawerListener(mDrawerToggle);
        // Calling sync state is necessary to show your hamburger icon...
        // or so I hear. Doesn't hurt including it even if you find it works
        // without it on your test device(s)
        mDrawerToggle.syncState();
    }

    /**
     * To be semantically or contextually correct, maybe change the name
     * and signature of this function to something like:
     *
     * private void showBackButton(boolean show)
     * Just a suggestion.
     */
     private void enableViews(boolean enable) {

        // To keep states of ActionBar and ActionBarDrawerToggle synchronized,
        // when you enable on one, you disable on the other.
        // And as you may notice, the order for this operation is disable first, then enable - VERY VERY IMPORTANT.
        if(enable) {
            //You may not want to open the drawer on swipe from the left in this case  
            drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            // Remove hamburger
            mDrawerToggle.setDrawerIndicatorEnabled(false);
            // Show back button
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            // when DrawerToggle is disabled i.e. setDrawerIndicatorEnabled(false), navigation icon
            // clicks are disabled i.e. the UP button will not work.
            // We need to add a listener, as in below, so DrawerToggle will forward
            // click events to this listener.
            if(!mToolBarNavigationListenerIsRegistered) {
                mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // Doesn't have to be onBackPressed
                        onBackPressed();
                    }
                });

                mToolBarNavigationListenerIsRegistered = true;
            }

        } else {
            //You must regain the power of swipe for the drawer. 
            drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

            // Remove back button
            getSupportActionBar().setDisplayHomeAsUpEnabled(false);
            // Show hamburger 
            mDrawerToggle.setDrawerIndicatorEnabled(true);
            // Remove the/any drawer toggle listener
            mDrawerToggle.setToolbarNavigationClickListener(null);
            mToolBarNavigationListenerIsRegistered = false;
        }

        // So, one may think "Hmm why not simplify to:
        // .....
        // getSupportActionBar().setDisplayHomeAsUpEnabled(enable);
        // mDrawer.setDrawerIndicatorEnabled(!enable);
        // ......
        // To re-iterate, the order in which you enable and disable views IS important #dontSimplify.
    }

Run Code Online (Sandbox Code Playgroud)

该解决方案用于ActionBarDrawerToggle.setDrawerIndicatorEnabled切换汉堡包图标ActionBar.setDisplayHomeAsUpEnabled的可见性以及向上按钮的可见性,主要是利用其各自的drawable资源.

其他假设

  • 您的活动主题扩展Theme.AppCompat.Light.NoActionBar.

  • 太棒了,@ Ade.Akinyede!这正是我在寻找的.你完成了我所有的赏金要求,给出了一个很好的解释和一个很好的例子,你也做了很好的分析和建议.你获得了赏金 (3认同)
  • 你救了我的一天!好的解决方案 我用我的应用程序用片段构建它,它工作正常!做得好!+1 (2认同)

Ste*_*nTo 6

在这种情况下,顶级解决方案不起作用:

  • 一个活动和多个片段
  • 一个片段 (SettingsFragment) 应该显示后退图标而不是汉堡菜单
  • 使用 com.google.android.material.appbar.AppBarLayout、androidx.appcompat.widget.Toolbar 和 ActionBarDrawerToggle

我在我的 Activity 的 onCreate() 中调用这个方法:

private fun initBackStackChangeListener() {
    supportFragmentManager.addOnBackStackChangedListener {
        val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

        if (fragment is SettingsFragment) {
            menuDrawerToggle?.isDrawerIndicatorEnabled = false
            drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
            menuDrawerToggle?.setToolbarNavigationClickListener { onBackPressed() }
            supportActionBar?.setDisplayHomeAsUpEnabled(true)
        } else {
            supportActionBar?.setDisplayHomeAsUpEnabled(false)
            drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
            menuDrawerToggle?.isDrawerIndicatorEnabled = true
            menuDrawerToggle?.toolbarNavigationClickListener = null
            menuDrawerToggle?.syncState()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而 menuDrawerToggle 是这样的:

menuDrawerToggle = ActionBarDrawerToggle(
        this, drawer_layout, toolbar,
        R.string.navigation_drawer_open,
        R.string.navigation_drawer_close
    ).apply {
        drawer_layout.addDrawerListener(this)
        this.syncState()
    }
Run Code Online (Sandbox Code Playgroud)

奇迹般有效。也许它可以帮助任何人。


Ant*_*ykh 5

我在The Google I/O 2017 Android App 中找到了灵活的解决方案。

public Toolbar getToolbar() {
    if (mToolbar == null) {
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        if (mToolbar != null) {
            setSupportActionBar(mToolbar);
            mToolbar.setNavigationContentDescription(R.string.navdrawer_description_a11y);
            mToolbarTitle = (TextView) mToolbar.findViewById(R.id.toolbar_title);
            if (mToolbarTitle != null) {
                int titleId = getNavigationTitleId();
                if (titleId != 0) {
                    mToolbarTitle.setText(titleId);
                }
            }

            // We use our own toolbar title, so hide the default one
            getSupportActionBar().setDisplayShowTitleEnabled(false);
        }
    }
    return mToolbar;
}

/**
 * @param clickListener The {@link android.view.View.OnClickListener} for the navigation icon of
 *                      the toolbar.
 */
protected void setToolbarAsUp(View.OnClickListener clickListener) {
    // Initialise the toolbar
    getToolbar();
    if (mToolbar != null) {
        mToolbar.setNavigationIcon(R.drawable.ic_up);
        mToolbar.setNavigationContentDescription(R.string.close_and_go_back);
        mToolbar.setNavigationOnClickListener(clickListener);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以用法很简单。

setToolbarAsUp(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // onBackPressed();
        // or navigate to parent or some other intent
    }
});
Run Code Online (Sandbox Code Playgroud)


Dav*_*eli 5

在我看来,选择的答案太老套了。

我尝试实现它,在这样做的同时,我意识到实际上没有什么用ActionBarDrawerToggle(也许这就是为什么它从关于Navigation Drawer的官方 android 教程中删除的原因):当你想要合作时,它并没有让你的生活更轻松- 导航抽屉和操作栏之间的坐标。

问题是,你只有1家“按钮”,并且它有2个不同的功能-打开抽屉,当你在主屏幕,并上去,当你在你的应用程序进一步下跌。将工具栏作为参数传递给ActionBarDrawerToggle构造函数,向其添加菜单图标,并在单击事件上调用 openDrawer。现在如果你想切换到一个向上事件,你必须关闭这个特殊的图标,并重新启用操作栏的固有返回功能......这仍然是一团糟。

因此,如果ActionBarDrawerToggle对您没有帮助(但是,也许有人会想出一种方法来帮助您),为什么首先要使用它?这是没有它的方法:

boolean homeShouldOpenDrawer; // flag for onOptionsItemSelected

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // if you're using NoActionBar theme
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    ActionBar actionbar = getSupportActionBar();

    // enables the home button with a <-
    actionbar.setDisplayHomeAsUpEnabled(true);

    // replaces the <- with the menu (hamburger) icon 
    // (ic_menu should be in every empty project, and can be easily added)
    actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);

    // I assume your first fragment/state should be main screen, i.e. home = opens drawer
    homeShouldOpenDrawer = true;
    ...
}

private void enableViews(boolean enable) {
    if(enable) {
        // Enables back button icon
        // passing null or 0 brings back the <- icon
        getSupportActionBar().setHomeAsUpIndicator(null);
        homeShouldOpenDrawer = false;
    } else {
        // Enables burger icon
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
        homeShouldOpenDrawer = true;
    }

}

// this is called whenever a selection is made from the action bar
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            if (homeShouldOpenDrawer) {
                drawerLayout.openDrawer(GravityCompat.START);
            } else {
                onBackPressed();
            }
    }

    return super.onOptionsItemSelected(item);
}
Run Code Online (Sandbox Code Playgroud)

  • 首先,删除帖子中的名称标注和否定方法。这是反社会。作为开发人员,应该清楚生态系统变化的速度有多快,解决方案也应该如此。 (2认同)