AndEngineでAndroidネイティブのView操作をSceneから行う

AndEngineでAndroidネイティブのView操作をSceneから行うこんにちは
Zynga Japanを12月に退職し、GeNERACEという作りたての会社でCTOやってます、村松です。
GeNERACEではAndroidのネイティブゲーム開発にAndEngine(gituhub)を使ってます。

AndEngineはとっても便利ですが、ネイティブのViewと連携させるとより便利です。
今開発中のゲームもネイティブのViewをいくつかのSceneで使っています。
その際にScene1ではいらないけど、Scene2では使いたいとかいう場合ありますよね。
これ、単純にActivityのインスタンスを取得し、対象のViewにsetVisibilityで制御出来るようで実は出来ない。

何故か。

Viewはシングルスレッドモデルです。
AndEngineのSceneはActivityとは別スレッド。
SceneでネイティブのView操作を行うとアプリが強制終了します。

その為、こんな感じに実装してみました。

  • StageScene.java(ゲーム画面のクラス)
  • public class StageScene extends GeneraceAndEngineBaseScene implements ButtonSprite.OnClickListener, IOnSceneTouchListener, IOnAreaTouchListener{
    	private void showResult() {
    		// ネイティブのViewを表示状態にしたいYO!
    		getBaseActivity().visibleNativeViewFromId(R.id.edit_text_result);
    	}
    }
    
  • GeneraceAndEngineBaseScene.java(ゲーム画面の親クラス)
  • public abstract class GeneraceAndEngineBaseScene extends Scene implements ButtonSprite.OnClickListener{
    	private GeneraceAndEngineBaseActivity baseActivity;
    	public GeneraceAndEngineBaseActivity getBaseActivity() {
    		return this.baseActivity;
    	}
    }
    
  • GeneraceAndEngineBaseActivity.java(アクティビティ制御クラス)
  • public abstract class GeneraceAndEngineBaseActivity extends SimpleLayoutGameActivity {
    	Handler goneNativeViewHandler = new Handler();
    	Handler visibleNativeViewHandler = new Handler();
    	Handler invisibleNativeViewHandler = new Handler();
    	public void goneNativeViewFromId(final int id) {
    		new Thread(new Runnable() {
    			public void run() {
    				goneNativeViewHandler.post(new Runnable() {
    					public void run() {
    						findViewById(id).setVisibility(View.GONE);
    					}
    				});
    			}
    		}).start();
    		
    	}
    	
    	public void invisibleNativeViewFromId(final int id) {
    		new Thread(new Runnable() {
    			public void run() {
    				invisibleNativeViewHandler.post(new Runnable() {
    					public void run() {
    						findViewById(id).setVisibility(View.INVISIBLE);
    					}
    				});
    			}
    		}).start();
    		
    	}
    	
    	public void visibleNativeViewFromId(final int id) {
    		new Thread(new Runnable() {
    			public void run() {
    				visibleNativeViewHandler.post(new Runnable() {
    					public void run() {
    						findViewById(id).setVisibility(View.VISIBLE);
    					}
    				});
    			}
    		}).start();
    	}
    }
    
  • 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" >
    
    	<org.andengine.opengl.view.RenderSurfaceView
    		android:id="@+id/renderview"
    		android:layout_width="fill_parent"
    		android:layout_height="fill_parent" />
    	<EditText
    		android:id="@+id/edit_text_result"
    		android:gravity="left|top"
    		android:inputType="textMultiLine"
    		android:layout_marginLeft="10dip"
    		android:layout_marginRight="10dip"
    		android:layout_marginTop="300dip"
    		android:visibility="gone"
    		android:layout_width="match_parent"
    		android:layout_height="100dip"/>
    </RelativeLayout>
    

    非同期処理とかで使う実装に似た感じ。
    なんかイマイチ綺麗じゃないなー、俺Handlerあんま好きじゃないんだよなーとか思うけど、もう今日は眠いのでこれで限界。(3:30 AMなう)
    より良い実装が浮かんだら書き換えよう。そうしよう。

    そういえば、AndEngineってZyngaのNicolas Gramlich(facebook)さんが作ってるですよね。
    Zynga Japan辞めてもなんやかんやでZyngaにお世話になることはまだまだありそうです。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です