Как отображать навигационный ящик во всех действиях?

У меня есть Navigation Drawer, который должен появиться во всех моих действиях.

Я видел много вопросов, подобных этому, и нашел решение, подобное расширению MainActivity с другими действиями.

Итак, я расширил мою основную деятельность до моей второй активности. Но ящик не отображается во втором действии.

MainActivity

public class MainActivity extends ActionBarActivity
{
    private ListView mDrawerList;
    private DrawerLayout mDrawer;
    private CustomActionBarDrawerToggle mDrawerToggle;
    private String[] menuItems;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
    // getSupportActionBar().hide();
    setContentView(R.layout.activity_main_drawer);

    // enable ActionBar app icon to behave as action to toggle nav drawer
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);

    mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);

    // set a custom shadow that overlays the main content when the drawer
    // opens
    mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    _initMenu();
    mDrawerToggle = new CustomActionBarDrawerToggle(this, mDrawer);
    mDrawer.setDrawerListener(mDrawerToggle);

}

private void _initMenu()
{
    NsMenuAdapter mAdapter = new NsMenuAdapter(this);

    // Add Header
    mAdapter.addHeader(R.string.ns_menu_main_header);

    // Add first block

    menuItems = getResources().getStringArray(R.array.ns_menu_items);
    String[] menuItemsIcon = getResources().getStringArray(R.array.ns_menu_items_icon);

    int res = 0;
    for (String item : menuItems)
    {

        int id_title = getResources().getIdentifier(item, "string", this.getPackageName());
        int id_icon = getResources().getIdentifier(menuItemsIcon[res], "drawable", this.getPackageName());

        NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon);
        // if (res==1) mItem.counter=12; //it is just an example...
        // if (res==3) mItem.counter=3; //it is just an example...
        mAdapter.addItem(mItem);
        res++;
    }

    mAdapter.addHeader(R.string.ns_menu_main_header2);

    mDrawerList = (ListView) findViewById(R.id.drawer);
    if (mDrawerList != null)
        mDrawerList.setAdapter(mAdapter);

    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

}

@Override
protected void onPostCreate(Bundle savedInstanceState)
{
    super.onPostCreate(savedInstanceState);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.control_menu, menu);
    return super.onCreateOptionsMenu(menu);
}

/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
    // If the nav drawer is open, hide action items related to the content
    // view
    boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerList);
    menu.findItem(R.id.action_keyboard).setVisible(!drawerOpen);
    return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    /*
     * The action bar home/up should open or close the drawer.
     * ActionBarDrawerToggle will take care of this.
     */
    if (mDrawerToggle.onOptionsItemSelected(item))
    {
        return true;
    }

    // Handle your other action bar items...
    return super.onOptionsItemSelected(item);
}

private class CustomActionBarDrawerToggle extends ActionBarDrawerToggle
{

    public CustomActionBarDrawerToggle(Activity mActivity, DrawerLayout mDrawerLayout)
    {
        super(mActivity, mDrawerLayout, R.drawable.ic_drawer, R.string.ns_menu_open, R.string.ns_menu_close);
    }

    @Override
    public void onDrawerClosed(View view)
    {
        getSupportActionBar().setTitle(getString(R.string.ns_menu_close));
        supportInvalidateOptionsMenu(); // creates call to
                                        // onPrepareOptionsMenu()
    }

    @Override
    public void onDrawerOpened(View drawerView)
    {
        getSupportActionBar().setTitle(getString(R.string.ns_menu_open));
        supportInvalidateOptionsMenu(); // creates call to
                                        // onPrepareOptionsMenu()
    }
}

private class DrawerItemClickListener implements ListView.OnItemClickListener
{

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        Intent intent = new Intent(MainActivity.this, Tutorial.class);
        startActivity(intent);

    }

}

 }

SecondActivity

 public class Tutorial extends MainActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.help);
    }

}

Ответы

Ответ 1

в onCreate of TutorialActivity не вызывайте setContentView вместо этого:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    LayoutInflater inflater = (LayoutInflater) this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View contentView = inflater.inflate(R.layout.help, null, false);
    mDrawer.addView(contentView, 0); 
}

сделать mDrawer в MainActivity защищенным. и в R.layout.activity_main_drawer просто удерживайте тег ящика и элемент с гравитацией влево (или вправо).

Ответ 2

Вот моя реализация.. надеюсь, что это поможет

FIRST, этот POST является концепцией.

SECOND, это также KEY.

НАКОНЕЦ. Вот комбинация всего ответа в одном месте.


ОСНОВНАЯ ДЕЯТЕЛЬНОСТЬ

Это базовое действие для всей другой деятельности.

Вы можете расширить действие или FragmentActivity или т.д., основываясь на своем требовании.

Navigation Drawer установите здесь один раз.

public class BaseActivity extends FragmentActivity {

    protected DrawerLayout mDrawer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.base_layout);

        mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);

        //This is about creating custom listview for navigate drawer
        //Implementation for NavigateDrawer HERE !
        ArrayList<DrawerListItem> drawerListItems = new ArrayList<DrawerListItem>();
        drawerListItems.add(new DrawerListItem(0,"AIR° DEVICES"));
        drawerListItems.add(new DrawerListItem(1,"A/C Device [1]"));
        drawerListItems.add(new DrawerListItem(1,"A/C Device [2]"));
        drawerListItems.add(new DrawerListItem(1,"A/C Device [3]"));
        drawerListItems.add(new DrawerListItem(0,"AIR° FEATURES"));
        drawerListItems.add(new DrawerListItem(2,"SLEEP MODE"));
        drawerListItems.add(new DrawerListItem(2,"TRACKING MODE"));
        drawerListItems.add(new DrawerListItem(2,"SETTINGS"));
        DrawerAdapter mDrawerAdapter = new DrawerAdapter(this, R.layout.drawer_list_header, drawerListItems);
        ListView mDrawerList = (ListView) findViewById(R.id.left_drawer);
        mDrawerList.setAdapter(mDrawerAdapter);
    }

}

ОСНОВНАЯ ДЕЯТЕЛЬНОСТЬ XML

Этот макет xml для Navigation Drawer

<?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/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

    </FrameLayout>

    <!-- The navigation drawer -->
    <ListView
            android:id="@+id/left_drawer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:scrollingCache="false"
            android:background="@drawable/drawer_bg"
            android:divider="@null"
            android:choiceMode="singleChoice"/>

</android.support.v4.widget.DrawerLayout>

ВСЕ ДРУГИЕ ДЕЯТЕЛЬНОСТИ

Другое Activity просто расширяет BaseActivity и определяет код, как показано ниже.

Navigation Drawer появится для определенной активности.

mDrawer является формой BaseActivity. это переменная protected.

public class Screen1 extends BaseActivity

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //inflate your activity layout here!
        View contentView = inflater.inflate(R.layout.screen1, null, false);
        mDrawer.addView(contentView, 0);

        //Do the rest as you want for each activity
    }

SCREEN 1 XML SAMPLE

Создайте, как хотите, каждое действие. не более Navigation Drawer Макет!

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

</LinearLayout>

Примечание

В этой реализации The Navigation Drawer не связывается с панелью действий. Если вы хотите сделать это, сделайте это в BaseActivity. Также это руководство не распространяется на все требования. Это просто образец.

Ответ 3

Я сделал активность BaseActivity, которая расширяет SherlockActivity (или ActionBarActivity, если это ваш случай)

public class BaseActivity extends SherlockActivity

Затем сделайте все ваши действия, расширяя BaseActivity, например:

public class GlossaryActivity extends BaseActivity

Позже вы должны заменить макет действия тем, который соответствует вашей активности, я сделал метод в BaseActivity:

protected void replaceContentLayout(int sourceId, int destinationId) {
    View contentLayout = findViewById(destinationId);

    ViewGroup parent = (ViewGroup) contentLayout.getParent();
    int index = parent.indexOfChild(contentLayout);

    parent.removeView(contentLayout);
    contentLayout = getLayoutInflater().inflate(sourceId, parent, false);
    parent.addView(contentLayout, index);
}

Я вызвал этот метод в методе onCreate в каждом действии:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.replaceContentLayout(R.layout.activity_glossary, super.CONTENT_LAYOUT_ID);

}

super.CONTENT_LAYOUT_ID - это FrameLayout для BaseActivity, а другой параметр - это макет, который вы хотите заменить с помощью

Ответ 4

Вы опустили @Override из производного класса onCreate.

UPDATE: Я не уверен, что эффекты вызывали setContentView дважды, но это может быть проблемой. Отделите код, который устанавливает ящик, и вызовите это из обоих методов onCreate.

Ответ 5

У меня тоже была эта проблема. Это моя реализация:

activity_main.xml - дочерний индекс в индексе 1 в CoordinatorLayout является content_main.xml, это я могу изменить в коде.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.AppBarLayout>

        **<include layout="@layout/content_main" />**

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@android:drawable/ic_dialog_email" />

    </android.support.design.widget.CoordinatorLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

Я создал класс, который использует надувание других действий UI:

public class MyLayoutInflater {

    public void inflate(Activity activity, int LayoutResource, android.app.ActionBar getSupportActionBar, Intent getIntent){
        CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator);
        android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View contentView = inflater.inflate(LayoutResource, null, false);

        //change i so that it suits the child number in you coordinator layout
        int i = 1;
        coordinatorLayout.removeViewAt(i);
        coordinatorLayout.addView(contentView, i);
        getSupportActionBar.setTitle(actionBarTitle);
    }

    public void inflate(Activity activity, int LayoutResource, android.support.v7.app.ActionBar getActionBar, String actionBarTitle){
        CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator);
        android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View contentView = inflater.inflate(LayoutResource, null, false);

        //change i so that it suits the child number in you coordinator layout
        int i = 1;
        coordinatorLayout.removeViewAt(i);
        coordinatorLayout.addView(contentView, i);
        getActionBar.setTitle(actionBarTitle);
    }

}

Теперь для остальных действий вам нужно расширить MainActivity и вызвать этот метод и предоставить ему необходимые параметры:

public class AnotherActivity extends MainActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new MyLayoutInflater().inflate(this,R.layout.content_activity_another, getSupportActionBar(), getIntent());

    }
}

Ответ 6

Хорошо, это хакерский способ сделать это, я использую его только для специального вида сборки отладки для установки свойств представлений в реальном времени (инструмент проектирования).

Преимущество состоит в том, что вы можете использовать свои дочерние действия как обычно без специального поведения, которое требуется в разных ответах.

поэтому в BaseActvity вы можете добавить:

@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);

// WARNING: Hacky, use carefully!!!
ViewGroup androidBaseView = (ViewGroup) findViewById(android.R.id.content);
//this one in what child activity has just set in setContentView()
ViewGroup childContent = (ViewGroup) androidBaseView.getChildAt(0);

View drawerView = LayoutInflater.from(this)
    .inflate(R.layout.base_activity_drawer, androidBaseView, false);
FrameLayout frameLayout = (FrameLayout) drawerView.findViewById(R.id.content);
androidBaseView.removeView(childContent);
frameLayout.addView(childContent);
androidBaseView.addView(drawerView);
}

и xml для ящика:

  <android.support.v4.widget.DrawerLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/nav_drawer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true">
  <FrameLayout
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  <LinearLayout
    android:id="@+id/drawer_for_components"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="end"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    />
</android.support.v4.widget.DrawerLayout>

Ответ 7

Вот простой и быстрый способ сделать это в Android Studio:

  1. Создайте в галерее новое действие (действие в разделе "Навигация") и назовите его как хотите. Android Studio создаст все для вас (класс и XML файлы, которые вы сможете настроить позже).

  2. В других действиях вы должны расширить действие панели навигации и убедиться, что в этих действиях нет файла "панели действий" в файле манифестов (android: theme = "@style/AppTheme.NoActionBar")

  3. Вы должны изменить ваши другие действия следующим образом:

    public class Mainactivity extends NavActivity
    {
    super.onCreate(savedInstanceState);
       LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       //inflate your activity layout here!
       View contentView = inflater.inflate(R.layout.activity_main, null, false);
       drawer.addView(contentView, 0);
    }
    

Примечание: основное действие расширит панель действий NavActivity, NavActivity имеет полнофункциональную панель действий, которая будет вызывать панель навигации

Я надеюсь, что это будет работать с вами

Ответ 8

В настоящее время вы должны использовать архитектуру приложений с одним действием (источник).

Затем просто добавьте Навигационный ящик в Основную активность

Ответ 9

Спасибо за вашу помощь в расширении макета Drawer в приложении. это было полезно и здорово. но, к сожалению, если возникли проблемы при использовании этого метода. хотя все выглядит хорошо при работе с фрагментами и ящиком, когда я нахожусь в новом действии и решаю перейти через ящик навигации и нажать на один из элементов, фрагменты загружаются при моем последнем действии. Есть ли помощь или предложение?

Я заранее ценю вашу помощь и поддержку.

С уважением