2013年12月23日月曜日

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

前回の「ActionBarを使ってみる(ActionProvider Android 2.2以上) 」で、
ActionProviderのサブメニューを利用して表示の方を行いましたが、
Android 2系と3系以上だと表示が若干違ったので、
どうにか3系と同じ見た目に出来ないかと探していたら、
PopupMenuというものを見つけました!(`・ω・´)シャキーン

これを使えばAndroid 2系でも同じような表示が出来るんじゃないかと思い試してみました。
PopupMenuはAPI Level 11以上から利用可能なので、
Android 2系ではサポートライブラリーを使わないといけません(´;ω;`)ブワッ

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.actionbar10"
    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.actionbar10.MainActivity"
            android:label="@string/app_name" >
            <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.actionbar10.SimpleActionProvider"
        myapp:showAsAction="always"/>
    <item
        android:id="@+id/action_settings1"
        android:orderInCategory="100"
        android:showAsAction="ifRoom"
        android:title="@string/action_settings"/>
    <item
        android:id="@+id/action_settings2"
        android:orderInCategory="100"
        android:showAsAction="ifRoom"
        android:title="@string/action_settings"/>
</menu>
■res/menu/popupmenu.xml

ActionProviderを設定したオプションメニューをクリックした時に
表示されるメニューのレイアウトになります。

画面からはみ出す場合にはどういう見た目になるか確認の為、
無駄に長くしてあります(; ・`д・´)

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

    <item
        android:id="@+id/Settings1"
        android:title="Settings1">
    </item>
    <item
        android:id="@+id/Settings2"
        android:title="Settings2">
    </item>
    <item
        android:id="@+id/Settings3"
        android:title="Settings3">
    </item>
    <item
        android:id="@+id/Settings4"
        android:title="Settings4">
    </item>
    <item
        android:id="@+id/Settings5"
        android:title="Settings5">
    </item>
    <item
        android:id="@+id/Settings6"
        android:title="Settings6">
    </item>
    <item
        android:id="@+id/Settings7"
        android:title="Settings7">
    </item>
    <item
        android:id="@+id/Settings8"
        android:title="Settings8">
    </item>
    <item
        android:id="@+id/Settings9"
        android:title="Settings9">
    </item>
    <item
        android:id="@+id/Settings10"
        android:title="Settings10">
    </item>
    <item
        android:id="@+id/Settings11"
        android:title="Settings11">
    </item>
    <item
        android:id="@+id/Settings12"
        android:title="Settings12">
    </item>
    <item
        android:id="@+id/Settings13"
        android:title="Settings13">
    </item>
    <item
        android:id="@+id/Settings14"
        android:title="Settings14">
    </item>
    <item
        android:id="@+id/Settings15"
        android:title="Settings15">
    </item>
    <item
        android:id="@+id/Settings16"
        android:title="Settings16">
    </item>
    <item
        android:id="@+id/Settings17"
        android:title="Settings17">
    </item>
    <item
        android:id="@+id/Settings18"
        android:title="Settings18">
    </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内にPopupMenuを生成する処理を記述してあります。

package com.example.actionbar10;

import android.app.Activity;
import android.content.Context;
import android.support.v4.view.ActionProvider;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.PopupMenu.OnDismissListener;
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;

public class SimpleActionProvider extends ActionProvider {

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

 // ポップアップメニューのアイテムがクリックされた時に呼ばれるイベントリスナ
 private OnMenuItemClickListener mItemClickListener = new OnMenuItemClickListener() {

  @Override
  public boolean onMenuItemClick(MenuItem item) {
   // TODO Auto-generated method stub
   Log.d("OnMenuItemClickListener",
     "onMenuItemClick id => " + item.getItemId()
       + " : title => " + item.getTitle());

   switch (item.getItemId()) {
   // クリックされたオプションメニューのidが「menu_custom_action_provider」だった場合
   case R.id.Settings1:
    Log.d("OnMenuItemClickListener", "click Settings1");
    break;
   case R.id.Settings2:
    Log.d("OnMenuItemClickListener", "click Settings2");
    break;
   }

   return false;
  }

 };
 // ポップアップメニューが非表示になる時に呼ばれるイベントリスナ
 private OnDismissListener mDismissListener = new OnDismissListener() {

  @Override
  public void onDismiss(PopupMenu arg0) {
   // TODO Auto-generated method stub
   Log.d("OnDismissListener", "onDismiss");
  }

 };

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

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

  Log.d("SimpleActionProvider", "onCreateActionView");

  // LayoutInflater を取得
  LayoutInflater layoutInflater = LayoutInflater.from(mContext);

  /*
   * popupmenuで表示されるviewに対して何かイベントなどを設定したい場合にはここで設定する
   */

  return null;
 }

 /*
  * popupmenuの生成と表示
  */
 public void showPopupMenu(Activity activity) {

  Log.d("SimpleActionProvider", "showPopupMenuEx");

  // メニューからpopupmenuを表示させるオプションメニューのIDを取得する
  View menuItemView = activity
    .findViewById(R.id.menu_custom_action_provider);

  // popupmenuをインスタンス化
  PopupMenu popupMenu = new PopupMenu(mContext, menuItemView);
  // xmlからviewを生成する
  popupMenu.inflate(R.menu.popupmenu);
  // ポップアップメニューのアイテムがクリックされた時に呼ばれるイベントリスナを取得する
  popupMenu.setOnMenuItemClickListener(mItemClickListener);
  // ポップアップメニューが非表示になる時に呼ばれるイベントリスナを設定する
  popupMenu.setOnDismissListener(mDismissListener);
  //
  popupMenu.show();

 }

}


■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.actionbar10;

import com.example.actionbar10.SimpleActionProvider;

import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.PopupMenu.OnDismissListener;
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

 private static final String TAG = "MainActivity";

 // ポップアップメニューのアイテムがクリックされた時に呼ばれるイベントリスナ
 private OnMenuItemClickListener mItemClickListener = new OnMenuItemClickListener() {

  @Override
  public boolean onMenuItemClick(MenuItem item) {
   // TODO Auto-generated method stub
   Log.d("OnMenuItemClickListener",
     "onMenuItemClick id => " + item.getItemId()
       + " : title => " + item.getTitle());

   switch (item.getItemId()) {
   // クリックされたオプションメニューのidが「menu_custom_action_provider」だった場合
   case R.id.Settings1:
    Log.d("OnMenuItemClickListener", "click Settings1");
    break;
   case R.id.Settings2:
    Log.d("OnMenuItemClickListener", "click Settings2");
    break;
   }

   return false;
  }

 };
 // ポップアップメニューが非表示になる時に呼ばれるイベントリスナ
 private OnDismissListener mDismissListener = new OnDismissListener() {

  @Override
  public void onDismiss(PopupMenu arg0) {
   // TODO Auto-generated method stub
   Log.d("OnDismissListener", "onDismiss");
  }

 };

 @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);

  return super.onCreateOptionsMenu(menu);

 }

 /*
  * オプションメニューがクリックされたら
  * 
  * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
  */
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

  Log.d(TAG, "onOptionsItemSelected title => " + item.getTitle());

  switch (item.getItemId()) {
  // クリックされたオプションメニューのidが「menu_custom_action_provider」だった場合
  case R.id.menu_custom_action_provider:

   // ActionProviderを取得する
   SimpleActionProvider actionProvider = (SimpleActionProvider) MenuItemCompat
     .getActionProvider(item);

   // popupmenuを表示する
   actionProvider.showPopupMenu(this);

  }

  return super.onOptionsItemSelected(item);

 }

}

実行結果は次のようになります。
オプションメニューをクリックすると次のように表示されます。
前回だとAndroid 2系と、3系以上で見え方に結構違いがありましが、
PopupMenuを利用する事で似たような表示にすることが出来ましたワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

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

参考URL

0 件のコメント:

コメントを投稿