当前位置: 首页 > 知识库问答 >
问题:

工具栏-只需一个活动即可从抽屉切换到后退按钮

东郭元魁
2023-03-14

我一直在搜索如何在抽屉打开/关闭图标(从汉堡到箭头)和简单的后箭头之间切换。我的html" target="_blank">应用程序目前只有一个在多个片段之间切换的活动。在某一点上,我想从一个主要片段(即抽屉中的一个片段)转换到一个层次上位于前一个片段(即“添加新”片段)之下的片段。在这个新片段中,我想让工具栏显示后退按钮,而不是抽屉按钮。

我环顾四周,尝试不同的解决方案已经有一段时间了。以下是最值得注意的:

  • 更改抽屉图标背靠背箭头-我成功地删除了抽屉图标,但在适当的地方有。。。。没有什么没有向上插入符号,没有后退按钮,没有图标。我怀疑这是因为我的活动没有父项,但除了廉价的变通(创建另一个活动,作为启动主活动的父项),我不知道该做什么
  • 当使用片段时,在Android导航抽屉图像和上插入符号之间切换——类似于上述,但有更多细节。最终,图标仍然不会变成后退按钮
  • AndroidLollipop工具栏在“打开/关闭抽屉”和“后退”按钮之间切换——我发现这很难理解,但最终抽屉图标可以被点击,并且什么都不做(尽管我相信我知道如何让它起到反按的作用)。然而,图标并没有改变

目前,我正在考虑一种漫长而艰巨的方法来创建一个自定义图标,我可以隐藏和显示它(以及隐藏/显示本机抽屉图标)。然而,有没有更好的方式在抽屉和后退按钮之间切换?

作为一个侧面但又相关的问题,我一直在看材料设计文档,有几个例子在左上角有一个X。这与实现抽屉和备份/备份按钮有多大不同?

谢谢~

编辑:

我可以找到替换图标的方法,但如何获得点击事件?

到目前为止,这是我最好的线索:

  • 无法捕获工具栏主页按钮单击事件

我现在尝试的是:

  • 必要时禁用抽屉切换(即,mDrawerToggle.setDrawerIndicatorEnabled(useDrawer)

为了更好地理解上下文,我现在有一个全屏片段,它在菜单中添加了一个“保存”按钮,并将抽屉图标更改为“X”。片段可以获得保存菜单事件,但当点击X时,甚至连活动和抽屉都无法获得。

根据要求,这里有一些代码。请注意,这都是从这个Github回购,我正在积极工作(请注意,我有一些无用的功能在这里或那里从快速测试)。

ActivityMain:

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

    // Add the toolbar
    mToolbar = (Toolbar) findViewById(R.id.toolbar);
    if (mToolbar != null) {
        setSupportActionBar(mToolbar);
    }

    // Initialize the drawer
    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);

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

    // TODO: Check if this helps to catch the main toolbar button click
    getSupportActionBar().setDisplayShowHomeEnabled(true);

    // Get the titles for the Toolbar
    mTitles = getResources().getStringArray(R.array.drawer_items);

    mDrawerPosition = -1;
    if (savedInstanceState == null) {
        // If there was no saved position, then the default, starting position should be used
        forceChangeItemSelected(0);
    }
    else {
        // Otherwise, get the saved position from the bundle
        int position = savedInstanceState.getInt(KEY_DRAWERPOS);
        mNavigationDrawerFragment.setSelectedItem(position);
        // Title needs to be re-set
        getSupportActionBar().setTitle(mTitles[position]);
    }

    // If I include the below bit, then the DrawerToggle doesn't function
        // I don't know how to switch it back and forth
    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d(LOG_TAG, "Navigation was clicked");

        }
    });
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    Log.d(LOG_TAG, "Activity responding to menu click...");
    if(item.getItemId() == android.R.id.home) Log.d(LOG_TAG, "Activity got it....");

    // If the fragment is supposed to handle things, then let it
    if(mIsFragmentHandlingMenus) return false;

    int id = item.getItemId();
    if(id == R.id.save) {
        // This isn't implemented! If chosen, then there's a bug!
        Log.e(LOG_TAG, "onOptionsItemSelected: Save was selected!");
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void fragmentHandlingMenus(boolean isFragmentHandlingMenus) {
    // Simply store the setting
    mIsFragmentHandlingMenus = isFragmentHandlingMenus;

    // Toggle the drawer as necessary
    mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus);
}

NavigationDrawer碎片:

public void toggleDrawerUse(boolean useDrawer) {
    // Enable/Disable the icon being used by the drawer
    mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);

    // TODO: Enable/Disable the drawer even being able to open/close
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d(LOGTAG, "Drawer responding to menu click...");
    if(item.getItemId() == android.R.id.home) Log.d(LOGTAG, "Drawer got it....");
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

目标添加片段:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Allow this fragment to handle toolbar menu items
    setHasOptionsMenu(true);

    // Set up the toolbar
    ((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ((ActionBarActivity) getActivity()).getSupportActionBar().setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel);
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(getResources().getString(R.string.title_addgoal));
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // Cache the Activity as the frag handler if necessary
    if(mFragHandler == null)
        mFragHandler = (TransactionHandler.FragmentTransactionHandler) getActivity();
    // Tell the Activity to let fragments handle the menu events
    mFragHandler.fragmentHandlingMenus(true);
}

@Override
public void onDetach() {
    super.onDetach();

    // Tell the Activity that it can now handle menu events once again
    mFragHandler.fragmentHandlingMenus(false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.save_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d(LOGTAG, "Item id: " + item.getItemId() + " | Save id: " + R.id.save);
    Toast.makeText(getActivity(), "Fragment activated!", Toast.LENGTH_SHORT).show();

    switch (item.getItemId()) {
        case R.id.save:
            return true;
        case android.R.id.home:
            return true;
        default:
            break;
    }

    return false;
}

这是最终的解决方案,我结束了,帮助Natario的答案如下:

NavigationDrawer碎片:

private View.OnClickListener mOriginalListener;

public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
     /* Rest of setting up code */

     // Save the default listener after setting everything else up
     mOriginalListener = mDrawerToggle.getToolbarNavigationClickListener();
}

// Tells the toolbar+drawer to switch to the up button or switch back to the normal drawer
public void toggleDrawerUse(boolean useDrawer) {
    // Enable/Disable the icon being used by the drawer
    mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);

    // Switch between the listeners as necessary
    if(useDrawer)
        mDrawerToggle.setToolbarNavigationClickListener(mOriginalListener);
    else
        mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "Custom listener", Toast.LENGTH_SHORT).show();
            }
        });
}

共有3个答案

咸弘雅
2023-03-14

这可能不是你想听到的,但即使从概念的角度来看,我也会选择一个新的活动,而不是一个片段。

你的主要活动与抽屉有严格的联系,所以在没有任何抽屉访问权限的情况下加载一个新片段对我来说毫无意义(但是如果你这样想,请随时等待其他答案)。一个新的活动可以解决这两个问题,因为它没有抽屉,可以是主活动的子代。

你的附带问题看起来也很到位。“添加新”活动可以很好地适应指南中的“全屏对话”视觉模式。见:

http://www.google.com/design/spec/components/dialogs.html#dialogs-全屏对话框

这个模式右上角有一个“保存”的正按钮和一个“X”。从概念上讲,“X”按钮是取消/中止一个进程,而不是向上导航一些后端堆栈。这意味着你在不让任何行动发生的情况下解雇了某件事。这很适合你想做的事情。

从设计的角度来看,它很容易由一个新的活动制作,可以保持在其他之上。此外,如果片段的重点基本上是能够在平板电脑和更大的屏幕上同时代表两个或更多——同样,我不会对左边的旧片段和右边的“添加新”片段感到高兴。

相反,在平板电脑上,我会按照指南的建议,选择浮动对话框。

http://www.google.com/design/spec/components/dialogs.html#dialogs-确认对话框

因此,对于手机来说,全屏活动带有X按钮,而对于平板电脑来说,则是浮动对话框(底部有按钮)。对我来说,这是最连贯的方法。

我建议阅读整个链接。之间的区别

X与向上箭头不同,向上箭头用于视图状态持续保存或应用程序具有草稿或自动保存功能时。例如,设置中使用向上箭头,因为所有更改都会立即提交。

而且还

触摸本设置示例中的X将放弃所有更改。只有触摸“保存”后,更改才会被保存。

公羊俊德
2023-03-14

即使对于最新的API 24,它也应该有效。

在您的活动中,执行以下操作:

final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
final DrawerLayout drawer = (DrawerLayout) view.findViewById(R.id.drawer_layout);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, 
    R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

final View.OnClickListener originalToolbarListener = toggle.getToolbarNavigationClickListener();

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
            toggle.setDrawerIndicatorEnabled(false);
            toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    getSupportFragmentManager().popBackStack();
                }
            });
        } else {
            toggle.setDrawerIndicatorEnabled(true);
            toggle.setToolbarNavigationClickListener(originalToolbarListener);
        }
    }
});
公孙宗清
2023-03-14

将此代码放入活动的onCreate()。对我来说很好。甚至使用编译dk 23和更高版本。

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    if(toolbar != null) {
        toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        toggle.syncState();
        drawer.setDrawerListener(toggle);
        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                    getSupportActionBar().setDisplayHomeAsUpEnabled(true); // show back button
                    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            onBackPressed();
                        }
                    });
                } else {
                    //show hamburger
                    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                    toggle.syncState();
                    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            drawer.openDrawer(GravityCompat.START);
                        }
                    });
                }
            }
        });

 类似资料:
  • 我有标准抽屉菜单,但现在我试图修改它,使用工具栏。 之前我的代码看起来像:MainActivity.java NavigationDrawerFragment.java 现在我修改了代码:MainActivity。Java语言 NavigationDrawerFragment.java 并应显示HomeUp功能: 但未显示后退箭头 我试过打电话 因此,返回箭头出现,但单击它没有效果

  • 我实现了一个自定义工具栏并将其作为操作栏。 但是,当当前片段被新片段替换时,汉堡图标不会变为后箭头。但当切换到新的活动时,返回箭头会正确出现。有人知道这里缺少什么吗? 感谢您的帮助。

  • 请帮帮我,我已经绕了几个小时了!我设置了一个抽屉菜单和一个工具栏(见下面的代码),我无法让返回/回家功能工作,因为单击它会导致打开抽屉。 这是我的主要活动,在OnCreate期间调用。 以下是我片段的OnCreateView方法中的内容。。。 抽屉菜单工作正常。更改工具栏的标题工作正常。汉堡包图标在片段中更改为向后箭头就好了...然而,每次我按下向后箭头,它都会打开抽屉...有点像抽屉的听众在向后

  • 我开始创建一个应用程序,它使用一个活动(导航抽屉)和许多片段。但我无法使用工具栏上的“后退”按钮从片段中导航回来。硬件后退按钮工作正常。我知道我需要覆盖选项ItemSelected,捕捉android。R、 id.home,检查后堆栈中是否有内容,然后弹出它。在更改片段后,“burger”按钮变为“back arrow”,但当我单击它时,选项ItemSelected将打开NavigationDra

  • 下面的代码为按钮添加缩放动画。 播放完动画后,我需要切换到其他活动。我试图建立如下逻辑: Android Studio发誓:新动画。动画监听器()

  • 我正在用导航抽屉做一个应用程序。为此,我有一个HomeActivity,它包含我导航抽屉的所有登录、菜单中的选项、视图、标题等。在这里,我设置listenerclick以获取导航元素。此侦听器接收FragmentManager,并使用开关执行以下操作: 将片段替换为我在每个开关情况下需要的片段。 在家庭布局中,我有一个框架布局和抽屉菜单。 Mi的问题是,我只有一个具有framelayout的活动,