airbnb / epoxy

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

How to make `spanCount` dynamic when extending from `Carousel` #1282

Open ichvandi opened 2 years ago

ichvandi commented 2 years ago
fun ModelCollector.gridBuilder(builder: EpoxyGridBuilder.() -> Unit): VerticalGridCarouselModel_ {
    val verticalGridBuilder = EpoxyGridBuilder().apply { builder() }
    add(verticalGridBuilder.verticalGridModel)
    return verticalGridBuilder.verticalGridModel
}

@ModelView(saveViewState = true, autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
class VerticalGridCarousel(context: Context) : Carousel(context) {

    init {
        setBackgroundColor(Color.YELLOW)
    }

    override fun createLayoutManager(): LayoutManager {
        return GridLayoutManager(context, 2 /** <<< How to make this dynamic */, GridLayoutManager.VERTICAL, false)
    }
}

class EpoxyGridBuilder(
    internal val verticalGridModel: VerticalGridCarouselModel_ = VerticalGridCarouselModel_()
// internal val verticalGridModel: VerticalGridCarouselModel_ = VerticalGridCarouselModel_().apply {
//        spanSizeOverride { _, _, _ -> 3 }
//    }
) : ModelCollector, VerticalGridCarouselModelBuilder by verticalGridModel {
    private val models = mutableListOf<EpoxyModel<*>>()

    override fun add(model: EpoxyModel<*>) {
        models.add(model)

        // Set models list every time a model is added so that it can run debug validations to
        // ensure it is still valid to mutate the carousel model.
        verticalGridModel.models(models)
    }
}

i have tried overriding spanSizeOverride but still not working, thanks before 😄

shahzadafridi commented 2 years ago

I have done this with the help of declare-styleable attr so just check my below example. I hope this will help you.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="carousel">
        <attr name="grid_span" format="integer" />
        <attr name="grid_orientation" format="string" />
    </declare-styleable>

</resources>

I have extended the class from carousel just check attrs part where I am getting the value

@ModelView(saveViewState = true, autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
class VerticalGridCarousel @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : Carousel(context, attrs, defStyleAttr) {

    var gridSapn = 0
    var orientation: String? = "vertical"

    init {
        val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.carousel)
        gridSapn = a.getInteger(R.styleable.carousel_grid_span,3)
        orientation = a.getString(R.styleable.carousel_grid_orientation)
        a.recycle()
    }

    override fun createLayoutManager(): RecyclerView.LayoutManager {
        val orientationManager = when(orientation){
            "horizontal" ->  GridLayoutManager.HORIZONTAL
            else -> GridLayoutManager.VERTICAL
        }
        return GridLayoutManager(context, gridSapn, orientationManager, false)
    }

}

In XML just inflate that class which you extended from the carousel and with attribute grid_span you can control spans with compile-time you see in preview changes

 <com.ui.component.VerticalGridCarousel
        android:id="@+id/control_explore_bottomsheet_items"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_8"
        app:grid_span="3"/>
ichvandi commented 2 years ago

Thanks for your help @shahzadafridi, but i need the builder style 😢