在决定我们将使用导航抽屉或汉堡菜单之前,我有一个应用程序有很多活动。我不想使用片段重做整个应用程序,所以我决定采用这个答案中使用的方法: Same Navigation Drawer in different Activities
编辑:现在,这一个https://stackoverflow.com/a/23477100/1371585
我创建了一个名为NavDrawerBaseActivity
的基本活动。这是代码:
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;
}
}
这是布局文件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>
每项活动都会延伸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);
// }
}
}
我的问题:如何在NavDrawer视图中正确突出显示当前活动?
启动Intent之前或启动之后的mDrawerList.setItemChecked(position, true);
无效。
奇怪的部分是:如果我当前在Activity1中,打开NavDrawer并选择Activity2。我登陆Activity2,打开NavDrawer并看到未选中“Activity2”。我单击Back按钮,登陆Activity1,打开NavDrawer并看到“Activity2”被选中。
这意味着setItemChecked
有效,但在启动的新活动中则无效。
目前我将该职位作为Intent extra传递,并专门设置检查位置,如LibraryActivity
中的注释部分。
这有效但似乎是一种解决方法。请告诉我在NavDrawerBaseActivity
类中是否有正确/更好的方法,而不是在每个扩展它的Activity中。
答案 0 :(得分:1)
不要在每个活动中放置导航抽屉,这会破坏扩展NavDrawerBaseActivity类的目的。因为所有其他活动都扩展了这个基类,所以它们应该自动继承它的所有功能。因此,只将抽屉放在NavDrawerBaseActivity中。然后,在您的抽屉的xml中,您可以指定每个按钮操作,如:
<Button
style="@style/drawerBtn"
android:id="@+id/activity1Btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick">
或者只需在抽屉上设置onClick侦听器,例如:
myDrawer.setOnClickListener().........etc
然后在你的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;
}
}
请记住,Activity1,Activity2,Activity3必须扩展NavDrawerBaseActivity,然后必须扩展Activity或扩展另一个类,而后者又扩展Activity ......依此类推。然后,您还可以在此开关中设置 mDrawerList.setItemChecked(position,true)等内容。简而言之,让所有抽屉的东西只在这个班级中发生,而且只需简单地实现&#34;这个类通过扩展它,记住这个类包含了所有&#34; child&#34;类/活动,它们都继承了这种行为
编辑:
如果要突出显示抽屉中的项目,则必须在项目上使用 setSelected(true)。如果要在drawables文件夹中创建选择样式,可以定义自定义选择状态。然后,将此样式设置为列表项示例的背景:
<!-- 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>
和您的抽屉物品:
<LinearLayout
android:id="@+id/my_drawer_item"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@drawable/myStyles">
然后在switch / if-else语句中,将所选项目设置为 myNewSelectedView.setSelected(true)。您可能必须手动取消选择旧的 myOldSelectedItem.setSelected(false)
然后单击/选择侦听器,切换到/ if-else语句:
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
view.setSelected(true)
//....the rest of your code here
}
最后,我建议您首先尝试这个,因为如果您使用普通的listView,这将是最简单的路线:
<ListView android:id="@+id/my_list"
android:choiceMode="singleChoice"
android:listSelector="@android:color/blue" />
EDIT2:
现在保留所选项目状态......所以似乎抽屉上的每个动作都重新实现了不理想的基类。我们需要以某种方式保留实例状态,因此它几乎就像一个单例。我已尝试覆盖 onSaveInstanceState 并使用 singleInstance 启动器状态,但它们无法正常工作。因此,在过渡期间,我提出了将当前选择保存在内存中作为静态变量的解决方案:
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);
}