【问题标题】:Tool bar setNavigationOnClickListener breaks ActionbarDrawerToggle functionality工具栏 setNavigationOnClickListener 中断 ActionbarDrawerToggle 功能
【发布时间】:2015-03-31 13:36:27
【问题描述】:

我正在将操作栏换成工具栏,而且我几乎把所有的拼图都准备好了。我的问题特别是如果我“向上”导航并恢复导航抽屉,抽屉切换按钮不再起作用。我发现如果我将抽屉模式设置为解锁,我可以滑动打开抽屉,但无法点击打开抽屉。

所以我加载了片段 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()。如果我不设置这个(并通过后退按钮向上) - 抽屉行为正确。所以现在的问题是我如何正确地允许用户“向上”,并在我们向上之后恢复点击侦听器?

【问题讨论】:

    标签: android android-toolbar android-navigation


    【解决方案1】:

    我们可以使用动画。

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

    为 HAMBURGER 图标传递动作 0,为 BACK 传递动作 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();
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      就我而言,这是一个顺序问题,我需要先设置工具栏,然后设置点击监听器。按此顺序:

             //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);
      

      【讨论】:

        【解决方案3】:

        受到 Daniel Wilson 解决方案的启发,但您只需执行一次即可。

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

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

        现在每次按下android.id.home 并且不显示汉堡符号时,都会调用父活动的onBackPressed()

        【讨论】:

          【解决方案4】:

          所以我发现我创建了错误的点击监听器。而不是 setNavigationOnClickListener(),我需要setToolbarNavigationClickListener() :)

          一个微妙但重要的变化,现在工具栏的行为与 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 检查
          • 谢谢。我刚刚将您的解决方案修改为simpler one
          【解决方案5】:

          我认为你不能使用:

               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;
          }
          

          PS:别忘了使用 setHasOptionsMenu(true);在您的片段 onCreateView 中。

          【讨论】:

          • 嗨丹尼尔,感谢您的输入,这实际上是它最初的方式。几个 SO 问题似乎引用了这样一个事实,即如果您使用的是工具栏,R.id.home 将不再被解雇,这是一种耻辱。我现在在想,我需要删除对操作栏抽屉切换的任何引用,并使用活动中的导航单击侦听器触发抽屉打开
          • 嗨,这很奇怪,因为在我的项目中我正在使用工具栏,当我点击箭头图标时,通常会触发 android.R.id.home。但我可以看到,您已经找到了另一个解决方案,所以也许下次我会受到启发:)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-11
          • 1970-01-01
          • 2020-04-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多