All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.androidx.compose.foundation.lazy.LazyItemScopeImpl.kt Maven / Gradle / Ivy

/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.compose.foundation.lazy

import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.foundation.lazy.layout.LazyLayoutAnimateItemElement
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.util.fastRoundToInt

internal class LazyItemScopeImpl : LazyItemScope {

    private var maxWidthState = mutableIntStateOf(Int.MAX_VALUE)
    private var maxHeightState = mutableIntStateOf(Int.MAX_VALUE)

    fun setMaxSize(width: Int, height: Int) {
        maxWidthState.intValue = width
        maxHeightState.intValue = height
    }

    override fun Modifier.fillParentMaxSize(fraction: Float) = then(
        ParentSizeElement(
            widthState = maxWidthState,
            heightState = maxHeightState,
            fraction = fraction,
            inspectorName = "fillParentMaxSize"
        )
    )

    override fun Modifier.fillParentMaxWidth(fraction: Float) = then(
        ParentSizeElement(
            widthState = maxWidthState,
            fraction = fraction,
            inspectorName = "fillParentMaxWidth"
        )
    )

    override fun Modifier.fillParentMaxHeight(fraction: Float) = then(
        ParentSizeElement(
            heightState = maxHeightState,
            fraction = fraction,
            inspectorName = "fillParentMaxHeight"
        )
    )

    override fun Modifier.animateItem(
        fadeInSpec: FiniteAnimationSpec?,
        placementSpec: FiniteAnimationSpec?,
        fadeOutSpec: FiniteAnimationSpec?
    ): Modifier =
        if (fadeInSpec == null && placementSpec == null && fadeOutSpec == null) {
            this
        } else {
            this then LazyLayoutAnimateItemElement(
                fadeInSpec,
                placementSpec,
                fadeOutSpec
            )
        }
}

private class ParentSizeElement(
    val fraction: Float,
    val widthState: State? = null,
    val heightState: State? = null,
    val inspectorName: String
) : ModifierNodeElement() {
    override fun create(): ParentSizeNode {
        return ParentSizeNode(
            fraction = fraction,
            widthState = widthState,
            heightState = heightState
        )
    }

    override fun update(node: ParentSizeNode) {
        node.fraction = fraction
        node.widthState = widthState
        node.heightState = heightState
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is ParentSizeElement) return false
        return fraction == other.fraction &&
            widthState == other.widthState &&
            heightState == other.heightState
    }

    override fun hashCode(): Int {
        var result = widthState?.hashCode() ?: 0
        result = 31 * result + (heightState?.hashCode() ?: 0)
        result = 31 * result + fraction.hashCode()
        return result
    }

    override fun InspectorInfo.inspectableProperties() {
        name = inspectorName
        value = fraction
    }
}

private class ParentSizeNode(
    var fraction: Float,
    var widthState: State? = null,
    var heightState: State? = null,
) : LayoutModifierNode, Modifier.Node() {

    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        val width = widthState?.let {
            if (it.value != Constraints.Infinity) {
                (it.value * fraction).fastRoundToInt()
            } else {
                Constraints.Infinity
            }
        } ?: Constraints.Infinity

        val height = heightState?.let {
            if (it.value != Constraints.Infinity) {
                (it.value * fraction).fastRoundToInt()
            } else {
                Constraints.Infinity
            }
        } ?: Constraints.Infinity
        val childConstraints = Constraints(
            minWidth = if (width != Constraints.Infinity) width else constraints.minWidth,
            minHeight = if (height != Constraints.Infinity) height else constraints.minHeight,
            maxWidth = if (width != Constraints.Infinity) width else constraints.maxWidth,
            maxHeight = if (height != Constraints.Infinity) height else constraints.maxHeight,
        )
        val placeable = measurable.measure(childConstraints)
        return layout(placeable.width, placeable.height) {
            placeable.place(0, 0)
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy