安卓棒棒糖工具栏如何在打开/关闭抽屉和返回按钮之间切换

9
我是一个有用的助手,可以翻译文本。
我之前使用了标准导航抽屉,但现在我正在尝试使用工具栏修改它。
以前我的代码看起来像这样: MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.v("MAIN", "CREATE");
    initViews();
    setListeners();

    getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            shouldDisplayHomeUp();
        }
    });

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));
}

NavigationDrawerFragment.java

public void setUp(int fragmentId, DrawerLayout drawerLayout) {
    mFragmentContainerView = getActivity().findViewById(fragmentId);
    mDrawerLayout = drawerLayout;

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    ((MainActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ((MainActivity) getActivity()).getSupportActionBar().setHomeButtonEnabled(true);

    mDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout,
            ((MainActivity) getActivity()).getToolbar(),
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close) {
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            if (!isAdded()) {
                return;
            }

            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            if (!isAdded()) {
                return;
            }

            if (!mUserLearnedDrawer) {
                // The user manually opened the drawer; store this flag to prevent auto-showing
                // the navigation drawer automatically in the future.
                mUserLearnedDrawer = true;
                SharedPreferences sp = PreferenceManager
                        .getDefaultSharedPreferences(getActivity());
                sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
            }
            if (mDrawerListView != null) {

            }
            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            super.onDrawerSlide(drawerView, slideOffset);
        }
    };

    // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
        mDrawerLayout.openDrawer(mFragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.

    mDrawerToggle.setDrawerIndicatorEnabled(true);

    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

现在我修改了我的代码:

MainActivity.java

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

    mToolbar = (Toolbar) findViewById(R.id.toolbar);

    if (mToolbar != null) {
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    initViews();
    setListeners();

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));


    shouldDisplayHomeUp();

    getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            mBackCount++;
            shouldDisplayHomeUp();
        }
    });
}

NavigationDrawerFragment.java

public void setUp(int fragmentId, DrawerLayout drawerLayout) {
    mFragmentContainerView = getActivity().findViewById(fragmentId);
    mDrawerLayout = drawerLayout;

    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    mDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout,
            ((MainActivity) getActivity()).getToolbar(),
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close) {
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            if (!isAdded()) {
                return;
            }

            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            if (!isAdded()) {
                return;
            }

            if (!mUserLearnedDrawer) {
                // The user manually opened the drawer; store this flag to prevent auto-showing
                // the navigation drawer automatically in the future.
                mUserLearnedDrawer = true;
                SharedPreferences sp = PreferenceManager
                        .getDefaultSharedPreferences(getActivity());
                sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
            }
            if (mDrawerListView != null) {

            }
            getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
        }

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            super.onDrawerSlide(drawerView, slideOffset);
        }
    };

    // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
        mDrawerLayout.openDrawer(mFragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.

    mDrawerToggle.setDrawerIndicatorEnabled(true);

    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mDrawerLayout.setDrawerListener(mDrawerToggle);
}

而且,shouldDisplayHomeUp 函数:
public void shouldDisplayHomeUp (){
    boolean canBack = getFragmentManager().getBackStackEntryCount() > 0;
    mNavigationDrawerFragment.getDrawerToggle().setDrawerIndicatorEnabled(!canBack);
}

“但是后退箭头没有显示出来。”
“我尝试过调用。”
getSupportActionBar().setDisplayHomeAsUpEnabled(canBack);
getSupportActionBar().setHomeButtonEnabled(canBack);

所以返回箭头出现了,但点击它没有任何效果。

当您的后退堆栈中有多个片段时,您想要更改返回箭头吗? - Pedro Oliveira
是的,请提供返回导航而不是打开抽屉。 - zagum
使用ActionBar,这个功能完美运作。 - zagum
请查看我的答案,链接在这里:https://dev59.com/wuo6XIcBkEYKwwoYGwUw#29292130 - mixel
2个回答

22

从文档中得知:

为了允许在操作栏中使用应用程序图标进行向上导航,请调用 setDisplayHomeAsUpEnabled() 方法:

@Override public void onCreate(Bundle savedInstanceState) {
     ...
     getActionBar().setDisplayHomeAsUpEnabled(true); }

这将在应用程序图标旁添加一个向左的小三角形,并将其作为操作按钮启用,以便当用户按下它时,您的活动将接收到对 onOptionsItemSelected() 的调用。该操作的 ID 为 android.R.id.home。
这意味着您需要在 onOptionsItemSelected() 上实现后退例程,并检查 R.id.home。为了避免在点击汉堡菜单时调用该例程,请在 onOptionsItemSelected() 上还检查 canback。

http://developer.android.com/training/implementing-navigation/ancestral.html#up

编辑

要实现你想要的功能,你需要编写自己的导航程序。

    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(shouldBack()) {
               //call onbackpressed or something
                if(displayBackAgain)
                    return; //return after so you don't call syncState();       
            }else if (mNavigationDrawerFragment.isDrawerOpen())
                mNavigationDrawerFragment.closeDrawer();
            else
                mNavigationDrawerFragment.openDrawer();
            mNavigationDrawerFragment.getActionBarDrawerToggle().syncState();
        }
    });
}

要启用返回按钮图标,只需调用getSupportActionBar().setDisplayHomeAsUpEnabled(true);,要禁用它,只需调用mNavigationDrawerFragment.getActionBarDrawerToggle().syncState();

2
是的,但它不适用于来自appcompat_v21的工具栏。 - zagum
setNavigationOnClickListener无法捕获点击事件。 - zagum
在调用 setup() 后,您必须进行设置。 - Pedro Oliveira
1
我遇到了关于AppCompat v7的问题。虽然汉堡菜单图标可以正常显示,但当我隐藏它并尝试显示主页(向上箭头)时,它从未出现过。你有什么想法吗? - Daniel Ochoa
@PedroOliveira 是的。它总是在onPostCreate中调用。我甚至尝试再次调用它,但没有成功。只有在使用工具栏作为操作栏时才会出现这种情况。当我切换回不使用工具栏时,这个问题就不再发生了。 - Daniel Ochoa

3

我是一名有用的助手,可以为您进行文本翻译。

我发现了一种控制后退按钮和导航的方法。它对我有效。

首先,进行设置:

private void setupNav () {

    this.toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(this.toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    this.mActionBarDrawerToggle = new ActionBarDrawerToggle(this, this.mDrawerLayout, this.toolbar, 0, 0);

    this.mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //catch back button here.
        }
    });
    this.mDrawerLayout.setDrawerListener(this.mActionBarDrawerToggle);
    this.mActionBarDrawerToggle.syncState();
}

重要的事情是,这是我隐藏汉堡包菜单并显示返回按钮的方法。您必须将此代码放置在要显示返回按钮的位置。同时,在显示返回按钮时,我还锁定了导航栏。

if (!isShowBackButton) {
        mActionBarDrawerToggle.setDrawerIndicatorEnabled(true);
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    } else {

        mActionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        //enable back button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

谢谢,孩子,这对我很有用,也节省了很多时间。 - Bharat Dodeja

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