工具栏setNavigationOnClickListener破坏了ActionbarDrawerToggle的功能性。

9
我正在将操作栏替换为工具栏,现在基本上已经将所有的内容放置到正确位置。我的问题是,如果我导航“向上”并还原导航抽屉,那么抽屉切换按钮就不能正常工作了。我发现,如果将导航模式设置为解锁状态,我就可以通过滑动打开抽屉,但无法通过点击打开抽屉。
因此,我加载片段A时,导航抽屉的行为很好,转到片段B并应用向上图标,单击向上返回到A时,抽屉无法再通过单击打开了。
进入片段B:
Toolbar t = mHostingActivity.getToolbar();
        mHostingActivity.getDrawerToggle().setDrawerIndicatorEnabled(false);
        mHostingActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        t.setNavigationIcon(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());
        t.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popBackStackToTop(mHostingActivity);
            }
        });

/**
 * Pop the back stack and hide the Up caret all the way to the top level of the {@link com.loylap.activities.MainActivity}
 *
 * @param activity our hosting activity
 */
public static void popBackStackToTop(MainActivity activity) {
    if (activity != null) {
        FragmentManager fm = activity.getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        activity.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        activity.getDrawerToggle().setDrawerIndicatorEnabled(true);
    }
}

导航抽屉与示例设置方式一致,也许是设置选项的旧方法存在问题?例如,我在活动中仍然有这个:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

编辑:

好的,我已经将问题缩小到setNavigationOnClickListener()上了。如果我不设置它(并通过返回按钮向上移动)- 抽屉就会正确地工作。现在的问题是如何正确地允许用户向上移动,并在我们向上移动后恢复单击监听器?

5个回答

15

我发现我创建了错误的点击监听器。我需要使用setToolbarNavigationClickListener()而不是setNavigationOnClickListener():(参考文档) :)

这是一个微小但重要的更改,现在工具栏与v7 ActionBarDrawerToggle合作表现良好。

/**
 * Create the Up caret for a lower level fragment {@link com.loylap.activities.MainActivity}
 *
 * @param activity our hosting activity
 */
public static void createUpButton(final MainActivity activity)
{
    ActionBarDrawerToggle toggle = activity.getDrawerToggle();
    //Disables onClick toggle listener (onClick)
    toggle.setDrawerIndicatorEnabled(false);
    toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            popBackStackToTop(activity);
        }
    });

    Toolbar t = activity.getToolbar();
    t.setNavigationIcon(activity.getV7DrawerToggleDelegate().getThemeUpIndicator());
    activity.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}

只是想添加一条快速说明,我注意到在片段中不会触发onOptionsItemSelected,但对于活动似乎没问题——可以进行标准的android.R.id.home检查。 - Daniel Wilson
谢谢。我刚刚将你的解决方案修改成了一个更简单的版本(https://dev59.com/gIfca4cB1Zd3GeqPi3FX#30951016)。 - Sufian

7

在我的情况下,这是一个顺序问题,我需要先设置工具栏,然后再设置单击侦听器。按照以下顺序:

       //works
    setSupportActionBar(myToolbar);

    myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            openDrawer(view);
        }
    });

而不是这样:

    //doesn't work
    myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            openDrawer(view);
        }
    });
    setSupportActionBar(myToolbar);

5

受到 Daniel Wilson 解决方案的启发,但您只需要执行一次操作,它就会全部设置好。

在我的 NavigationDrawersetUp() 中(或者您可以在任何初始化 ActionBarDrawerToggle 实例的地方执行此操作),我编写了以下代码:

mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(!mDrawerToggle.isDrawerIndicatorEnabled()) {
            getActivity().onBackPressed();
        }
    }
});

现在,每次按下android.id.home键且汉堡菜单未显示时,会调用父活动的onBackPressed()函数。

0

我认为你不能使用:

     t.setNavigationIcon(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());
     t.setNavigationOnClickListener(new View.OnClickListener() ...

因为它会破坏您的正常导航抽屉行为。

相反,尝试在onCreateOptionsMenu(Menu menu, MenuInflater inflater)中使用类似以下的代码:

mHostingActivity.getDrawerToggle().setDrawerIndicatorEnabled(false);
mHostingActivity.getDrawerToggle().setHomeAsUpIndicator(mHostingActivity.getV7DrawerToggleDelegate().getThemeUpIndicator());

然后在onOptionsItemSelected中

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:  
        popBackStackToTop(mHostingActivity);
        return true;

    default:
        break;
    }
    return false;
}

提示:在你的Fragment的onCreateView方法中,不要忘记使用setHasOptionsMenu(true)方法。


嗨,丹尼尔,感谢您的输入,这实际上是最初的方式。几个SO问题似乎已经引用了这样一个事实,即如果您正在使用工具栏,则不再触发R.id.home,这很遗憾。我现在正在考虑需要删除对操作栏抽屉切换的任何引用,并在活动中使用导航单击侦听器触发抽屉打开。 - Daniel Wilson
1
嗨,这很奇怪,因为在我的项目中,我正在使用工具栏,当我点击箭头图标时,android.R.id.home通常会被触发。但是我可以看到,你已经找到了另一种解决方案,也许下次我会受到启发 :) - Daniel

0

我们可以使用动画效果。

ValueAnimator drawerAnimator = ValueAnimator.ofFloat(Constants.HAMBURGER, Constants.BACK);
drawerAnimator.addUpdateListener(drawerAnimationUpdateListener);
drawerAnimator.setDuration(Constants.DRAWER_ANIMATION_DURATION);
drawerAnimator.setInterpolator(new LinearInterpolator());

传递操作0以显示汉堡图标,传递操作1以显示返回图标。

public void updateNavigationDrawer(int action) {
    drawerArrowDrawable = actionBarDrawerToggle.getDrawerArrowDrawable();
    if (action == Constants.BACK) {
        actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
        actionBarDrawerToggle.setHomeAsUpIndicator(drawerArrowDrawable);
        actionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //onBackPress();
            }
        });
       drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED););
    } else {
        actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
        drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    }
    if (drawerArrowDrawable.getProgress() != action) {
        if (action == Constants.BACK) {
            drawerAnimator.start();
        } else {
            drawerAnimator.reverse();
        }
    }
}

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