51歳から（現52）のプログラミング 備忘 Android Toolbar (アプリBar)

#Toolbar
Toolbarを使ってonOptionsItemSelected()をactivity毎に記載する方法と、Fragmentを使ってonOptionsItemSelected()する方法について。

#Fragment不使用
##Toolbar表示まで
###androidx
manifest build.gradle dependencies implementationは、androidxのappcompatであることを確認ね

```java:
dependencies{
   ...
   implementation 'androidx.appcompat:appcompat:1.1.0'
   ...
}
```

###AppCompatActivityを拡張

```java:
public class MyActivity extends AppCompatActivity{
}
```

###manifestでNoActionBarテーマを設定
以下はandroidx未満の説明。androidxでの扱いが不明だったので、一応呪文として書いておく。

manifestの<application>要素でappcompatのNoActionBarテーマの何れかを使用するように設定すると、ネイティブのActionBarでアプリバーが使えなる、とリファレンスに書いてある。

```java:
<application
   android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
```
###Toolbarをレイアウトに追加
ConstraintLayoutだとToolbarをparentに関連付けないとエラーになるので注意

```java:
<androidx.appcompat.widget.Toolbar
   android:id="@+id/myToolbar"
   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="@sytle/ThemeOverlay.AppCompat.Light"/>

   // attr　適用してるテーマに定義されてる値を参照
   // elevation　UIの高さ。影をつける
   // popup　ポップアップ

```
##setSupportActionBar()にToolbarを渡す（ToolBar表示）
```java:
@Override
protected void onCreate(Bundle savedInstanceState){
   super.onCreate(SavedInstanceState);
   setContentView(R.layout.activity);

   Toolbar myToolbar = (Toolbar) findViewById(R.id.myToolbar);
   setSupportActionBar(myToolbar);
}

   // setSupportActionBar AppCompatActivityのmethod
```

##ToolBarアクションの追加
アプリバーの余白にアクションを表示させ、余白がなくなればオーバーフローメニューに格納する。オーバーフローメニューのみを使うように設定できる。

###menu.xmlの作成
res/menu/menu.xml
res直下にmenuディレクトリを作成し、menu.xmlを作成して配置する。

```java:res/menu/menu.xml
<menu xmlns:andoid="http://schemas.android.com/apk/res/android">

   <!-- 以下は、"お好みのアクション"の登録 -->
   <!-- OverFlowMenuに余白があれば、action Buttonを表示 -->
   <item
      android:id="@+id/action_favorite"
      android:icon="drawable/ic_favorite"
      android:title="お好み"
      app:showAsAction="ifRoom"/>

   <!-- 下はOverFlowMenuに登録 -->
   <item
      android:id="@+id/action_settings"
      android:title="アクション"
      app:showAsAction="never"/>

</menu>

      // showAsAction
      //    action ItemをAppBarに表示する、タイミング、方法を指定
      //    ifRoon スペースがある限りAppBar内に表示
      //           スペースがないとき、orderInCategory値が小さいアイテムからactionとして表示される
      //           残りはOverFlowMenuに格納
      //    never  AppBar内には配置せず、OverFlowMenu内にアイテムをリスト表示
      //    その他　withText / always / collapseActionView
```

###Action追加
AplBarのアイテムを選択する　->　Activityの onOptionsItemSelected() コールバックメソッドに、MenuItemオブジェクトを渡す -> 選択してアイテムを表示

onOptionsItemSelected()の実装では、MenuItem.getItemId()メソッドを呼び出して、選択アイテムを判別する。返されるIDはandroid:id属性の値。

```java:Activity.java
@Override
public boolean onCreateOptionsMenu(Menu menu){
   getMenuInflater().inflate(R.menu.menu,menu);
   // res の menuディレクトリのmenu.xml を ,menuに設定してインフレートする
   return true;
}

@Override 
public boolean onOptonsItemSelected(MenuItem item){
   switch(item.getItemId()){
      case R.id.action_settings:
         return true;
      case R.id.action_favorite:
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }     
}
```
##アップアクション（MainActivityに戻るアクション）
MainActivity以外のActivityのアプリバーに、アップボタンを表示させる。ユーザはアップボタンを選択するだけでMainActivityに移動できる。

manifestで親Activityを宣言し、AppBarのアップボタンを有効にする。

###Manifest 親子Activityを宣言

android:parentActivityName属性はAndroid4.1（API16）で導入。
旧バージョンのAndroidディバイスでするなら<meta-data>の名前と値のペアを定義する。ここで、Nameは、"android.support.PARENT_ACTIVITY"、値は親ActivityのName。

以下は、MainActivityと子Activityで親子関係を指定する例。

```java:manifest.java
<application ...>
   ...
   <!-- MainActicity(親Activityを持たない） -->
   <activity
      android:name="com.oldcat.sample.MainActivity"
      ...>
   </activity>
   
   <!-- MainActivityの子 -->
   <activity
      android:name="com.oldcat.sample.ChildActivity"
      android:label="ChildTitle"
      android:parentActivityName="com.oldcat.sample.MainActivity"
      >

      <!-- support4.0以下では <meta-data>で親子を指定する -->
      <meta-data
         android:name="android.support.PARENT_ACTIVITY"
         android:value="com.oldcat.sample.MainActivity"
         />
   </activity>
</application>
```
###アップボタンを有効にする
getSupportActinBar() で AppBarのユーティリティメソッド の setDisplayHomeAsUpEnabled()を呼び出してアップボタンを有効にする。

通常、<font color="#f555">子</font>Activityの作成時に、onCreate()でToolbarを設定して、アップボタンを設定する。

```java:MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState){
   super.onCreate(savedInstanceState);
   setContentView(R.layout.ChildActivity);

   Toolbar childToolbar = (Toolbar) findViewById(R.id.ChildToolbar);
   setSupportActionBar(ChildToolbar);

   ActionBar actionbar  = getSupportActionBar();
   actionbar.setDisplayHomeAsUpEnabled(true);
}
```
setDisplayHomeAsUpEnabled(true) を使えば onOptionItemSelected()でキャッチしなくても親Activityに移動できる。

#Fragment利用
##流れ
MainActivity.onCreate() -> activity_main.xml/\<fragment> -> Fragment_Toolbar.onCreateView -> fragment_toolbar.xml

```java:AndroidManifest.xml
<application
    ...
    android:theme="@style/Theme.AppCompat.Light.NoActionBar">
```

```java:MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // <- レイアウト(activity_main.xml)を呼ぶ
    }
}
```
```java:activity_main.xml
<fragment
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:id="@+id/fragmentArea"
   class="(packegeName).Fragment_Toolbar" // <- Fragment_Toolbar.classを呼ぶ
   />
```
```java:Fragment_Toolbar.java
public class Fragment_Toolbar extends Fragment{
   @Override 
   public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){

   AppCompatActivity activity = (AppCompatActivity) getActivity();
   View view = inflater.inflate(R.layout.fragment_toolbar,container.false);// <- レイアウト(fragment_toolbar)を呼びだしてインフレート！
   Toolbar toolbar = view.findViewById(R.id.toolbar);
   activity.setSupportActionBar(toolbar); // <- Toolbarをセット
   setHasOptionsMenu(true); // menuを使えるようにする
   return view;
   }

   // ToolbarにMenuを搭載する
   @Override 
   public void onCreateOptionsMenu(Menu menu,MenuInflater inflater){
      super.onCreateOptionsMenu(menu,inflater);
      inflater.inflate(R.menu.overflow_menu01,menu); // res/menu/overflow_menu01.xmlをToolbarにインフレート！
   }

   // Menu選択の分岐処理
   @Override 
   public boolean onOptionsItemSelected(MenuItem item){
      retun super.onOptionsItemSelected(item)
      switch(item.getItemId()){
         case R.id.menu01:
            return true;
         case R.id.menu02:
            return true;
         default
            return super.onOptionsItemSelected(item);
      }
   }
}
```

```java:fragment_toolbar.xml
<androidx.appcompat.widget.Toolbar
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:background="#aaa"
   android:id="@+id/toolbar"
   />
```
style.xmlでToolbarのタイトル表示、タイトルの色設定

```java:style.xml
//res/value/style.xml

<resources>
   // …
   <style name = "Toolbar" >
      <item name = "android:textColorPrimary">#fff</item>
      <item name = "title>@string/app_name</item>
   </style>
</resourced>
```

res/menu/overflow_menu01.xml

```java:overflow_menu01.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <item
      android:title="MENU01"
      android:id="@+id/menu01"
      app:showAsAction="never"
      />

   <item
      android:title="MENU02"
      android:id="@+id/menu02"
      app:showAsActoion="never"
      />
</menu>
```
Fragmentで遷移した後に戻るボタンで戻るときには、

```
transaction.replace(R.id.fragmentArea,fragment);
transaction.addToBackStack(null); // <- ここでバックスタックに入れて管理する
transaction.commit();
```
#Toolbar Style

例）

```java:res/style.xml
<resources>

    <!-- 以下のレイアウトは　Manifest　で設定   -->
    <style name="NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimaryDark">#fd0</item>
        <item name="title">@string/app_name</item>
        <item name="android:navigationBarColor">#fd0</item>
        <item name="android:textColorPrimary">#fff</item>    <!-- タイトルの色 -->
        <item name="android:textColorSecondary">#fff</item>  <!-- optionMenu印の色 -->
        <item name="android:textColor">#f70</item>           <!-- popupメニューのテキスト色 -->
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- 以下のレイアウトは　androidx.appcompat.widget.Toolbar タグで設定   -->
    <style name ="Toolbar">
        <item name="android:background">#f70</item>
    </style>

</resources>
```