端末の向きを変えると異常終了

 端末の向きを変更すると異常終了する。
 作ってるアプリを起動し、「横向き(LANDSCAPE)←→縦向き(PORTRAIT)」の変更をするとアプリが異常終了するんだ。
 どうも Activity が初期化されてしまうのが原因のようだ。
 Android では画面の向きを変える際、Activity が初期化されてしまうらしい。
 それで予期しない初期化が起きて、異常終了するみたい。

 それじゃ、画面の向きを固定すればいい話し。
 でも、固定したくない場合もあるよね。
 その場合、「向きを変えても初期化しない」ようにすればいい。

Manifest の設定

 初期化しないようにするには、AndroidManifest.xml に configChanges=”orientation” を追加する。

<activity android:name=".XmSpriteView_Test"
		android:label="@string/app_name"
		android:configChanges="orientation">
</activity>

 orientation は、初期化をAndroid に任せず、アプリが行うということらしい。

 この設定は、eclipse の機能を使うと簡単に追加・設定できるよ。

1. eclipse でAndroidManifest.xml を開く

2. ウィンドウ下にある、「アプリケーション」タブをクリック

3. 設定するActivity をクリック

4. 右下のエリアにある、「Config changes」の「選択」ボタンをクリック。
 するとダイアログが出るので、その中の「orientation」をチェック。

 以上で設定が追加される。

Posted in アプリ設定, 画面. Tags: , , . 端末の向きを変えると異常終了 はコメントを受け付けていません。 »

「画面サイズ設定」ってナニよ?

 エミュレータ・ベース(VBox)で作ってたアプリを、端末で実行したら拡大表示されてしまった。
 いや、拡大表示っていうのは、正確じゃない。
 画像表示は拡大されて、ボタン等は横幅が圧縮されてしまってる。
 ちょうど、”小さな画面” に押し込まれた感じ。なんだけど…。

	VBoxの画面サイズは、800x600
	端末のタブレットも、800x600

 画面サイズは同じなのに、これはどういうことなんだろ…?

画面サイズを調べる

 原因は「端末の画面サイズ」だろうと予想がつく。
 なぜなら、ボタン等の左右端は、画面端から一定の長さを保つようにしているから。
 だから小さい画面になると、左右幅が圧迫されて横幅が小さくなってしまうんだ。
 でも前述のように、端末は800×600のハズ…。
 なにはともあれ、画面サイズをまず調べてみることにした。

 画面サイズは、下記方法で取得できる。

◆Activityの場合

	WindowManager wm = (WindowManager) getSystemService( Activity.WINDOW_SERVICE );
	Display display = wm.getDefaultDisplay();
	int width = display.getWidth();
	int height = display.getHeight();

◆Viewの場合

	WindowManager wm = (WindowManager) context.getSystemService( Context.WINDOW_SERVICE );
	Display display = wm.getDefaultDisplay();
	int width = display.getWidth();
	int height = display.getHeight();

 結果は…

	width  = 533
	height = 400

 やはり、画面サイズが小さいようだ。
 とすると、アプリ側で画面サイズの設定が必要…ということなのかな?

実は必要、画面サイズ設定(解像度設定)

 調べると、AndroidManifest.xml に supports-screens が必要らしい。
 supports-screens は、アプリでサポートしている画面解像度を設定するようだ。
 たとえば、下記のような感じ。

	<manifest xmlns:android="http://schemas.android.com/apk/res/android">
		<supports-screens
			android:largeScreens="true"
			android:normalScreens="true"
			android:smallScreens="true"
			android:anyDensity="true" />
	 </manifest>

 それぞれの意味は…

	largeScreens … ラージスクリーンのサポート
	normalScreens … ノーマルスクリーンのサポート
	smallScreens … スモールスクリーンのサポート
	anyDensity … ピクセル密度を調整可能

 ということのよう。
 これらの設定がない場合、解像度設定は、SDK Version の設定(後述)に従うらしい。
 そして、SDK Version の設定もない場合、すべてfalse となるらしい。

 supports-screens もSDK Version もない…
 その場合は、SDK 1.5相当のサポートとなり、normalScreens で動作することになる。
 つまり、「端末がlargeScreens の解像度でも、normalScreens の解像度で動作」する。
 ──今回のような「小さな画面サイズ」になってしまうようだ。

 PCに例えると、「17インチ・モニター(1024×768)で、15インチ設定(800×600)」にした感じかな。
 それと、これには逆の現象もあるらしい。
 本来、画面いっぱいに表示されるアプリが、小さく表示されてしまうようなんだ。
 原因は同じで、supports-screens もSDK Version の設定もないせいで起きるみたい。

 現在、作っているアプリは、800×480での動作を対象としている。
 なので、下記を追加したことで、画面サイズの問題はひとまず解決。

	<supports-screens
		android:largeScreens="true"
		android:anyDensity="true" />

SDK Version の設定

 前記 supports-screens とは別の設定でも、画面サイズを設定できる。
 別の設定とは、minSdkVersin もしくは targetSdkVersion の設定。
 それぞれは…

	minSdkVersino … 指定SDKバージョン以上で動作
	targetSdkVersion … 指定SDKバージョンでのみ動作

 …ということらしい。
 なので正確には、画面サイズ設定ではない。
 しかしこれらの設定をすると、SDKでサポートしている設定が supports-screens に設定されるため、同様の結果がえられるんだ。

 今回、下記を追加したことでも、画面サイズの問題は解決した。

	<uses-sdk android:minSdkVersion="4" />

※. 参考資料
http://developer.android.com/guide/practices/screens_support.html

未解決がひとつ…

 さて。
 画面サイズの問題は、supports-screens もしくは、minSdkVersion で解決した。
 けれども、「画像表示が拡大されてしまう」不具合は直らなかった。
 これはピクセル密度が関係した不具合で…
 解決方法は、またページを改めて。
 →「ピクセル密度ってナニよ?」

by the way…

 ここらへんって、基本中の基本っていうか、すごく重要なことだと思うんだけど…。
 手元にある緑本には記述が見当たらない。
 なんだかなぁ…。
 入門書だからこそ、解説してほしい事項なのになぁ。

Posted in アプリ設定, 画面. Tags: , , , , , . 「画面サイズ設定」ってナニよ? はコメントを受け付けていません。 »

ボタンの外観を変える

 ボタンの外観を変えるには、xmlで設定し、それをsetBackgroundResource() method で適用することになる。
 ※.「xmlナシ」については→XMLなしで、ボタンの外観を変える

setBackgroundResource

 引数に、設定xmlを指定するだけ。
 たとえばこんな感じ。

	but.setBackgroundResource( R.drawable.button_style );

 ※.xmlファイル名は任意

XMLの設定

 ただ単に外観を変えるだけなら、xmlの設定は必要ない。
 setBackgroundDrawable()やsetBackgroundResource() を使えばいい。
 設定xmlが必要になるのは、状態によって変化させたいとき。
 たとえば、ボタンにフォーカスが当たった、ボタンを選択された。
 これらの「状態」と、その時の「色・画像」を設定したものが、設定内容となる。

 単純に選択/非選択だけの設定ならこんな感じになる。

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

	<item android:state_focused="true">
		<color android:color="#ff00ff00" />
	</item>
	<item>
		<color android:color="#ff0000ff" />
	</item>

</selector>

 全てを設定すると、こんな感じ。

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:state_enabled="false" >
		<color android:color="#00ffffff" />
	</item>
	
	<item android:state_pressed="true" >
		<color android:color="#80ff0000" />
	</item>
	<item android:state_focused="true">
		<color android:color="#8000ff00" />
	</item>
	<item>
		<color android:color="#800000ff" />
	</item>
</selector>

 上から順に…

  • 選択できない(非活性) … 透明(白)
  • 押された瞬間 … 赤(半透明)
  • 選択された … 緑(半透明)
  • 選択されていない(通常) … 青(半透明)

 実行すると、「clickしたのに、緑色になる…」なんて風に思うかもしれない。
 でもよく見てほしい。
 clickした瞬間は赤になるハズだ。
 どうもstate_pressed は、clickした瞬間を表しているらしい。
 決定状態を作るには、リスナーのonClickでやる以外はなさそうだ。

設定は優先順位順で、itemタグのパラメータは状態を現す

 プログラム言語に読み替えると、こんな感じになる。

	if ( state_enabled == false ){
		color="#00ffffff";
	}
	else if ( state_pressed == true ){
		color="#80ff0000";
	}
	else if ( state_focused == true ){
		color="#8000ff00";
	}else{
		color="#800000ff";
	}

 なので、表記の順番には気をつけなくてはいけない。

 また、パラメータは複数つけることもできる。
 たとえば

	<item android:state_enabled="true"
		 android:state_pressed="true"
		 >
		<color android:color="#80ff0000" />
	</item>

 選択できる状態で、押された … 半透明・赤
 といった感じ。

by the way…

 色の指定には、他のxml から引用することもできる。

	<color android:color="@color/blue_t" />

 color.xml の中に記述されている、blue_t の値
 といった感じだね。
 仮設定や、色の名前でつけたい、色を統一したい、なんていうときに便利だね。

 色ではなく画像を指定したい、という場合は…
 すまないけど、他の方の解説を見てほしい。(^_^;

Posted in ボタン. Tags: , . ボタンの外観を変える はコメントを受け付けていません。 »

任意のXMLファイルの作成

 Androidアプリから、任意フォーマットのxmlを作成してみた。
 使用するのは、XmlSerializer

XmlSerializer って?

 XMLの作成には、XmlSerializerを使用しなくても行える。
 しかし、XML規格に沿って作成するには、それなりの知識も必要だし、ヘッダー等を整備するのも面倒くさい。
 XmlSerializer はそこらへんの面倒を引き受けて、XML の編集を行えるものらしい。
 また、書き込みの他に、読み込みmethod も用意されているようだ。

 ここでは書き込みのみXmlSerializer で行い、読み込みはXmlPullParser で行った。

XMLの書き出し

 書き出す内容は、以下の内容とすることにした。

	<xml? …>
	<gdat id="1">
	<Int>
	0
	</Int>
	<key>
	Kanon
	</key>
	</gdat>

 ※.xmlヘッダーは面倒なので略している。

 ソースでは以下のようになる。

//====================
// save method
//====================

	public void save( String fPath ){

		int i = 0;
		String key = "Kanon";
		//--
		
		XmlSerializer serializer = Xml.newSerializer();
		try {
			FileOutputStream os = new FileOutputStream( fPath );
			serializer.setOutput( os, "UTF-8" );
			
			serializer.startDocument("UTF-8", true);	// ヘッダー

			//<gdat id="1">
			serializer.startTag("", "gdat");
			serializer.attribute("", "id", "1" );
			//--

			//
				serializer.startTag("", "Int");	//<Int>
					serializer.text( ""+i );
				serializer.endTag("", "Int");	//</Int>
				
				serializer.startTag("", "key");	//<key>
					serializer.text( key );
				serializer.endTag("", "key");	//</key>
			//--

			serializer.endTag("", "gdat");	//</gdat>
			serializer.endDocument();	// フッター
			
			serializer.flush();	// 出力
			os.close();
		} catch (Exception e) {
		}
	}
	

 XmlSerializer は、それ自身でファイルにする能力はないようだ。
 そのため、FileOutputStream を出力先として指定している。( setOutput )
 また、出力先には、StringWriter 等も指定できる。

 編集自体は単純なので、ソースからわかるかと思う。

 編集が終われば、flush() で出力。
 FileOutputStream の出力先にファイルが作られる。

 なお、出力されたファイルを見てみると、改行コードが一切省かれていた。
 それでも機能するし、データも小さくなるからいいんだけど。(^_^;

XMLの読み込み

 読み込み方は、それぞれの効率性などから、色々とやり方が考えられる。
 サンプルでは、単純な順番読み込みをやってみた。

//====================
// load method
//====================

	public void load( String fPath ){
		
		try{
			FileInputStream is = new FileInputStream( fPath );

			XmlPullParser xmlPullParser = Xml.newPullParser();
			xmlPullParser.setInput( is, "UTF-8" );
			
			String buf_s = "";
			int buf_i = 0;
			
			Log.d( "TEST", "---- load start ----" );

			int i = xmlPullParser.next();
			if( i == XmlPullParser.START_TAG ){

				Log.d( "TEST", "Parser.getName : " +xmlPullParser.getName() );	// gat

				if ( xmlPullParser.getName().equals("gdat") ){
						buf_s = xmlPullParser.getAttributeValue( null, "id" );	// idの値
						buf_i = Integer.parseInt( buf_s );

						Log.d( "TEST", "" +buf_i );
				}
				xmlPullParser.next();

				if ( xmlPullParser.getName().equals("Int") ){	//Int
						buf_s = xmlPullParser.nextText();
						buf_i = Integer.parseInt( buf_s );

						Log.d( "TEST", "" +buf_i );
				}
				xmlPullParser.nextTag();	// -><END_TAG>
				xmlPullParser.nextTag();	// -><START_TAG>
			
				if ( xmlPullParser.getName().equals("key") ){	//key
						buf_s = xmlPullParser.nextText();

						Log.d( "TEST", "" +buf_s );
				}

			}
			Log.d( "TEST", "---- load over ----" );

			is.close();
		}catch( Exception ex ){
			Log.d( "Deb", "load error...(game data)" );
		}
		//--

	}

 非常にお莫迦なサンプルなので、実用的ではないね。(笑

 XmlPullParser は一行ごとに読み込みを行うようだ。
 next…とついているmethod は、「行送りをする」と考えていい。

	next()  … 一行送り。
	nextText()  … タグのtextを読み込み、一行送る。
	nextTag()  … 次の START_TAG か END_TAG まで送る

 getAttributeValue でタグのパラメータの値を取り出せる。
 パラメータ名の他にも、要素位置で読む方法もある。

	getAttributeValue(0)

 getName でタグの名前を取得。
 .equals で、文字列の比較を行える。
 .equals(“gdat”) だとしたら、==”gdat” と読み替えると理解しやすい。


 ここで取り上げた使用方法はほんの一例。
 他にも色々なmethod ややり方があるので、それぞれ調べてみてほしい。

Posted in File, XML. Tags: , , . 任意のXMLファイルの作成 はコメントを受け付けていません。 »