nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

Unity でネイティブプラグインを使って ActivityIndicator の画像変更と画面中央での表示(Android編)

はじめに

  • Unity で OS ネイティブの読み込み中アニメーションを表示するメソッドとして Handheld.StartActivityIndicator がある。
  • これは Android では画面左上に表示されてしまうので、画面中央に表示させられるようにネイティブプラグインを作ったメモ。

バージョン

ネイティブプラグインの作り方

プラグインからリソースを参照する

  • jar 形式のファイルにはリソースが含まれないため、R.id などで参照するとエラーになる
  • リソースを参照したい場合は http://sixeight.hatenablog.com/entry/2013/10/12/215456 こちらの通り、Unity の Assets/Plugins/Android/res にファイルを配置し、プラグイン側からは getResources().getIdentifier() を使って参照するとうまくいく
  • 今回はこのおかげで表示したい画像を Unity 側で差し替えやすくなったのが嬉しかった

画面中央に任意の画像の Progress Dialog を表示する

Progress Dialog の拡張クラス

  • 前記の通り R による参照を使えないので、初期化時に context から取得している
package com.example.activityindicator;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;

public class MyCustomProgressDialog extends ProgressDialog {
  private static int layoutId;
  private static int animationId;
  private static int drawableId;

  private AnimationDrawable animation;

  public static MyCustomProgressDialog ctor(Context context) {
    MyCustomProgressDialog dialog = new MyCustomProgressDialog(context);
    dialog.setIndeterminate(true);
    dialog.setCancelable(false);
    layoutId = context.getResources().getIdentifier("view_custom_progress_dialog", "layout", context.getPackageName());
    animationId = context.getResources().getIdentifier("animation", "id", context.getPackageName());
    drawableId = context.getResources().getIdentifier("custom_progress_dialog_animation", "drawable", context.getPackageName());
    return dialog;
  }

  public MyCustomProgressDialog(Context context) {
    super(context);
  }

  public MyCustomProgressDialog(Context context, int theme) {
    super(context, theme);
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(layoutId);

    ImageView la = (ImageView) findViewById(animationId);
    la.setBackgroundResource(drawableId);
    animation = (AnimationDrawable) la.getBackground();
  }

  @Override
  public void show() {
    super.show();
    animation.start();
  }

  @Override
  public void dismiss() {
    super.dismiss();
    animation.stop();
  }
}

呼び出し用クラス

package com.example.activityindicator;
import android.app.Activity;

import com.unity3d.player.UnityPlayer;

public class ActivityIndicator {

    private static MyCustomProgressDialog _dialog;

    public static void show() {
        final Activity activity = UnityPlayer.currentActivity;
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (_dialog == null) {
                    _dialog = MyCustomProgressDialog.ctor(activity);
                }
                _dialog.show();
            }
        });
    }

    public static void hide() {
        if (_dialog == null) return;
        final Activity activity = UnityPlayer.currentActivity;
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                _dialog.hide();
            }
        });
    }
}

Unity への取り込み

Unity 側のコード

    void StartActivityIndicator () {
        #if UNITY_ANDROID
        AndroidJavaClass androidNativePlugin = new AndroidJavaClass("com.example.activityindicator.ActivityIndicator");
        androidNativePlugin.CallStatic("show");
        #endif
    }

    void StopActivityIndicator () {
        #if UNITY_ANDROID
        AndroidJavaClass androidNativePlugin = new AndroidJavaClass("com.example.activityindicator.ActivityIndicator");
        androidNativePlugin.CallStatic("hide");
        #endif
    }