禁用导航抽屉,切换主页按钮/向上指示器

时间:2013-10-17 23:58:31

标签: android android-actionbar navigation-drawer

设置

我有一个活动,其contentView是DrawerLayout的一个实例,它的导航抽屉带有一个抽屉指示符,显示在操作栏中。该活动包含Fragment,我们称之为ListFragment,其中包含选项列表。单击某个选项后,我将ListFragment替换为DetailFragment

Architecture of the application

此时,我想显示一个“向上”导航选项,而不是导航抽屉指示器。如果我通过调用mDrawerToggle.setDrawerIndicatorEnabled(false)禁用抽屉指示器,我可以显示“向上”图标,但这只会删除抽屉图标 - 它不会删除功能 - 也就是说,当我点击插入符号时,导航抽屉仍然打开。

此外,在这些子视图中,我想通过从屏幕边缘拖动来禁用抽屉的打开。我试过通过调用setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)来尝试这样做,但它似乎没有禁用此功能。

我尝试扩展ActionBarDrawerToggle类以防止在点击指示符时打开抽屉 - 但是,所有发生的事情都是执行覆盖操作(“向上”导航),但抽屉< strong>仍然打开。

我还实施了Switching between Android Navigation Drawer image and Up caret when using fragments中的步骤。它可以显示插入符号,但是尽管覆盖了向上按钮功能,菜单仍然会打开(应用程序会导航回来 - 它也会打开抽屉)。

问题

所以,长话短说:当我的布局根是DrawerLayout时,是否有任何(最好是干净和优雅,但此时我会用hacky)方式实现这些事情:

  1. 将抽屉指示器更换为“向上”插入符号(暂时可通过mDrawerToggle.setDrawerIndicatorEnabled(false))
  2. 进行操作
  3. 单击插入符号时防止抽屉打开,而是使用我自己的“向上”功能覆盖
  4. 当我从屏幕边缘拖动时,防止抽屉打开。
  5. 修改

    好吧,看起来如果我同时覆盖ActionBarDrawerToggleonOptionsItemSelected,单击插入符号时菜单就不会打开。但是如果我从边缘拖动它仍然会打开。救命啊!

5 个答案:

答案 0 :(得分:33)

短代码

public void setDrawerState(boolean isEnabled) {
    if ( isEnabled ) {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.setDrawerIndicatorEnabled(true);
        drawerToggle.syncState();

    }
    else {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.setDrawerIndicatorEnabled(false);
        drawerToggle.syncState();
    }
}

答案 1 :(得分:22)

这只是我遇到的解决方案的一部分,但很难弄清楚这个错误,所以我为了后人的缘故离开这里。

这就是我为导航抽屉定义ListView的方法:

<ListView
    android:id="@+id/listview_drawer"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start|bottom"
    android:background="#111"
    android:choiceMode="singleChoice"
    android:divider="@android:color/transparent"
    android:dividerHeight="0dp" />

即使在致电setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)之后,我仍然可以将抽屉滑开。

但是,在将layout_gravity更改为"start"后,此问题似乎已得到解决。

我能够在示例,仅限导航抽屉的应用中重现此问题,因此它似乎是一个可重现的问题,并非我的情况所独有。

答案 2 :(得分:11)

以sonida的答案为基础。在调用setDrawerIndicatorEnabled(false)之后,onNavigateUp仍然没有被调用。所以,我刚刚创建了一个新的onClickListener来调用它:

public void setDrawerState(boolean isEnabled) {
    if ( isEnabled ) {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.setDrawerIndicatorEnabled(true);
        drawerToggle.syncState();

    }
    else {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.setDrawerIndicatorEnabled(false);
        drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onSupportNavigateUp();
            }
        });
        drawerToggle.syncState();
    }
}

我也认为

drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);

已经折旧,但没有它就可以正常工作。

答案 3 :(得分:2)

您需要停用滑动并禁用操作栏主页按钮:

使用以下代码构建的代码,以禁用滑动

  public void setDrawerState(boolean isEnabled) {
        if ( isEnabled ) {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
            mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
            mDrawerToggle.setDrawerIndicatorEnabled(true);
            mDrawerToggle.syncState();
            getActivity().getActionBar().setHomeButtonEnabled(true);

        }
        else {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            mDrawerToggle.setDrawerIndicatorEnabled(false);
            mDrawerToggle.syncState();
            getActivity().getActionBar().setHomeButtonEnabled(false);
        }
    }

答案 4 :(得分:0)

以@sonida的回答为基础并在使用@ luca992和@jai给出的调整之后。

我尝试了以上建议的代码但是&#34; up&#34;或&#34;返回&#34;操作栏左侧的箭头没有显示在我的应用程序中。但幸运的是,我能够解决这个问题。

我必须在setNavigationDrawerState()[Ref:android.support.v7.app.ActionBarDrawerToggle.setHomeAsUpIndicator]

中添加额外的代码行
  

toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);

我从Material.io下载了drawable:ic_keyboard_backspace_white_24dp

以下是完整的代码:

MainActivity.java - &gt;的onCreate()

DrawerLayout drawer;
ActionBarDrawerToggle toggle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // Start: Code automatically generated by Android Studio
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

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

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();
    // End: Code automatically generated by Android Studio

    // I had to add this listener as the "back" arrow was totally unresponsive
    // Thanks to @luca992
    toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
    });

    // Start: Code automatically generated by Android Studio
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
    // End: Code automatically generated by Android Studio

    // More custom code for other stuff
    // ...
}

MainActivity.java - &gt; setNavigationDrawerState()

public void setNavigationDrawerState(boolean isEnabled) {
if ( isEnabled ) {
    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    toggle.setDrawerIndicatorEnabled(true);
    toggle.syncState();
}
else {
    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    toggle.setDrawerIndicatorEnabled(false);
    // the extra line of code goes here
    toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);    

    toggle.syncState();
}

MainActivity.java - &gt; onBackPressed()

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        getSupportFragmentManager().popBackStack();
    }else {
        super.onBackPressed();
    }
}

MainActivity.java - &gt; startFragment()[例如虚函数]

public void startFragment(){
    MyFrag myFrag = new MyFrag();

    getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.frag_container ,myFrag)
        .addToBackStack(null)
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .commit();
}

MyFrag.java - &gt; onViewCreated()

@Override
public void onViewCreated (View view, Bundle savedInstanceState){
    super.onViewCreated(view, savedInstanceState);

    // Say, using an implemented interface Make call to MainActivitiy's  setNavigationDrawerState() passing false
    // setNavigationDrawerState(false)

    // ...
}

MyFrag.java - &gt; onDestroyView()

@Override
public void onDestroyView(){
    // Say, using an implemented interface Make call to MainActivitiy's setNavigationDrawerState() passing true 
    // setNavigationDrawerState(true)

    super.onDestroyView();
}