4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ConstraintLayoutでアスペクト比を動的に設定し高さの最大値を設定する

Last updated at Posted at 2018-02-02

動作環境

  • 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_maxlayout_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)
}

参考にしたページ

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?