2

I am trying to dynamically set the ratio of 2 ImageViews using databinding. If a flag is true, the second ImageView's (B) visibility is set to gone and the first (A) should display in 16:9 format and expand to fill the width of the parent. If both views are supposed to be visible, they are supposed to be 1:1 and display side by side.

The problem is that the left image view, A, never displays. With the layout inspector I can verify that it exists and has a width, but it has no height.

Am I missing something? B displays as expected. If I manually set the ratio on A it displays properly.

My Binding looks like this:

@BindingAdapter("imageRatio")
fun setConstraintRatio(view: ImageView, ratio: String) {
    val constraintLayout = view.parent as ConstraintLayout
    val constraintSet = ConstraintSet()
    constraintSet.clone(constraintLayout)
    constraintSet.setDimensionRatio(view.id, ratio)
    constraintLayout.setConstraintSet(constraintSet)
}

Formatter:

val dimensionRatio: String
    get() {
        return if (showB) "1:1"
        else "H,16:9"
    }

My Layout looks like this:

<ImageView
        android:id="@+id/card_image_a"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp" android:scaleType="centerCrop"
        app:imageRatio="@{formatter.dimensionRatio}"
        app:layout_constraintEnd_toStartOf="@id/card_image_b"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/divider"
        android:visibility="visible" />

    <ImageView
        android:id="@+id/card_image_b"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        android:scaleType="centerCrop"
        app:imageRatio="@{formatter.dimensionRatio}"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/card_image_a"
        app:layout_constraintTop_toBottomOf="@id/divider"
        app:visibleOrGone="@{formatter.showImageB}"
        tools:visibility="visible" />
kira_codes
  • 1,457
  • 13
  • 38
  • Anything interesting in the logs? Also, maybe too obvious, but have to ask: is the `BindingAdapter` for `imageRatio` being called? – Xavier Rubio Jansana Apr 29 '19 at 20:56
  • Good questions, if I set a break point I do see `imageRatio` being called for each view. I'm not seeing anything noteworthy in the logs either. – kira_codes Apr 29 '19 at 21:03

1 Answers1

2

After some tests, I've realized that as your layout is already laid out, you should use constraintSet.applyTo(constraintLayout), like so:

@BindingAdapter("imageRatio")
fun setConstraintRatio(view: ImageView, ratio: String) {
    val constraintLayout = view.parent as ConstraintLayout
    val constraintSet = ConstraintSet()
    constraintSet.clone(constraintLayout)
    constraintSet.setDimensionRatio(view.id, ratio)
    constraintSet.applyTo(constraintLayout)
}

Also, I've always seen the DimensionRatio direction letter as lower case (could be another issue to be found later). So, just in case, change in your Formatter:

val dimensionRatio: String
    get() {
        return if (showB) "1:1"
        else "h,16:9"
    }

Hope this solves the issue!

Xavier Rubio Jansana
  • 6,388
  • 1
  • 27
  • 50