2013年12月20日金曜日

ActionBarを使ってみる(ActionProvider Android 2.2以上)

ActionBarのオプションメニューの動作を操作するように、ActionProviderというものが用意されています。
前回の「ActionBarを使ってみる(SearchViewを配置する Android 2.2以上) 」で
行ったActionBarの中にSearchViewとの違いは、
見え方だけではなく、メニューアイテムのデフォルトイベントも処理できるという点らしいです。

2系で実行したい場合には、次の点を気をつける必要があるみたいです。
android.support.v4.view.ActionProviderから抜粋
・メニューリソースにてルート要素に「xmlns:app="http://schemas.android.com/apk/res-auto"」を追加。
・メニューリソースにて「android:actionProviderClass='hogehoge'」は「app:actionProviderClass='hogehoge'」に書き直す。
・「MenuItem.getActionProvider()」は「MenuItemCompat.getActionProvider(MenuItem)」に書き直す。
・「MenuItem.setActionProvider(actionProvider)」は「MenuItemCompat.setActionProvider(MenuItem,actionProvider)」に書き直す。
・「MenuInflater」は「SupportMenuInflater」に書き直す。 *1

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.actionbar9"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.Light" >
        <activity
            android:name="com.example.actionbar9.MainActivity"
            android:label="@string/app_name"
            android:uiOptions="splitActionBarWhenNarrow" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
■res/menu/main.xml

オプションメニューの画面レイアウト。
Android 2系で、ActionBarにオプションメニューを表示するためには、 名前空間の「xmlns:myapp="http://schemas.android.com/apk/res-auto"」を忘れずに記述する事。
また、actionProviderClassでは、先ほど追加した名前空間を利用する事。
※Android 2系の記述で書いておけばそれ以降のバージョンでも動作する。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myapp="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/menu_custom_action_provider"
        android:showAsAction="ifRoom"
        android:title="Custom action provider"
        myapp:actionProviderClass="com.example.actionbar9.SimpleActionProvider"
        myapp:showAsAction="always"/>

</menu>
■res/menu/provider_menu.xml

オプションメニューをクリックした時に表示される画面レイアウト。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myapp="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/item1"
        android:icon="@android:drawable/ic_menu_compass"
        android:title="sub1">
    </item>
    <item
        android:id="@+id/item2"
        android:icon="@android:drawable/ic_menu_camera"
        android:title="sub2">
    </item>

</menu>
■activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

■SimpleActionProvider.java
ActionProviderを継承したクラスになります。

package com.example.actionbar9;

import android.content.Context;
import android.support.v4.view.ActionProvider;
import android.util.Log;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
import android.widget.Toast;

public class SimpleActionProvider extends ActionProvider implements
  OnMenuItemClickListener {

 private static final String TAG = "SimpleActionProvider";
 private Context mContext;

 public SimpleActionProvider(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  this.mContext = context;
 }

 /*
  * MenuItemが作成されるタイミングで呼ばれ、作成されるMenuItemに対して何か変更を加える(例えばある条件の場合だけ背景画像を変えるなど)
  * 場合に戻り値として表示させたいViewクラスのオブジェクトを指定すると、ActionBarに戻り値で返したViewが表示されるようになります
  * 
  * @see android.support.v4.view.ActionProvider#onCreateActionView()
  */
 @Override
 public View onCreateActionView() {
  return null;
 }

 /*
  * デフォルトのアクションターゲットがタップされた時に呼びされる。
  * アクティビティやフラグメントがonOptionsItemSelectedをオーバーライドしているか
  * 、アクションプロバイダーがサブメニューを実装している場合には呼び出されない。
  * 
  * @see android.support.v4.view.ActionProvider#onPerformDefaultAction()
  */
 @Override
 public boolean onPerformDefaultAction() {
  Toast.makeText(mContext, "onPerformDefaultAction", Toast.LENGTH_SHORT)
    .show();
  return super.onPerformDefaultAction();
 }

 /*
  * サブメニューがあることを伝えるためにhasSunMenu()ではtrueを返します
  * 
  * @see android.support.v4.view.ActionProvider#hasSubMenu()
  */
 @Override
 public boolean hasSubMenu() {
  return true;
 }

 /*
  * メニュー表示のたびにonPrepareSubMenu()が呼ばれるので、そこでサブメニューを作成
  * 
  * @see
  * android.support.v4.view.ActionProvider#onPrepareSubMenu(android.view.
  * SubMenu)
  */
 @Override
 public void onPrepareSubMenu(SubMenu subMenu) {

  // クリアしないとサブメニューがどんどん追加されてしまう。
  subMenu.clear();
  MenuInflater inflator = new MenuInflater(mContext);
  inflator.inflate(R.menu.provider_menu, subMenu);
  //
  for (int i = 0; i < subMenu.size(); ++i) {

   // サブメニューのアイテムを取得する
   MenuItem item = subMenu.getItem(i);

   // タイトルを設定
   item.setTitle("メニュー" + String.valueOf(i));

   // 各アイテムのクリックイベントを設定する
   item.setOnMenuItemClickListener(this);

  }
 }

 /*
  * サブメニューがクリックされたら
  * 
  * @see
  * android.view.MenuItem.OnMenuItemClickListener#onMenuItemClick(android
  * .view.MenuItem)
  */
 @Override
 public boolean onMenuItemClick(MenuItem item) {
  // TODO Auto-generated method stub

  String title = (String) item.getTitle();

  Log.d(TAG, "onMenuItemClick " + title);

  return false;
 }
}
■MainActivity.java

注意点として、上記にも書いてありますが、
Android 2系と、Android 3.0以上のもので次の点が違うので気をつける必要があります。
※Android 2系の記述で書いておけばそれ以降のバージョンでも動作する。

Android 2系の場合について。
・「MenuItem.getActionProvider()」は「MenuItemCompat.getActionProvider(MenuItem)」に書き直す。
・「MenuItem.setActionProvider(actionProvider)」は「MenuItemCompat.setActionProvider(MenuItem,actionProvider)」に書き直す。
・「MenuInflater」は「SupportMenuInflater」に書き直す。

package com.example.actionbar9;

import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.example.actionbar9.SimpleActionProvider;

public class MainActivity extends ActionBarActivity {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // action bar を取得する
  ActionBar ab = getSupportActionBar();

 }

 /*
  * メニューが生成される際に起動される。この中でメニューのアイテムを追加したりする。
  * 
  * 
  * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
  */
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {

  // メニューインフレーターを取得して、xmlのリソースファイルを使用してメニューにアイテムを追加
  getMenuInflater().inflate(R.menu.main, menu);

  // ItemのProviderを取得
  MenuItem item = menu.findItem(R.id.menu_custom_action_provider);

  // ActionProviderを継承したクラスをインスタンス化
  SimpleActionProvider actionProvider = new SimpleActionProvider(this);

  // 2系の場合
  MenuItemCompat.setActionProvider(item, actionProvider);

  return super.onCreateOptionsMenu(menu);

 }

 /*
  * オプションメニューがクリックされたら
  * 
  * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
  */
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  Toast.makeText(this, item.getTitle() + " is selected",
    Toast.LENGTH_SHORT).show();
  return super.onOptionsItemSelected(item);
 }

}
実行結果は次のようになります。


ActionBarのオプションメニューをクリックすると、次のような画面が表示されます。

同じソースコードでAndroid 4.0のエミュレーターでやってみたら、
次のような見た目で表示されてました(´・∀・`)ヘー


以上です(`・ω・´)ゞビシッ!!

参考URL

0 件のコメント:

コメントを投稿