简体   繁体   English

带有NavigationDrawer的多个活动(不是片段)。 如何显示当前选择的活动?

[英]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.

相关问题 带有活动的NavigationDrawer与带有碎片的NavigationDrawer - NavigationDrawer with Activities vs. NavigationDrawer with Fragments 对多个活动使用NavigationDrawer - Use of NavigationDrawer for multiple Activities 一个活动中的多个片段或单独的活动 - Multiple fragments in one activity or separate activities 如何将NavigationDrawer从活动模板添加到其他活动? - How do I add NavigationDrawer from an activity template to other activities? 使用NavigationDrawer打开Activities而不是片段是正确的吗? - It would be correct to use the NavigationDrawer to open Activities, not fragments? 如何使用片段处理多个活动? - How to handle multiple activities with fragments? 多个活动和样式行中的NavigationDrawer - NavigationDrawer in multiple Activities and styled line 在片段中使用CoordinatorLayout和TabsLayout,在封闭的Activity中使用NavigationDrawer - Using CoordinatorLayout with TabsLayout in fragments and NavigationDrawer in the enclosing Activity 将多个预先创建的Android活动转换为带有片段的单个活动 - Turning multiple pre-created Android activities to a single activity with fragments 多步骤流中的单个活动多个片段/单独活动? - Single activity multiple fragments / separate activities in a multi-step flow?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM