在新导航抽屉活动模板(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);
应该在FrameLayout
replace碎片,旧的导航抽屉布局看起来像这样:
<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”中添加一个框架。
按照以下步骤操作:
-
打开位于“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文件中引发的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.container
的Fragment
的方式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
:
- 主屏幕(
LinearLayout
) - 抽屉(
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>