[英]Multiple activities (not fragments) with a NavigationDrawer. How to show currently selected Activity?
I had an application with quite a few activities before it was decided that we will be using a Navigation Drawer or a hamburger menu. 在决定要使用导航抽屉或汉堡菜单之前,我有一个包含大量活动的应用程序。 I did not want to redo the whole app using fragments so I decided to go with the approach used in this answer: Same Navigation Drawer in different Activities 我不想使用片段重做整个应用程序,因此我决定采用此答案中使用的方法: 在不同的活动中使用相同的导航抽屉
EDIT: And now, this one https://stackoverflow.com/a/23477100/1371585 编辑:现在,这个https://stackoverflow.com/a/23477100/1371585
And I created a base activity called NavDrawerBaseActivity
. 我创建了一个名为NavDrawerBaseActivity
的基本活动。 Here is the code: 这是代码:
public class NavDrawerBaseActivity extends MyBaseActivity {
public DrawerLayout mNavDrawerLayout;
public ListView mDrawerList;
public String[] mMenuItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.navdrawer_activity);
mNavDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mMenuItems = getResources().getStringArray(R.array.optionsmenu_array);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mMenuItems);
mDrawerList.setAdapter(adapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener(this));
super.onCreate(savedInstanceState);
}
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
private DrawerItemClickListener(Context context) {
mContext = context;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String textClicked = ((TextView) view).getText().toString();
view.setSelected(true);
if (textClicked.equalsIgnoreCase(mContext
.getString(R.string.optionsmenu_library))) {
Intent libraryIntent = new Intent(mContext,
LibraryActivity.class);
libraryIntent.putExtra("navdrawerposition", position);
startActivity(libraryIntent);
mNavDrawerLayout.closeDrawers();
mDrawerList.setItemChecked(position, true); //Not working
} else if (textClicked.equalsIgnoreCase(mContext
.getString(R.string.optionsmenu_settings))) {
// TODO: open activity and close the drawer
} else if (textClicked.equalsIgnoreCase(mContext
.getString(R.string.optionsmenu_logout))) {
// TODO: open activity and close the drawer
}
}
private Context mContext;
}
}
Here is the layout file navdrawer_activity.xml
这是布局文件navdrawer_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/activity_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<!-- The navigation drawer -->
<ListView
android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
/>
</android.support.v4.widget.DrawerLayout>
Every activity extends the NavDrawerBaseActivity
and does not use setContentView
, like so: 每个活动都扩展NavDrawerBaseActivity
,并且不使用setContentView
,如下所示:
public class LibraryActivity extends NavDrawerBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Not setting content view here, since its already set in
// NavDrawerBaseActivity
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.activity_frame);
// Inflating the Camera activity layout
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater
.inflate(R.layout.library_page, null, false);
// Adding the custom layout of this activity to frame layout set in
// NavDrawerBaseActivity.
frameLayout.addView(activityView);
// Only this part of the code is doing what I want.
// int drawerSelectedPosition = getIntent().getIntExtra(mNavDrawerPosExtraName, -1);
// if(drawerSelectedPosition > -1){
// mDrawerList.setItemChecked(drawerSelectedPosition, true);
// }
}
}
My problem: How do I correctly highlight the current activity in the NavDrawer View? 我的问题:如何在NavDrawer视图中正确突出显示当前活动? The mDrawerList.setItemChecked(position, true);
mDrawerList.setItemChecked(position, true);
before launching Intent or after launching it is not working. 在启动Intent之前或启动之后,它不起作用。
The weird part is: If I am currently in Activity1, Open the NavDrawer and select Activity2. 奇怪的是:如果我当前处于Activity1中,请打开NavDrawer并选择Activity2。 I land in Activity2, open the NavDrawer and see that "Activity2" is not selected. 我进入Activity2,打开NavDrawer,然后看到未选择“ Activity2”。 I click the Back button, land in Activity1, open the NavDrawer and see that "Activity2" is selected. 我单击“后退”按钮,进入Activity1,打开NavDrawer,然后看到已选择“ Activity2”。
Which means setItemChecked
works, but not in the new activity that gets launched. 这意味着setItemChecked
可以工作,但不能在启动的新活动中工作。
Currently I am passing the position as an Intent extra and specifically setting the checked position, like the commented section in LibraryActivity
. 目前,我正在将该职位作为Intent额外传递,并专门设置了选中的职位,例如LibraryActivity
的注释部分。 This works but seems like a work around. 这可行,但似乎可以解决。 Please tell me if there is a correct/better way of doing that in NavDrawerBaseActivity
class instead of in each Activity that extends it. 请告诉我,在NavDrawerBaseActivity
类中(而不是在扩展它的每个Activity中)是否有正确/更好的方法。
Do not put a nav drawer in every activity, this defeats the purpose of extending the NavDrawerBaseActivity class. 不要在每个活动中都放置一个导航抽屉,这会破坏扩展NavDrawerBaseActivity类的目的。 Because all your other activities extend this base class they should automatically inherit all its functionality. 因为您的所有其他活动都扩展了该基类,所以它们应该自动继承其所有功能。 Hence, only put the drawer in the NavDrawerBaseActivity. 因此,仅将抽屉放在NavDrawerBaseActivity中。 Then, in your xml for the drawer you can specify each buttons action like: 然后,在抽屉的xml中,您可以指定每个按钮动作,例如:
<Button
style="@style/drawerBtn"
android:id="@+id/activity1Btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick">
Or simply set an onClick listener on your drawer, something like: 或者只是在您的抽屉上设置一个onClick侦听器,例如:
myDrawer.setOnClickListener().........etc
Then in your onClick handler (which is inside the NavDrawerBaseActivity class) you can simply check which button was pressed and open the associated activity, something like: 然后,在您的onClick处理程序(位于NavDrawerBaseActivity类内部)中,您可以简单地检查按下了哪个按钮并打开关联的活动,例如:
//remember, if you used the onClickListener you have to use @Override at the top of this function
public void onClick(View item) {
//lets see which button on the drawer was pressed....item is the item that triggered the click
switch (item.getId()) {
case R.id.activity1Btn:
Intent intent1 = new Intent(this, Activity1.class);
startActivity(intent1);
break;
case R.id.activity2Btn:
Intent intent2 = new Intent(this, Activity2.class);
startActivity(intent2);
break;
case R.id.activity3Btn:
Intent intent3 = new Intent(this, Activity3.class);
startActivity(intent3);
break;
}
}
Remember that Activity1, Activity2, Activity3 will have to extend NavDrawerBaseActivity which then either have to extend Activity or extend another class which in turn extends Activity...... and so on and so forth. 请记住,Activity1,Activity2,Activity3必须扩展NavDrawerBaseActivity,然后必须扩展Activity或扩展另一个类,而后者又扩展了Activity……,依此类推。 You can then also set things like mDrawerList.setItemChecked(position, true) in this switch. 然后,您还可以在此开关中设置诸如mDrawerList.setItemChecked(position,true)之类的内容 。 So in short, make all drawer things happen in this class only and simply "implement" this class by extending it, remember this class contains all functionality that is common across all the "child" classes/activities, they all inherit this behaviour 因此,简而言之,使所有抽屉式操作仅发生在此类中,并通过扩展它简单地“实现”该类,请记住该类包含所有“子”类/活动共有的所有功能,它们都继承了此行为
EDIT: 编辑:
If you want to highlight the items in your drawer and you must rather use setSelected(true) on your item. 如果要突出显示抽屉中的项目,则必须在项目上使用setSelected(true) 。 You can define custom selection states if you want to by creating a selection style in your drawables folder. 如果需要,可以通过在drawables文件夹中创建选择样式来定义自定义选择状态。 You then set this style as the background of your list items example: 然后,您将此样式设置为列表项示例的背景:
<!-- drawable/myStyles.xml-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true" android:drawable="@color/blue"/> <!--item selected state-->
<item android:state_enabled="true" android:state_focused="true" android:drawable="@color/blue"/> <!--item selected state-->
<item android:state_enabled="true" android:state_selected="true" android:drawable="@color/blue"/> <!--item selected state-->
<item android:state_focused="false" android:state_pressed="false" android:drawable="@color/gray"/> <!--item NOT selected state-->
</selector>
and your drawer item: 和你的抽屉物品:
<LinearLayout
android:id="@+id/my_drawer_item"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@drawable/myStyles">
Then in your switch/if-else statement you set the selected item as myNewSelectedView.setSelected(true) . 然后在switch / if-else语句中,将所选项目设置为myNewSelectedView.setSelected(true) 。 You might have to manually deselect the old one like myOldSelectedItem.setSelected(false) 您可能必须手动取消选择旧的,例如myOldSelectedItem.setSelected(false)
Then click/selected listener where you have you switch/if-else statement: 然后单击/选择要在其中切换/ if-else语句的侦听器:
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
view.setSelected(true)
//....the rest of your code here
}
Lastly I recommend you try this first as this will be the easiest route to follow if you use a normal listView: 最后,我建议您首先尝试一下,因为如果使用普通的listView,这将是最简单的方法:
<ListView android:id="@+id/my_list"
android:choiceMode="singleChoice"
android:listSelector="@android:color/blue" />
EDIT2: 编辑2:
Now to retain the selected items state...So it seems that each action on the drawer reinstantiates the base class which isnt ideal. 现在要保留选定的项目状态...所以抽屉上的每个动作似乎重新实例化了不理想的基类。 We need to somehow retain the instance state so it acts almost as a singleton. 我们需要以某种方式保留实例状态,以便它几乎像一个单例。 I've tried overriding the the onSaveInstanceState and using the singleInstance launcher state but they did not work. 我尝试覆盖onSaveInstanceState并使用singleInstance启动器状态,但是它们不起作用。 So, for the interim I've come up with the solution of saving the current selection in memory as a static variable: 因此,在此期间,我想出了将当前选择保存为静态变量的解决方案:
private static int mCurrentSelectionIndex = 0; //this is defined at the top of your class with your default selected screen ie the first item in the list.
//then in setContentView after assigning the drawer layout you set the currentSelection
@Override
public void setContentView(final int layoutResID) {
//...... first assign the layouts ie mDrawerList = findViewByLayout(R.id.myDrawerList) etc
mDrawerList.setSelection(mCurrentSelectionIndex);
// OR:
mDrawerList.setItemChecked(mCurrentSelectionIndex, true);
}
//then in onClick()
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mCurrentSelection = position;
item.setSelected(true);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.