この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
アスペクト比を設定すれば高さが決まる
そんなビューを作ります。
カスタムビュークラスの作成
まずはカスタムクラスを作成しましょう。
例によってコンストラクタを記述します。
/**
* 高さを動的に決めるカスタムビュー
* 利用する側がアスペクト比(高さ ÷ 横幅)をセットする
*/
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!