工具栏
工具栏 - 仅使用一个活动从抽屉切换到后退按钮(Toolbar - Switching from drawer to back button with only one Activity)我一直在寻找如何在抽屉打开/关闭图标(从汉堡包到箭头)和简单的后退箭头之间切换的一段时间。 目前我的应用程序只有一个Activity在几个片段之间切换。 在某一时刻,我想要在一个主要片段(即抽屉中的一个片段)与一个分层位于前一个片段之下的片段(即“Add New”片段)之间进行切换。 在这个新的片段中,我想让工具栏显示后退按钮而不是抽屉按钮。
我一直在环顾四周,尝试不同的解决方案很长一段时间。 以下是最值得注意的:
将抽屉图标背对背箭头更改 - 我成功删除了抽屉图标,但在位置上......没有任何东西。 没有注意事项,没有后退按钮,没有图标。 我怀疑这是因为我的活动没有父母,但除了一个便宜的工作(创建另一个活动,充当启动主活动的父母),我迷失了该做的事情。 在使用片段时在Android导航抽屉图像和上方插入符号之间切换 - 与上面类似,但具有更多细节。 最终,该图标仍然不会变成后退按钮。 Android棒棒糖工具栏在打开/关闭抽屉和后退按钮之间切换 - 我觉得这很难遵循,但最终抽屉图标可以被挖掘并且什么也不做(尽管我相信我知道如何使它成为背部按键)。 但是,图标不会更改。目前,我正在考虑一种创建自定义图标的长而艰巨的方法,我隐藏并显示(并隐藏/显示原始抽屉图标)。 但是,是否有更好的方式在抽屉和后退按钮之间切换?
作为一个侧面相关的问题,我一直在寻找Material Design文档,并且一些例子的左上角有一个X. 实施抽屉与后退/上升按钮有何不同?
谢谢〜
编辑:
我可以弄清楚如何替换图标,但是如何获得点击事件?
到目前为止,这是我最好的领先:
无法捕捉工具栏主页按钮单击事件我现在试过的:
必要时禁用DrawerToggle(即, mDrawerToggle.setDrawerIndicatorEnabled(useDrawer); ) 在我的NavigationDrawerFragment,我的Activity以及DialogFragment中添加了onOptionsItemSelected中的日志,如果item.getItemId() == android.R.id.home为true,那么我正在测试哪些运行。 这些日志语句都没有关闭为了获得更好的上下文,我现在有一个全屏幕片段,它在菜单中添加一个“保存”按钮并将抽屉图标更改为“X”。 该片段可以获得保存菜单事件,但即使活动和抽屉在轻击X时也不能获取。
EDIT2:按要求,这是一些代码。 请注意,这一切都来自这个Github repo ,我正在积极努力(请注意,在快速测试中,我在这里或那里有几个无用功能)。
ActivityMain :
@Overrideprotected 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"); } });}@Overridepublic 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);}@Overridepublic void fragmentHandlingMenus(boolean isFragmentHandlingMenus) { // Simply store the setting mIsFragmentHandlingMenus = isFragmentHandlingMenus; // Toggle the drawer as necessary mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus);} 解:这是我最终解决的最终解决方案,在下面接受的答案的帮助下:
NavigationDrawerFragment :
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 drawerpublic 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(); } });}I've been searching for a while on how to change between the drawer open/close icon (going from a hamburger to the arrow) to a simple back arrow. My application at the moment only has one Activity which switches between several fragments. At one point, I want to transition between one of the main fragments (ie, one of the fragments in the drawer) to a fragment that hierarchically is under the previous fragment (ie, an "Add New " fragment). In this new fragment, I want to have the Toolbar to show the back button instead of the drawer button.
I've been looking around and trying different solutions for quite a while. Here are the most notable:
Change drawer icon back to back arrow - I successfully removed the drawer icon, but in place there's.... nothing. No up caret, no back button, no icon. I suspect this is because my Activity has no parent, but other than a cheap work around (create another Activity that acts as a parent which launches the main Activity), I'm at a lost of what to do. Switching between Android Navigation Drawer image and Up caret when using fragments - Similar to the above, yet has far more detail. Ultimately, the icon still doesn't turn into a back button. Android lollipop toolbar switch between open/close drawer and back button - I find this hard to follow, but ultimately the drawer icon can be tapped and does nothing (although I believe I know how to make it act as a back press). However, the icon doesn't change.At the moment, I'm thinking of a long, arduous method of creating a custom icon that I hide and show (and hide/show the native drawer icon). However, is there a better way to switch between the drawer and back buttons?
As a side yet related question, I've been looking at the Material Design docs, and a few examples have an X in the top left corner. How different is that to implement than implementing the drawer vs back/up buttons?
Thanks~
Edit:
I can figure out how to replace the icon, but how would I get the click event?
So far, this was my best lead:
Cannot catch toolbar home button click eventWhat I've tried now:
Disabled the DrawerToggle when necessary (ie, mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);) Added logs in onOptionsItemSelected in my NavigationDrawerFragment, my Activity, as well as the DialogFragment I'm currently testing which run if item.getItemId() == android.R.id.home is true. None of these log statements go offFor better context, I now have a full screen fragment which adds a "Save" button to the menu and changes the drawer icon to an "X". The fragment can get the save menu event, yet not even the Activity and Drawer can get when the X is tapped.
Edit2:As requested, here is some code. Note that this is all from this Github repo, which I'm actively working on (note that I have a few useless functions here or there from rapid testing).
ActivityMain:
@Overrideprotected 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"); } });}@Overridepublic 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);}@Overridepublic void fragmentHandlingMenus(boolean isFragmentHandlingMenus) { // Simply store the setting mIsFragmentHandlingMenus = isFragmentHandlingMenus; // Toggle the drawer as necessary mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus);}Solution:This is the ultimate solution I ended up on, with the help of the accepted answer below:
NavigationDrawerFragment:
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 drawerpublic 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(); } });} 最满意答案这可能不是你想听到的,但即使从概念的角度来看,我也会去做一个新的活动,而不是一个片段。
你的主要活动与抽屉有着紧密的联系,因此加载一个没有任何访问抽屉的新片段对我来说毫无意义(但如果你这么认为,请随时等待其他答案)。 一项新的活动将解决这两个问题,因为它没有抽屉,可能是主要的孩子。
你的侧面问题看起来也是现货。 “添加新”活动可以很好地适应指南中的“全屏对话”视觉模式。 看到:
.html#dialogs-full-screen-dialogs
这个模式有一个“保存”,右上角的正面按钮和一个X.从概念上讲,X按钮是取消/中止一个过程,而不是导航某个后台堆栈。 这意味着你在不采取任何行动的情况下解雇某人。 这适合你想要做的事情。
从设计角度来看,它很容易通过一个新的Activity ,它可以保持在其他Activity之上。 另外,如果碎片点基本上能够在平板电脑和更大的屏幕上同时表示两个或更多个 - 我再也不会对我左侧的旧片段和右侧的“添加新片段”感到满意。
相反 - 在平板电脑上 - 我会按照指导原则建议进行浮动对话。
.html#dialogs-confirmation-dialogs
因此,全屏活动时使用电话的X按钮以及平板电脑的浮动对话框(底部有按钮)。 对我而言,这是最准则一致的方法。
我建议阅读整个链接。 关于< - 和X之间的区别,
X不同于向上箭头,在视图状态不断被保存或应用程序具有草稿或自动保存功能时使用。 例如,设置中使用向上箭头,因为所有更改都立即提交。
并且
在此设置示例中触摸X将放弃所有更改。 仅在触摸保存时才会保存更改。
That's probably not what you would like to hear, but even from a conceptual point of view I would go for a new activity rather than a fragment.
Your main activity is strictly linked to the drawer, so loading a new fragment without any access to the drawer makes no sense to me (but feel free wait for other answers if you think so). A new activity would solve both problems, since it would have no drawer and could be a child of the main one.
Your side question looks spot on also. A "Add New" activity could nicely fit into the "full-screen dialog" visual pattern from the guidelines. See:
.html#dialogs-full-screen-dialogs
This pattern has a "save", positive button on top-right, and a X. Conceptually, the X button is to cancel/abort a process, rather than navigating up some backstack. It means you are dismissing something without letting any action happen. This fits well for what you want to do.
From a design point of view, it's easily made by a new Activity, that can stay on top of others. Also, if the point of fragments is basically being able to represent two or more at once in tablets and bigger screen - again - I wouldn't be so happy with an old fragment on my left and an "Add New" fragment on the right.
Rather - on tablets - I would go for a floating dialog, as suggested by the guidelines.
.html#dialogs-confirmation-dialogs
So full-screen activity with a X button for phones, and floating dialog (with buttons at the bottom) for tablets. This, to me, is the most guidelines-coherent approach.
I recommend reading the whole link. On the difference between <- and X,
The X differs from an Up arrow, which is used when the view’s state is constantly being saved or when apps have draft or autosave capabilities. For example, an Up arrow is used in Settings because all changes are committed immediately.
And also
Touching the X in this Settings example will discard all changes. Changes will be saved only upon touching Save.