在新导航抽屉活动模板(Android Studio 1.4以上版本)中使用onNavigationItemSelected在片段之间切换

IntelliJ使用Activity Studio中更less的代码行对Android Studio中的导航抽屉模板Activity进行了更改。 新的Activity类看起来像这样:

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; } } 

其中最显着的变化之一是方法:

onNavigationItemSelected(MenuItem item)

旧的导航抽屉模板对此方法的定义是:

onNavigationItemSelected(int position, long itemId)

您可以通过删除内部的PlaceHolderFragment类来修改旧的模板,创build自己的片段和布局,并执行如下操作:

 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(); } 

但这不适用于新的模板(至less不是从我的小知识)。 我努力了:

  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; } 

但是news布局中也显示了home布局的布局。 这可能是因为这一行:

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

应该在FrameLayoutreplace碎片,旧的导航抽屉布局看起来像这样:

 <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"/> 

但新的看起来像这样:

  <?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> 

长话短说,如何修改新模板以便能够在碎片之间切换?

所以,基于@LL的答案,我能够解决这个问题。

首先,将你的FrameLayout添加到你的content_main.xml文件中:

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

在你的MainActivity (或者任何你已经用导航抽屉命名了Activity)中定义了一个名为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); } 

我在3个自定义片段之间切换; NewsFragment,EventsFragment和GalleryFragment。

在我的菜单activity_main_drawer我已经改变了这个内容:

 <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> 

回到Activity类,在你的onNavigationItemSelected方法中做到这一点:

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

最后,在onCreate方法中的最后一个语句:

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

这是因为我想要我的用户看到的第一个视图是新闻。将其更改为任何您select的。

处理新闻事件:

就目前而言,如果您按下任何片段的后退button,应用程序将退出。当用户按下后退button时,我希望我的应用程序返回到News Fragment(我的家庭片段)。 所以我这样做了:

声明了一个布尔variables:

 private boolean viewIsAtHome; 

然后在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 = 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; 

最后,删除旧的onBackPressed方法,并在onCreate()方法之外创build一个像这样的新方法:

 @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 } } 

为我工作。

您不应该更改DrawerLayout ,您只需要在“content_main.xml”中添加一个框架。

按照以下步骤操作:

  1. 打开位于“layout”文件夹中的“content_main.xml”文件。

  2. 使用下面的代码:

     <?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. 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; } 

另一种方法是:

 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; } 

然后你需要实现所有的片段到你的活动。 在我的情况下

MainActivity.java

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

并处理碎片java文件中引发的exception

  "must implement OnFragmentInteractionListener" 

你只需添加下面的方法

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

你去了! 可以了,好了

感谢这个教程来解决这个问题

不知道是否能够帮助,但是如果你想修改NavigationDrawer Activity的布局模板,你可以在<Path\to\Program_Files>\Android\Android Studio\plugins\android\lib\templates\activities\NavigationDrawerActivity\root\res\layout

我相信,最好是有一个类似于以下的布局 –

 <!-- 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> 

这将与您在之前更换R.id.containerFragment的方式R.id.container

我也使用了由Android Studio 1.4自动创build的模板,而且我遇到了和你一样的困难。

首先,我更改了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> 

包含两部分的DrawerLayout

  1. 主屏幕( LinearLayout
  2. 抽屉( NavigationView

主屏幕包含ActionBar和FrameLayout( R.id.content )将被replace为一个片段。 抽屉包含标题和菜单。

所以,我们现在重写onNavigationItemSelected并用一个片段replaceR.id.content

这是我的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; } 

主页也是一个片段。 而且我在onCreate方法中设置了主页面,虽然我不确定是否有更好的方法来设置主页面。

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

PS。 这里是toolbar.xml ,ActionBar

 <?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>