with the studio hamburger from fragments con activity android android-navigation-drawer

the - navigationview android



Alternar entre fragmentos con onNavigationItemSelected en la nueva plantilla de actividad del cajón de navegación(Android Studio 1.4 en adelante) (5)

Entonces, basado en la respuesta de @ LL, pude resolver este problema.

En primer lugar, agregue su FrameLayout a su archivo content_main.xml :

<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/content_frame"/>

En su MainActivity (o como se llame la Actividad con el cajón de navegación) defina un método llamado displayView

public void displayView(int viewId) { Fragment fragment = null; String title = getString(R.string.app_name); switch (viewId) { case R.id.nav_news: fragment = new NewsFragment(); title = "News"; break; case R.id.nav_events: fragment = new EventsFragment(); title = "Events"; break; } if (fragment != null) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.content_frame, fragment); ft.commit(); } // set the toolbar title if (getSupportActionBar() != null) { getSupportActionBar().setTitle(title); } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); }

Estoy cambiando entre 3 Fragmentos personalizados; NoticiasFragmento, EventosFragmento y GaleríaFragmento.

en mi menu activity_main_drawer he cambiado el contenido a esto:

<menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_news" android:icon="@android:drawable/ic_menu_news" android:title="News" /> <item android:id="@+id/nav_events" android:icon="@android:drawable/ic_menu_events" android:title="Events" /> <item android:id="@+id/nav_gallery" android:icon="@android:drawable/ic_menu_gallery" android:title="Gallery" /> </group> </menu>

Volviendo a la clase de actividad, en su método onNavigationItemSelected haga esto:

@Override public boolean onNavigationItemSelected(MenuItem item) { displayView(item.getItemId()); return true; }

Finalmente, la última declaración en su método onCreate:

@Override protected void onCreate(Bundle savedInstanceState) { .... .... displayView(R.id.nav_news); }

Esto se debe a que quiero que la primera vista que vea mi usuario sea Noticias. Cámbiela a lo que elija.

Manejar atrás evento de prensa:

Tal como está, si presiona el botón Atrás desde cualquiera de los Fragmentos, la aplicación sale. Quiero que mi aplicación regrese al Fragmento de Noticias (mi fragmento de inicio) cuando el usuario presione el botón Atrás. Así que hice esto:

Declarada una variable booleana:

private boolean viewIsAtHome;

Luego en el método displayView() hice esto:

public void displayView(int viewId){ Fragment fragment = null; String title = getString(R.string.app_name); switch (viewId) { case R.id.nav_news: fragment = new NewsFragment(); title = getString(R.string.news_title); viewIsAtHome = true; break; case R.id.nav_events: fragment = new EventsFragment(); title = getString(R.string.events_title); viewIsAtHome = false; break; case R.id.nav_gallery: fragment = new GalleryFragment(); title = getString(R.string.gallery_title); viewIsAtHome = false; break;

Finalmente, elimine su antiguo método onBackPressed y cree uno nuevo como este fuera del método onCreate() :

@Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } if (!viewIsAtHome) { //if the current view is not the News fragment displayView(R.id.nav_news); //display the News fragment } else { moveTaskToBack(true); //If view is in News fragment, exit application } }

Funciona para mi.

IntelliJ ha realizado cambios en la actividad de la plantilla de Navigation Drawer en Android Studio con menos líneas de código en la clase de actividad. La nueva clase de actividad se ve así:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); } @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_camara) { // Handle the camera action } else if (id == R.id.nav_gallery) { } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } }

Uno de los cambios más notables aquí es el método:

onNavigationItemSelected(MenuItem item)

La definición de este método de la vieja plantilla de Navigation Drawer era:

onNavigationItemSelected(int position, long itemId)

Puedes modificar esa plantilla antigua eliminando la clase interna PlaceHolderFragment , creando tus propios fragmentos y diseños y haciendo algo como esto:

Fragment fragment = null; switch (position) { case 0: fragment = new FragmentA(); break; case 1: fragment = new FragmentB(); break; default: break; } if (fragment != null) { FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.frame_container, fragment).commit(); }

Pero esto no funciona con la nueva plantilla (al menos no por mi poco conocimiento). Yo he tratado:

public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), item.getTitle() + " clicked", Snackbar.LENGTH_SHORT); Fragment fragment = null; switch (id) { case R.id.nav_home: fragment = HomeFragment.getFragInstance(); break; case R.id.nav_news: fragment = NewsFragment.getFragInstance(); break; default: break; } if (fragment != null) { FragmentTransaction transaction = fragmentManager.beginTransaction(); transaction.addToBackStack(null); transaction.replace(R.id.drawer_layout, fragment); transaction.commit(); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); } return true; }

pero el diseño para el diseño de home también se muestra en el diseño de news . Esto probablemente está sucediendo debido a la línea:

transaction.replace(R.id.drawer_layout, fragment);

Se supone que los fragmentos deben reemplazarse en un FrameLayout y el diseño anterior del cajón de navegación tenía este aspecto:

<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 to display Fragments --> <FrameLayout android:id="@+id/frame_container" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- Listview to display slider menu --> <ListView android:id="@+id/list_sliderMenu" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@color/white" android:dividerHeight="1dp" android:listSelector="@drawable/list_selector" android:background="@color/list_background"/>

Pero el nuevo se ve así:

<?xml version="1.0" encoding="utf-8"?> <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"> <include layout="@layout/app_bar_base" android:layout_width="match_parent" android:layout_height="match_parent" /> <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_base" app:menu="@menu/activity_base_drawer" /> </android.support.v4.widget.DrawerLayout>

En pocas palabras, ¿cómo se puede modificar la nueva plantilla para poder cambiar entre Fragmentos?


No debe cambiar DrawerLayout , solo necesita agregar un marco en el "content_main.xml".

Siga los pasos a continuación:

  1. abra el archivo "content_main.xml" ubicado en la carpeta "layout".

  2. Usa el siguiente código:

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/app_bar_main" tools:context=".MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/mainFrame"> </FrameLayout> </RelativeLayout>

  3. vaya al método onNavigationItemSelected :

    public boolean onNavigationItemSelected(MenuItem item) { int id = item.getItemId(); Fragment fragment; if (id == R.id.nav_camara) { fragment = new YourFragment(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.mainFrame, fragment); ft.commit(); } else if (id == R.id.nav_gallery) { } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; }


No estoy seguro de si podré ayudar, pero si desea modificar las plantillas de diseño para la Activity NavigationDrawer , puede encontrarlas en <Path/to/Program_Files>/Android/Android Studio/plugins/android/lib/templates/activities/NavigationDrawerActivity/root/res/layout

Creo que será mejor tener un diseño similar al siguiente:

<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. --> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}"> <!-- As the main content view, the view below consumes the entire space available using match_parent in both dimensions. --> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- android:layout_gravity="start" tells DrawerLayout to treat this as a sliding drawer on the left side for left-to-right languages and on the right side for right-to-left languages. If you''re not building against API 17 or higher, use android:layout_gravity="left" instead. --> <!-- The drawer is given a fixed width in dp and extends the full height of the container. --> <NavigationView android:id="@+id/navigation_drawer" android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent" android:layout_gravity="<#if buildApi gte 17>start<#else>left</#if>" /> </android.support.v4.widget.DrawerLayout>

Y esto funcionará con la forma en que anteriormente reemplazó los Fragment en el R.id.container .


También utilicé una plantilla creada automáticamente por Android Studio 1.4 y tuve las mismas dificultades que tú.

Primero, cambié activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <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"> <!--Main--> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- The ActionBar --> <include layout="@layout/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </LinearLayout> <!--Drawer--> <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" app:menu="@menu/drawer" /></android.support.v4.widget.DrawerLayout>

Un DrawerLayout que contiene dos partes:

  1. Pantalla principal ( LinearLayout )
  2. el cajón ( NavigationView )

La pantalla principal contiene la barra de acción y el FrameLayout ( R.id.content ) se reemplazará por un fragmento. El cajón contiene el encabezado y el menú.

Por lo tanto, ahora reemplazamos onNavigationItemSelected y reemplazamos R.id.content con un fragmento.

Aquí está mi código de MainActivity:

@Override public boolean onNavigationItemSelected(MenuItem item) { Fragment fragment; FragmentTransaction ft = getFragmentManager().beginTransaction(); // Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_A) { fragment = new AFragment(); ft.replace(R.id.content, fragment).commit(); } else if (id == R.id.nav_B){ fragment = new BFragment(); ft.replace(R.id.content, fragment).commit(); } else if (id == R.id.nav_settings) { Intent intent = new Intent(MainActivity.this, SettingsActivity.class); startActivity(intent); } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; }

La página principal también es un fragmento. Y configuro la página principal en el método onCreate , aunque no estoy seguro de si hay una mejor manera de configurar la página principal.

//MainPageFragment FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.content, new MainPageFragment()).commit();

PD. Aquí está la toolbar.xml , la barra de acción

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="jean.yang.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" 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> </android.support.design.widget.CoordinatorLayout>


otra forma es

public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. Fragment fragment; int id = item.getItemId(); if (id == R.id.nav_camera) { // Handle the camera action fragment = new BlankFragment(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.container_new, fragment); ft.commit(); } else if (id == R.id.nav_gallery) { fragment = new HorizontalView(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.container_new,fragment); ft.commit(); } else if (id == R.id.nav_slideshow) { fragment = new FragmentVerticleView(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.container_new,fragment); ft.commit(); } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; }

Y luego deberá implementar todos los fragmentos de su actividad. En mi caso es

MainActivity.java

public class MainActivity extends AppCompatActivity implements BlankFragment.OnFragmentInteractionListener, HorizontalView.OnFragmentInteractionListener,FragmentVerticleView.OnFragmentInteractionListener,OnNavigationItemSelectedListener { //coding stuff }

Y para manejar la excepción que es lanzada en el fragmento de archivo java.

"must implement OnFragmentInteractionListener"

simplemente agrega el siguiente método

public void onFragmentInteraction(Uri uri){ //We can keep this empty }

¡Y ahí tienes! Todo listo

Gracias a este tutorial para golpear esto