airbnb / epoxy

Epoxy is an Android library for building complex screens in a RecyclerView
https://goo.gl/eIK82p
Apache License 2.0
8.46k stars 730 forks source link

The Carousel Epoxy view has an issue on first layout pass #1319

Open etiennelawlor opened 1 year ago

etiennelawlor commented 1 year ago

I have set the numViewsToShowOnScreen(3f) on an epoxy view that inherits the com.airbnb.epoxy.Carousel class and on the first layout pass it doesn't go full width

Screen Shot 2022-10-19 at 10 45 51 AM

but if you exit the feature and come back then exit it again and come back on the 3rd layout pass it goes full width

Screen Shot 2022-10-19 at 10 46 05 AM

Why won't it go full width on the first layout pass?

etiennelawlor commented 1 year ago

@viroth-ty

viroth-ty commented 1 year ago

Can you show me your code? It would be better to understand it more clearly.

etiennelawlor commented 1 year ago

Here is the code ... removed all the parts that are not relevant

// Epoxy Controller
class FooBarController @Inject constructor() : EpoxyController() {

    var data: FooBarPresentationModel? = null
        set(value) {
            field = value
            requestModelBuild()
        }

    override fun buildModels() {
        data?.let { model ->
            fooBarCarousel {
                id("fooBarCarousel")
                numViewsToShowOnScreen(3f)
                hasFixedSize(true)
                padding(Carousel.Padding.dp(24, 16, 24, 24, 16))
                models(
                    model.forEachIndexed { index, statusButton ->
                        FooBarStatusButtonModel_()
                            .id("statusButton$index")
                            .addModel(statusButton)
                    }
                )
            }
        }
    }
}

// Epoxy Models
@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
internal class FooBarCarousel constructor(context: Context?) : Carousel(context) {

}

@ModelView(autoLayout = ModelView.Size.WRAP_WIDTH_WRAP_HEIGHT)
class FooBarStatusButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : MaterialCardView(context, attrs, defStyleAttr) {

    private var model: FooBarPresentationModel? = null
    private var binding: ViewFooBarStatusButtonBinding =
        ViewFooBarStatusButtonBinding.inflate(
            LayoutInflater.from((context)),
            this
        )

    @ModelProp(options = [ModelProp.Option.IgnoreRequireHashCode])
    fun addModel(model: FooBarPresentationModel) {
        this.model = model
        // bind to views ...
    }
}

// xml layout
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:parentTag="androidx.cardview.widget.CardView">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="182dp"
        android:layout_height="100dp">

        <View
            android:id="@+id/fooBarStatusIndicatorLine"
            android:layout_width="8dp"
            android:layout_height="match_parent"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/statusLabel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"            
            app:layout_constraintBottom_toTopOf="@+id/statusShortDescription"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toEndOf="@+id/fooBarStatusIndicatorLine"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="spread_inside" />

        <TextView
            android:id="@+id/statusShortDescription"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/statusLabel"
            app:layout_constraintTop_toBottomOf="@+id/statusLabel"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</merge>
etiennelawlor commented 1 year ago

Do you have enough context now @viroth-ty ?

viroth-ty commented 1 year ago

@etiennelawlor I suggest you to view my repo Book store

etiennelawlor commented 1 year ago

so it looks like you pass in a value of 1.5 to numViewsToShowOnScreen()

https://github.com/viroth-ty/Book-shop/blob/ef430b7b2f656e1706fc729b18848c48bd2b1ca5/app/src/main/java/org/viroth/bookstore/app/view/book/BookController.kt#L64

but i need to pass in 3.

I don't think this addresses the issue of the erroneous layout rendering on the first couple of layout passes. What else is different about your implementation?

etiennelawlor commented 1 year ago

Hey @viroth-ty am i missing something else that you did in your repo?

viroth-ty commented 1 year ago

That's all from me!

etiennelawlor commented 1 year ago

Is there anyone else on the @airbnb team that has some insight into this?

etiennelawlor commented 1 year ago

@viroth-ty are there any updates on this outstanding issue?

sandrozhibosun commented 8 months ago

Encounter the same issue that I have to re-enter 3 times to have the correct width, any update on it?