![](/img/trans.png)
[英]How to switch between Fragments in default Android Studio Navigation Drawer
[英]Switch between Fragments with onNavigationItemSelected in new Navigation Drawer Activity template (Android Studio 1.4 onward)
IntelliJ在Android Studio中对Navigation Drawer模板Activity进行了更改,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)
旧的Navigation Drawer模板对此方法的定义是:
onNavigationItemSelected(int position, long itemId)
您可以通过删除内部PlaceHolderFragment
类来修改该旧模板,创建自己的片段和布局,并执行以下操作:
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();
}
但这不适用于新模板(至少不是我的小知识)。 我试过了:
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;
}
但是home
布局的布局也显示在news
布局中。 这可能是因为这条线:
transaction.replace(R.id.drawer_layout, fragment);
片段应该在FrameLayout
替换,旧的Navigation Drawer布局如下所示:
<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);
}
这是因为我希望我的用户看到的第一个视图是News.Change它为您选择的任何内容。
处理新闻事件:
就目前而言,如果您按下任何片段中的后退按钮,应用程序将退出。当用户按下后退按钮时,我希望我的应用程序返回到新闻片段(我的主片段)。 所以我这样做了:
声明了一个布尔变量:
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()
方法之外创建一个这样的新方法:
@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”中添加一个框架。
请按照以下步骤操作:
打开位于“layout”文件夹中的“content_main.xml”文件。
使用以下代码:
<?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>
转到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文件中抛出的异常
"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
找到它<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.container
的Fragment
的方式一起R.id.container
。
我使用了Android Studio 1.4自动创建的模板,我遇到了和你一样的困难。
首先,我更改了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
包含两部分:
LinearLayout
) NavigationView
) 主屏幕包含ActionBar,FrameLayout( R.id.content
)将被片段替换。 抽屉包含标题和菜单。
因此,我们现在覆盖onNavigationItemSelected并用片段替换R.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>
尝试删除以前的片段或删除所有历史记录而不是添加新片段。
//Here we are clearing back stack fragment entries
int backStackEntry = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntry > 0) {
for (int i = 0; i < backStackEntry; i++) {
getSupportFragmentManager().popBackStackImmediate();
}
}
//Here we are removing all the fragment that are shown here
if (getSupportFragmentManager().getFragments() != null && getSupportFragmentManager().getFragments().size() > 0) {
for (int i = 0; i < getSupportFragmentManager().getFragments().size(); i++) {
Fragment mFragment = getSupportFragmentManager().getFragments().get(i);
if (mFragment != null) {
getSupportFragmentManager().beginTransaction().remove(mFragment).commit();
}
}
}
从这里获得更多帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.