Android Compose:Alignment(一)

Alignment是AndroidCompose中用于控制布局位置的关键接口,包括Horizontal和Vertical布局策略。它提供了不同方向的对齐常量,如TopStart、Center、BottomEnd等,用于在容器内定位组件。BiasAlignment数据类用于计算基于偏移量的位置,考虑了布局方向和组件大小的关系。
摘要由CSDN通过智能技术生成

Android Compose:Alignment(一)

Alignment是Compse中唯一控制布局位置的接口,源码:

@Stable
fun interface Alignment {
    /**
     * 在布局容器中使用,通过尺寸和布局规则计算出偏移量
     * 详情详细信息见自定义布局
     */
    fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset

    /**
     * 横向布局接口:在布局容器内可用宽度区域内,计算子控件的位置
     * 横向布局时,开始位置分类左开始或右开始
     * 所在此接口中包含LayoutDirection字段,而后面的Vertical接口中没有
     */
    @Stable
    fun interface Horizontal {
        /**
         * 计算布局容器可用宽度内的位置接口
         */
        fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int
    }

    /**
     *	纵向布局接口:在使用和Horizontal一样,由于纵向不像横向布局有两个起始位置
     * 	所以align方法中少了一个LayoutDirection参数
     */
    @Stable
    fun interface Vertical {
        /**
         * 计算布局容器可用宽度内的位置接口
         */
        fun align(size: Int, space: Int): Int
    }

    /**
     * 在布局方向确定时,常用的对齐集合
     */
    companion object {
        // 以下是我们常用的变量参数,常与Modifier.align()使用
        @Stable
        val TopStart: Alignment = BiasAlignment(-1f, -1f)
        @Stable
        val TopCenter: Alignment = BiasAlignment(0f, -1f)
        @Stable
        val TopEnd: Alignment = BiasAlignment(1f, -1f)
        @Stable
        val CenterStart: Alignment = BiasAlignment(-1f, 0f)
        @Stable
        val Center: Alignment = BiasAlignment(0f, 0f)
        @Stable
        val CenterEnd: Alignment = BiasAlignment(1f, 0f)
        @Stable
        val BottomStart: Alignment = BiasAlignment(-1f, 1f)
        @Stable
        val BottomCenter: Alignment = BiasAlignment(0f, 1f)
        @Stable
        val BottomEnd: Alignment = BiasAlignment(1f, 1f)

        // 纵向布局参数,不常用,一般用在布局参数中或在布局中使用
        @Stable
        val Top: Vertical = BiasAlignment.Vertical(-1f)
        @Stable
        val CenterVertically: Vertical = BiasAlignment.Vertical(0f)
        @Stable
        val Bottom: Vertical = BiasAlignment.Vertical(1f)

        // 横向布局参数,不常用,一般用在布局参数中或在布局中使用
        @Stable
        val Start: Horizontal = BiasAlignment.Horizontal(-1f)
        @Stable
        val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f)
        @Stable
        val End: Horizontal = BiasAlignment.Horizontal(1f)
    }
}

/**
 * 在不确定布局方向时,常用的对齐集合
 */
object AbsoluteAlignment {
    // 以下是我们常用的变量参数,常与Modifier.align()使用
    @Stable
    val TopLeft: Alignment = BiasAbsoluteAlignment(-1f, -1f)
    @Stable
    val TopRight: Alignment = BiasAbsoluteAlignment(1f, -1f)
    @Stable
    val CenterLeft: Alignment = BiasAbsoluteAlignment(-1f, 0f)
    @Stable
    val CenterRight: Alignment = BiasAbsoluteAlignment(1f, 0f)
    @Stable
    val BottomLeft: Alignment = BiasAbsoluteAlignment(-1f, 1f)
    @Stable
    val BottomRight: Alignment = BiasAbsoluteAlignment(1f, 1f)

    // 横向布局参数,不常用,一般用在布局参数中或在布局中使用
    @Stable
    val Left: Alignment.Horizontal = BiasAbsoluteAlignment.Horizontal(-1f)
    @Stable
    val Right: Alignment.Horizontal = BiasAbsoluteAlignment.Horizontal(1f)
}

/**
 * 位置偏移数据类
 * 根据传入的横纵位置参数,计算出布局中子控件的位置
 * 
 */
@Immutable
data class BiasAlignment(
    val horizontalBias: Float,
    val verticalBias: Float
) : Alignment {
    
    /**
     *	align()方法计算出x,y的位置偏移量
     *	主要是根据传进来的值:horizontalBias,verticalBias
     *	根据上面常量传参可知,
     *	顶部左对齐(-1, -1)横、纵都是-1,代入方法中结果得:(0,0)
     *	顶部居中(0, -1),代入方法中结果得:(centerX,0),正好x是居中位置
     *	顶部右对刘(1, -1),代入方法中结果得:(centerX * 2,0),正好x是右对齐
     */
    override fun align(
        size: IntSize,
        space: IntSize,
        layoutDirection: LayoutDirection
    ): IntOffset {
        val centerX = (space.width - size.width).toFloat() / 2f
        val centerY = (space.height - size.height).toFloat() / 2f
        val resolvedHorizontalBias = if (layoutDirection == LayoutDirection.Ltr) {
            horizontalBias
        } else {
            -1 * horizontalBias
        }

        val x = centerX * (1 + resolvedHorizontalBias)
        val y = centerY * (1 + verticalBias)
        return IntOffset(x.roundToInt(), y.roundToInt())
    }

    /**
     * 见:align()说明,这里只是上面的其中一种情况
     */
    @Immutable
    data class Horizontal(private val bias: Float) : Alignment.Horizontal {
        override fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int {
            val center = (space - size).toFloat() / 2f
            val resolvedBias = if (layoutDirection == LayoutDirection.Ltr) bias else -1 * bias
            return (center * (1 + resolvedBias)).roundToInt()
        }
    }

    /**
     * 见:align()说明,这里只是上面的其中一种情况
     */
    @Immutable
    data class Vertical(private val bias: Float) : Alignment.Vertical {
        override fun align(size: Int, space: Int): Int {
            val center = (space - size).toFloat() / 2f
            return (center * (1 + bias)).roundToInt()
        }
    }
}

/**
 * 绝对位置偏移类
 * 和BiasAlignment算法一样
 */
@Immutable
data class BiasAbsoluteAlignment(
    private val horizontalBias: Float,
    private val verticalBias: Float
) : Alignment {
    override fun align(size: IntSize, space: IntSize, layoutDirection: LayoutDirection): IntOffset {
        // Convert to Px first and only round at the end, to avoid rounding twice while calculating
        // the new positions
        val remaining = IntSize(space.width - size.width, space.height - size.height)
        val centerX = remaining.width.toFloat() / 2f
        val centerY = remaining.height.toFloat() / 2f

        val x = centerX * (1 + horizontalBias)
        val y = centerY * (1 + verticalBias)
        return IntOffset(x.roundToInt(), y.roundToInt())
    }
    
    @Immutable
    data class Horizontal(private val bias: Float) : Alignment.Horizontal {
        override fun align(size: Int, space: Int, layoutDirection: LayoutDirection): Int {
            val center = (space - size).toFloat() / 2f
            return (center * (1 + bias)).roundToInt()
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值