IntelliJは、Activityクラスのコード行を減らして、Android StudioのNavigation Drawerテンプレート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;
}
}
ここで最も注目すべき変更点の1つはメソッドです。
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
で置き換えられ、古いナビゲーションドロワーレイアウトは次のようになります。
<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>
簡単に言えば、新しいテンプレートを変更してフラグメントを切り替えるにはどうすればよいですか?
だから、@ L.L。の答えに基づいて、私はこの問題を解決することができました。
まず、FrameLayoutをcontent_main.xml
ファイルに追加します。
<FrameLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent" Android:id="@+id/content_frame"/>
MainActivity
(またはナビゲーションドロワーでアクティビティに名前を付けたもの)で、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にしたいからです。
バックプレスイベントの処理:
現状では、いずれかのフラグメントから戻るボタンを押すと、アプリは終了します。ユーザーが戻るボタンを押したときに、アプリがニュースフラグメント(ホームフラグメント)に戻るようにします。だから私はこれをやった:
ブール変数を宣言しました:
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
メソッドを削除し、次のような新しいメソッドを作成しますoutside the 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
で見つけることができます。
次のようなレイアウトにするのが最善だと思います-
<!-- 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
sを置き換えていた方法で機能します。
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>
2つの部分を含む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>