[Android] アスペクト比が固定のビューを作成する
アスペクト比を設定すれば高さが決まる
そんなビューを作ります。
カスタムビュークラスの作成
まずはカスタムクラスを作成しましょう。
例によってコンストラクタを記述します。
/** * 高さを動的に決めるカスタムビュー * 利用する側がアスペクト比(高さ ÷ 横幅)をセットする */ public class DynamicHeightView extends View { public DynamicHeightView(Context context, AttributeSet attrs) { super(context, attrs); } }
属性の定義
res/values/attrs.xml
を作成し、aspectRatio というカスタム属性を追加します。
XML での属性追加に関してはこちらの記事をご覧ください。
<resources> <declare-styleable name="DynamicHeightView"> <attr name="aspectRatio" format="float"/> </declare-styleable> </resources>
コンストラクタの実装
作成したカスタムビューのコンストラクタに、値の取得と設定処理を実装します。
private float mAspectRatio; public DynamicHeightView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.DynamicHeightView, 0, 0); try { mAspectRatio = a.getFloat(R.styleable.DynamicHeightView_aspectRatio, 0); } finally { a.recycle(); } if (mAspectRatio < 0) mAspectRatio = 0; }
onMeasure() のオーバーライド
onMeasure() メソッドは View の高さと横幅を決定するメソッドです。
このメソッドをオーバーライドし、動的に高さを求めます。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); // *1 int heightSize = (int) (widthSize * mAspectRatio); // *2 setMeasuredDimension(widthSize, heightSize); // *3 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); super.onMeasure(widthMeasureSpec, heightMeasureSpec); // *4 }
解説
まず、引数で渡された widthMeasureSpec
からビューの横幅を取得します。(*1)
次にメンバ変数の mAspectRatio
を利用して、高さを動的に設定します。(*2)
そして setMeasuredDimension()
メソッドで、横幅と高さを決定します。(*3)
onMeasure() メソッドをオーバーライドした場合、setMeasuredDimension() は必ず実行しなければなりません。
それ以降の部分ではスーパークラスの onMeasure() に渡す MeasureSpec を作成しています。
ここではビューのサイズから正しい値の MeasureSpec を作成し、スーパークラスの onMeasure() メソッドを呼び出す必要があります。(*4)
これを行わなかった場合、ビューの表示時にレイアウトが崩れることがあるので注意しましょう。
layout xml での設定
<jp.co.ketanaka.app.dynamicheightview.view.DynamicHeightView android:layout_width="200dp" android:layout_height="0dp" android:background="#00ff00" app:aspectRatio="0.75" />
作成したカスタムビューを指定し、aspectRatio
に任意の値を設定します。
この値に x
を指定した場合、「高さは横幅の x 倍」というビューができあがります。
実行
app:aspectRatio="0.75"
(4 : 3)
app:aspectRatio="1.0"
(1 : 1)
app:aspectRatio="2.0"
(1 : 2)
リンク
ミレニアム・ファルコン製作日記 #6
6 号 表紙
パーツ
成果
今回の作業は以下の 4 つでした。
- コクピット外装を仮組みする
- コクピット後部計器パネルにステッカーを貼る
- 操作レバーを仮組みする
- コクピットの取り付け位置を確認する
今回はコクピットの回でした。
内装・外装共にパーツが多く、かなり仕上がってきたように感じます。
外装部分ではコクピット連結リングをはめ込むのにコツが必要で、なかなか苦戦しました。
ただしこれはまだ仮組みです。
ステッカーも徐々に慣れてきて、今回は綺麗に貼ることができました。
そろそろステッカーパダワンは卒業ですね。
ヨーダさん、三つ編み切っちゃってください!
操作レバーの仮組みでは指先を痛めました。
湾曲したレバー 3 つがなかなかの曲者で、前方制御コンソールの小穴に差し込むときにとても力が入れづらかったのです。
I can feel my anger.
少し見づらいですが操縦レバーが 4 つ付いているのがわかると思います。
私が商売道具の指先を痛めてまで取り付けたレバーです。
凝視してやってください。
今回からは薄刃ニッパーが必要となりました。
私は持っていないため、カッターでパーツを切り取りました。
プラスドライバーはパーツの一部として提供してくれたのですが、ニッパーは各自で用意ですか。
そうですか・・・
それではまた次回。
May the Force be with you!