Activity、Fragment、ネスティングにToolBarを使用します.

28978 ワード

ToolbarはアクションBarとして紹介します.
AndroidでToolbarをアクションBarとして使用する方法を紹介し、Fragmentと入れ子FragmentではToolbarをアクションBarとして使用する際の注意事項を紹介します.
support libraryを使ったToolbar
Androidのアクションバーはバージョンごとにいくつかの変化をするので、オリジナルのアクションバーは異なるシステムで見られます.support libraryバージョンのToolbarを使うと、さまざまなデバイスのタイプに適用されます.support libraryには常に最新のfeatureが含まれています.Androidは5.0から提供されます.v 7バージョンのToolbarを使ったら、Android 2.1(API Level 7)以上のマシンでMaterial DesignスタイルのToolbarが見られます.
ActivityでToolbarを使用します.
1.まずプロジェクトのgradleに追加する:
compile 'com.android.support:appcompat-v7:23.4.0'
2.ActivityがAppCompatActivity 3を継承することを保証する.アプリケーション設定において、Noアクションバーのテーマを使用する:
<application  android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
4.Toolbarをレイアウトに書く
<android.support.v7.widget.Toolbar  android:id="@+id/my_toolbar"  android:layout_width="match_parent"  android:layout_height="?attr/actionBarSize"  android:background="?attr/colorPrimary"  android:elevation="4dp"  android:theme="@style/ThemeOverlay.AppCompat.ActionBar"  app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
5.ActivityでToolbarをActivityに設定して、まずToolbar findを出して、set Support Action Bar方法を呼び出してToolbarを自分のアクションバーに設定すればいいです.
public class ToolbarDemoActivity extends AppCompatActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar_demo);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);
    }
}
そして自由に使えるようになりました.get Supportアクションバーでアクションバータイプのオブジェクトを取得することができます.アクションバーの方法を使います.
アクションButotonsを追加します.
定義menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto">

    <item  android:id="@+id/action_android"  android:icon="@drawable/ic_android_black_24dp"  android:title="@string/action_android"  app:showAsAction="always" />
    <item  android:id="@+id/action_favourite"  android:icon="@drawable/ic_favorite_black_24dp"  android:title="@string/action_favourite"  app:showAsAction="ifRoom" />
    <item  android:id="@+id/action_settings"  android:title="@string/action_settings"  app:showAsAction="never" />
</menu>
そしてコードの中でinflateとそのクリックイベントを処理します.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    Log.i(TAG, "onCreateOptionsMenu()");
    getMenuInflater().inflate(R.menu.menu_activity_main, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_android:
            Log.i(TAG, "action android selected");
            return true;
        case R.id.action_favourite:
            Log.i(TAG, "action favourite selected");
            return true;
        case R.id.action_settings:
            Log.i(TAG, "action settings selected");
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
上に戻るactionを追加します.
上に戻るparentのactionを追加:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_toolbar_demo);
    ButterKnife.bind(this);
    setSupportActionBar(toolbar);

    // add a left arrow to back to parent activity,
    // no need to handle action selected event, this is handled by super
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
その後はmanifestでparentを指定するだけです.
<activity  android:name=".toolbar.ToolbarDemoActivity"  android:parentActivityName=".MainActivity"></activity>
FragmentではToolbarを使用します.
FragmentではToolbarの手順とActivityを使って、FragmentレイアウトにToolbarを追加して、findして、Activityの方法を呼び出して、それをアクションBarに設定します.
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
注意ここには強い回転があります.AppComppatActivityでなければなりません.しかし、Fragmentに実行したところ、Toolbarの文字とボタンは全部Activityから送られてきました.これはActivityのonCreateOptionsMenu()だけが呼び出されたためです.しかし、Fragmentのは呼び出されていません.Fragmentにはこの文をつけます.
setHasOptionsMenu(true);
このとき、FragmentのonCreateOptionsMenu()回は異動になりますが、inflateから出たボタンとActivityのactionsを合わせて表示しました.ActivityのonCreateOptionsMenu()は前に呼び出しますので、Fragmentの表記はこうなります.
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    Log.e(TAG, "onCreateOptionsMenu()");
    menu.clear();
    inflater.inflate(R.menu.menu_parent_fragment, menu);
}
とりあえずクリアしてください.このようにボタンはFragmentで設定した自分だけです.Activityのボタンはありません.
入れ子FragmentにToolbarを使用します.
前に紹介しましたが、フラジャイティは入れ子で使用できます. Android Fragmentが使用しています.(二)ネストされたFragmentsの使用とよくあるエラーです.前のFragmentにもう一つの子を表示します.また違ったToolbarを持っています.どのような処理が必要ですか?まず、javaコードにはまだあります.
setHasOptionsMenu(true)
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
そしてメニューボタンが必要かどうかによって、オンクリエテオプロモーションMenuを上書きします.方法はinflate自身のmenuファイルでいいです.普通のFragmentでToolbarをActiverとして使ってもいいと思います.しかし、もしあなたの多くのFragmentが異なるToolbarメニューの選択項目があれば、その原理が分かりません.ちょっと混乱するかもしれませんが、その方法を説明します.
OptionsMenuメソッドの呼び出し
呼び出したら
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
Activity onCreateOptionsMenu()メソッドの呼び出しにつながるが、Activityは、FragmentがsetHasOptionsMenuを設定しているかどうかに応じて、FragmentのonCreateOptionsMenu()メソッドを呼び出し、呼び出し順序はツリーであり、階層的に呼び出し、中間にfalseがある場合はスキップする.
現在のActivityを仮定すると、Partent FragmentとChild Fragmentの中には自分のToolbarをActivityとして設定しています.Child fragmentを開く時、  onCreateOptionsMenu()の呼び出し順序は.Activity -> Parent -> Child.. この時、parentとchild fragmentはset HasOptionsMenuを設置しました.
これについては、以下のような場合があります.

-   Parent `setHasOptionsMenu(false)`, Child true,  Parent `onCreateOptionsMenu()`    ,   Child   Activity -> Child.
-   Child `setHasOptionsMenu(false)`, Parent true,    Child        Activity Parent onCreateOptionsMenu()  .
-   Parent Child   false,   Parent Child Fragment       Activity onCreateOptionsMenu()  .
child Fragmentのショー()hideの切り替えだけで、activityとparent FragmentのオンクリエーテオptionsMenu()もまた新たに入ります.この点はまだ分かりませんでした.プロジェクトで出会ったのです.menuの顕著な変化の可能性があります.invalidate menu、天気を変えてみます.
上記のメカニズムは常にToolbar上のボタンが混同される原因です.例を挙げると、ActivityとPartent Fragmentには異なるToolbarボタンがありますが、Childは文字だけで、ボタンがありません.childにmenuファイルを書く必要がないのは明らかです.child内のonCreateOptionsMenu()方法を書く必要がないです.しかし、この時はとにかく、parentのonCreateOptionsMenu()方法はいずれも呼び出されます.このようにして、私達がchildを開ける時、toolbarの上に不思議にparentの中のボタンが現れました.このような状況はどう解決しますか?parentに条件を追加できます.child fragmentがない時はinflateの仕事をします.
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    Log.e(TAG, "onCreateOptionsMenu()");
    menu.clear();
    if (getChildFragmentManager().getBackStackEntryCount() == 0) {
        inflater.inflate(R.menu.menu_parent_fragment, menu);
    }
}
また、setSupportActionBar()を除いて、もし私達がアクティブにトリガしたいならば  onCreateOptionsMenu()方法の呼び出しは、invalidateOptionsMenu()方法を用いることができる.
OptionsItem Selected()メソッドの呼び出し
Activityとその中のFragmentにoptionmentがある場合は、menu itemのidは重複しないように注意してください.クリックイベントの配布もActivityから配布されていると思いますが、child fragmentの中にオプションがあるidとActivityの中の一つのオプションのidが重複したら、Activityで処理されます.配布されません.
入れ子があるときはBackキーで処理します.
これまでの段差がない場合は、FragmentをBack Stockに加えるだけで、Backキーを押した時のpop動作はシステムが自動的に行います.child fragmentを追加した時にback stackに入れますが、backキーを押した時はまだparent fragmentをポップアップして、Activityだけが残ります.child fragmentについては、そのparentで自分で処理する必要があります.例えば、このように処理します.
Activityでは
@Override
public void onBackPressed() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(android.R.id.content);
    if (fragment instanceof ToolbarFragment) {
        if (((ToolbarFragment) fragment).onBackPressed()) {
            return;
        }
    }
    super.onBackPressed();
}
その中でToolbarFragmentは直接Activityにparent fragmentとして追加されました.parent fragmentにおいて(つまりToolbarFragmentにおいて):
public boolean onBackPressed() {
    return getChildFragmentManager().popBackStackImmediate();
}
この記事のDemoアドレス: Demo on githubのうち:Toolbar DemoActivityはToolbar Demoです.本文の住所: Android Fragmentは(四)Toolbar使用及びFragment中のToolbar処理を使用します.
参考資料
Developer Android:Training ApBar v 7.widget.Toolbar Reference v 7.Activer Bar
Guide s:action bar menu items and fragments