2012/01/28

Android で View.getWidth() が 0 になる件

Activity.onCreate() とかライフサイクルの最初の方で View.getWidth() しても 0 になるのは、
結構有名どこ。
違う要因で 0 になった。


画像一枚のレイアウト。
最初は非表示で、なにか処理が始まると同時に表示して、終わったらまた非表示に。
ローディング中のイメージ。
だいぶ簡素化してみた。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!--
ローディング中に出したいので最初は隠しておく
android:visibility="gone" にしてみる
-->
<ImageView
android:id="@+id/loading_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@android:drawable/ic_popup_sync"
android:visibility="gone"/>
</RelativeLayout>
view raw gistfile1.xml hosted with ❤ by GitHub

Activity はこんな感じ。
/**
*
*/
package local.practice;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
/**
* @author peko
*
*/
public class ZeroWidthExampleActivity extends Activity {
protected ImageView _imageView;
/* (non-Javadoc)
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.zerowidthexample);
this._imageView = (ImageView)this.findViewById(R.id.loading_image);
// このタイミングで 0 になるのは想定の範囲内。
Log.v("onCreate", String.valueOf(this._imageView.getWidth()));
}
/* (non-Javadoc)
* @see android.app.Activity#onWindowFocusChanged(boolean)
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// 表示と同時にウィジェットの高さや幅を取得したいときは大抵ここで取る。
if (hasFocus) {
// ローディング中の画像を表示する
this._imageView.setVisibility(View.VISIBLE);
// 表示したら高さを取得してみる
Log.v("onWindowFocusChanged", String.valueOf(this._imageView.getWidth()));
}
super.onWindowFocusChanged(hasFocus);
}
}
view raw gistfile1.java hosted with ❤ by GitHub


onCreate() の中で getWidth() 、 getHeight() が取れないのは想定の範囲内。
でも、 onWindowFocusChanged() の中ででも取れない。

これは View の visibility が原因。
こう変える
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!--
ローディング中に出したいので最初は隠しておく
android:visibility="invisible" にしてみる
-->
<ImageView
android:id="@+id/loading_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@android:drawable/ic_popup_sync"
android:visibility="invisible"/>
</RelativeLayout>
view raw gistfile1.xml hosted with ❤ by GitHub


ConstantValueDescription
visible0Visible on screen; the default value.
invisible1Not displayed, but taken into account during layout (space is left for it).
gone2Completely hidden, as if the view had not been added.

invisible の場合は見えないけど"そこにはいる"から取得できる。
gone の場合には"いない"ので、View のプロパティ取得までにはタイムラグがあるようだ。

あまり深く考えたくないので invisible でいくことにする。