動作環境
-
com.android.support.constraint:constraint-layout:1.1.0-beta4
-
1.0.2
では期待した動作をしませんでした
-
実現したいこと
- WebAPIからImageViewに表示する画像のURLを取得し、そのURLの画像を表示する
- WebAPIから画像のアスペクト比を取得し、画像取得前にImageViewの高さと幅をfixさせておく
- これをしないと画像表示時に画面がかくつく
- 画像の横幅の最大値は画面幅
- 画像の高さの最大値は固定値(今回の例では220dp)
実現したコード
xml
- AndroidのDataBindingを使用しています
- xmlの一部を抜粋しています
-
mainImageUrl
は画像のURLです -
mainImageSizeRatio
は幅の比率を1とした場合の高さの比率です
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<ImageView
heightForRatio="@{1}"
widthForRatio="@{mainImageSizeRatio}"
maxHeightDp="@{220}"
imageUrl="@{mainImageUrl}"
android:layout_width="match_parent"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
BindingAdapter
- アスペクト比と高さの最大値を設定するコードは以下のとおりです
-
layout_constraintWidth_max
とlayout_constraintHeight_max
を使ってみましたが期待した動きはしませんでした
@BindingAdapter("widthForRatio", "heightForRatio", "maxHeightDp")
fun View.setDimensionRatio(width: Number, height: Number, maxHeightDp: Number?) {
val ratioString = "$width:$height"
val constraintLayout = parent as ConstraintLayout
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)
constraintSet.setDimensionRatio(id, ratioString)
constraintLayout.setConstraintSet(constraintSet)
val (maxHeightPx, maxWidthPx) = if (height.toInt() == 0) {
0 to 0
} else {
maxHeightDp?.let {
val h = DpPixelConverter.toPixel(context, it)
val w = (h * width.toFloat() / height.toFloat()).toInt()
h to w
} ?: Int.MAX_VALUE to Int.MAX_VALUE
}
constraintLayout.maxHeight = maxHeightPx
/*
* maxWidthの設定がないと、maxHeightを超える縦長画像が来た場合(その他のケースもあるかもしません)に、
* Viewの高さがwidthとrationを元に設定され、maxHeightを無視されてしまいます。
* その為、widthとrationを元に計算される高さをmaxHeightに収めるためにmaxWidthを設定します。
*/
constraintLayout.maxWidth = maxWidthPx
}
参考までにimageUrlを設定するBindingAdapterも記載しておきます。
@BindingAdapter("imageUrl")
fun ImageView.loadWebImage(imageUrl: String?) {
Picasso.with(context).load(imageUrl).into(this)
}