カメラのプレビューサイズと、SurfaceViewのサイズについては、カメラアプリを作るときに必須なので、すでに多くのサイトで解説がなされているので、さらっとおさらい。
●カメラのプレビューサイズは、任意に決定できない。
サポートされているサイズセットの中から選ぶ
●プレビューサイズは、端末の画面サイズと同じとは限らない
(というか、一致しない方がデフォ)
●プレビューサイズを設定しても、最終的には、SurfaceViewのサイズになる。
(viewのサイズに、
ViewGroup.LayoutParams.WRAP_CONTENTを指定した場合)
なので、16:9のアスペクト比を持つ画面いっぱいのViewに、4:3のプレビューを表示すると、横に伸びた映像になる。
この辺りを、どう解決するかで、みんながググる事になる。
一般的な解決方法は、SurfaceViewを作って、レイアウトにaddView() する際に、
プレビューの比率に合わせてサイズを指定することである。
しかしこのSurfaceViewのサイズ、一旦決めたら、変更するのがなかなか難しい。
もし、画面サイズが変わる端末があったら、プレビューが見切れたりしてしまう。
そんな、恐ろしい端末が、
s5110bである!
画面下のアクションバーを(アプリ起動中でも)いつでも出し入れできるのだ。
アクションバーが消えているときは、画面一番下を横にスワイプすることで出てくる。
ちなみに画面サイズは、[800x480] [800x432]で、アクションバーの高さは48ピクセル、
割合にして、10%も変化してしまう。
アクションバーを出した状態で、カメラアプリを起動し、アクションバーを消すと、変な空白が生まれるわけだ。
この微妙な見た目に対応するためには、どうにかしてSurfaceViewのサイズを変更する必要がある。
画面サイズが変更されるので、onSizeChanged()が呼ばれるが、
名前の通り、サイズが変更"された"ときに呼ばれるメソッドだ。
ここで何をやっても何も起こらない。
そこで、見つけたのが、
onMeasure() だ。
これは、画面サイズ変更時(だけではないが)に呼ばれ、
各Viewのサイズを算出して設定するメソッドだ。
ここで取得できるサイズは、変更後の新サイズで、試しに100x100を設定したら、きちんと反映された。
まあ、自力で算出しろってことだ。
そんなこんなで、実際のコード。
カメラプレビューは、アスペクト比4:3から変更するつもりがないので、固定で書き込んでいる。
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int heightMode= MeasureSpec.getMode(heightMeasureSpec);
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int dw = w;
int dh = h;
switch(widthMode) {
case MeasureSpec.EXACTLY:// 確定
break;
case MeasureSpec.UNSPECIFIED:// 自由
dw = h *4 /3;
break;
case MeasureSpec.AT_MOST:// 以下
dw = h *4 /3;
if ( dw > w ) {
dw = w;
}
break;
}
switch(heightMode) {
case MeasureSpec.EXACTLY:// 確定
break;
case MeasureSpec.UNSPECIFIED:// 自由
break;
case MeasureSpec.AT_MOST:// 以下
dh = dw *3 /4;
if ( dh > h )
dh = h;
break;
}
//サイズ反映
setMeasuredDimension(dw, dh);
}