Compose中的基本布局

1、简介

Compose是一个界面工具包,可让您轻松完结运用的规划。您只需描述自己想要的界面外观,Compose会担任屏幕上进行绘制。

1.1、学习内容

您将学习:

  • 怎么凭借修饰符扩充可组合项?
  • 怎么经过Column和LazyRow等规范布局组件定位可组合项?
  • 怎么经过对齐办法和排列办法更改可组合项在父项的位置?
  • 怎么凭借Scaffold和Bottom Navigation等Material可组合项创立详细布局?
  • 怎么运用槽位API构建灵活的可组合项?

2、从制定方案着手

下面咱们来详细了解一下规划:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

在需求完结规划时,最好先清楚了解其结构。不要当即开端编码,而应剖析规划本身。假如将此界面拆分为多个可重复运用的部分

接下来,咱们试着剖析一下规划。在最高抽象等级,咱们能够将此规划分为两部分:

  • 屏幕上的内容
  • 底部导航栏

Jetpack Compose(第四趴)——Compose中的基本布局(上)

打开细目后,您能够看到屏幕内容包含三个子部分:

  • 查找栏
  • ”Align your body“板块
  • ”Favorite collections“板块

Jetpack Compose(第四趴)——Compose中的基本布局(上)

在每个版块中,您还能够看到一些可重复运用的较低等级组件:

  • ”align your body“元素,显现在可水平翻滚的行中。

Jetpack Compose(第四趴)——Compose中的基本布局(上)

  • ”favorite collection“卡片,显现在可水平翻滚的网格中。

Jetpack Compose(第四趴)——Compose中的基本布局(上)

现在,您现已剖析了规划,接下来能够开端为每个已确定的界面部分完结可组合项。先从最低等级的可组合项着手,然后继续讲它们组合成更复杂的可组合项。完结后,您的新运用将与供给的规划相似。

3、查找栏 – 修饰符

第一个要转换为可组合项的元素是查找栏。咱们来看一下规划:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

之经过上面的屏幕截图,很难在完结该规划时让元素完美出现。通常情况下,规划人员应传达更多关于规划的信息。他们能够授权您访问他们的规划工具,或分享所谓的用红线标示的规划。在此示例中,咱们的规划人员提交了用红线标示的规划,方便您读出任何尺度值。该规划选用8dp网格叠加层的办法显现,以便您轻松查看各个元素之间和周围的空间大小。此外,还明确增加了一些距离,以阐明特定尺度。

Jetpack Compose(第四趴)——Compose中的基本布局(上)

您能够看到,查找栏的高度应为56密度无关像素。它还应填充其父项的全宽。

若要完结查找栏,请运用名为文本字段的Materila组件。Compose Material库包含一个名为TextField的可组合项,后者是此Material组件的完结。

从基本的TextField完结着手。在您的代码库中,打开MainActivity.kt并查找SearchBar可组合项。

在名为SearchBar的可组合项,编写基本的TextField完结:

import androidx.compose.material.TextField
@Composable
fun SearchBar(
    modifier: Modifier = Modifier
) {
    TextField(
        value = "",
        onValueChange = {},
        modifier = modifier
    )
}

需求留意以下几点:

  • 您已对文本字段的值进行了硬编码,onValueChange回调不会履行任何操作。
  • SearchBar可组合函数承受modifier形参,并将其传递给TextField。这是契合Compose准则的最佳实践。这样一来,办法调用方就能够修改可组合项的外观和风格,使其愈加灵活且可重复运用。

咱们来看一看此可组合项的预览。请留意,您能够运用Android Studio中的预览功能快速迭代各个可组合项。MainActivity.kt包含您要在此构建的一切可组合项的预览。在此示例中,SearchBarPreview办法会渲染咱们的SearchBar可组合项,并供给一些鳖精和内边距,以便供给更多上下文。完结您刚才天津爱的完结后,预览应如下所示:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

不过,还缺少一些内容。首要,咱们运用修饰符修正可组合项的尺度。

编写可组合项时,您能够运用修饰符履行以下操作:

  • 更改可组合项的尺度、布局、行为和外观。
  • 增加信息,例如无障碍标签。
  • 处理用户输入
  • 增加高档互动,例如使元素可点击、可翻滚、可拖动或可缩放。

您调用的每个可组合项都有一个modifier形参,您能够设置该形参以适应相应可组合项的外观、风格和行为。设置修饰符时,您能够将多个修饰符办法串联起来,以创立更复杂的调试。

在此示例中,查找栏的高度应至少为56dp,并填充其父项的宽度。为了找到适宜查找栏的修饰符,您能够阅读修饰符列表,并查看尺度部分。关于高度,您能够运用heightIn修饰符。这可确保该可组合项具有特定的最小高度。但是,假如用户扩大体系字体大小,该高度会随之变高。关于宽度,您能够运用fillMaxWidth修饰符,此修饰符可确保查找栏占用其父项的一切水平空间。

更新修饰符以匹配下面代码:

import androidx.compose.material.TextField
@Composable
fun SearchBar(
    modifier: Modifier = Modifier
) {
    value = "",
    onValueChange = {},
    modifier = modifier
        .fillMaxWidth()
        .heightIn(min = 56.dp)
}

在此示例中,因为一个修饰符会影响宽度,另一个修饰符会影响高度。因而这些修饰符的次序无关紧要。

您还有必要设置TextField的一些形参。您能够试着设置形参值,以使可组合项相似于规划。相同,以下规划供给您参考:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

更新完结时应采取以下过程:

  • 增加查找图标。TextField包含一个可承受其他可组合项的leadingIcon形参。您能够在其中设置Icon,在此实力中应为Search图标。请务必运用正确的ComposeIcon导入。
  • 将文字字段的布景色彩设为MaterialTheme的surface色彩。您能够运用TextFieldDetaults.textFieldColors替换特定色彩。
  • 增加占位符文本”Search”(以字符串资源R.string.placeholder_search的方法显现)。

完结后,您的可组合项应如下所示:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.ui.res.stringResource
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.Icons
import androidx.compose.material.filled.Search
@Composable
fun SearchBar(
    modifier: Modifier = Modifier
) {
    TextField(
        value = "",
        onValueChange = {},
        leadingIcon = {
            Icon(
                imageVector = Icons.Default.Search,
                contentDescription = null
            )
        },
        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = MaterialTheme.colors.surface
        ),
        placeholder = {
            Text(stringResource(R.string.placeholder_search))
        },
        modifier = modifier
            .fillMaxWidth()
            .heightIn(min = 56.dp)
    )
}

请留意:

  • 您增加了一个用于显现查找图标的leadingIcon。此图标不需求内容阐明,因为文本字段的占位符现已阐明了文本字段的意义。请留意,内容阐明通常用于完结无障碍功能,以文本方法向运用用户出现图片或图标。
  • 假如调整文本字段的布景色彩,请设置colors特点。该可组合项包含一个组合形参,而不是每种色彩的单独形参。在这种情况下,您能够传入TextFieldDefaults数据类的副本,您能够经过该类仅更新不同的色彩。在此示例中,即仅更新布景色彩。
  • 您设置的是最小高度,而不是固定高度。建议您选用这种办法,这样依赖,假如用户在体系设置增加字体大小,文本字段的带下仍会增加。

在此过程中,您了解了怎么运用可组合项的形参和修饰符来更改可组合项的外观和风格。这适用于Compose和Material库供给的可组合项,以及您自己编写的可组合项。您应该一直考虑经过供给形参来自界说所编写的可组合项。您还应增加modifier特点,以便从外部调整可组合项的外观和风格。

4、Align your body – 对齐

接下来,您要完结的可组合项“Align your body”元素。咱们来看看该元素的规划,包含它旁边的红线规划:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

红线规划现在还包含面向基线的距离。以下是咱们从中取得的信息:

  • 图片高度应为88dp
  • 文本基线与图片之间的距离应为24dp
  • 基线与元素底部的距离应为8dp
  • 文本的排版款式应为H3.

文本基线是指字母所在的那一行。规划人员认为依据基线(而不是顶部或底部)对齐文本元素是一种最佳时刻。

如需完结此可组合项,您需求一个Image和一个Text可组合项。您还需求将它们增加到Column中,以便一个坐落另一个下方。

在您的代码中找到AlignYourBodyElement可组合项,运用以下基本完结更新器内容:

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.res.painterResource
@Composable
fun AlignYourBodyElement(
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
    ) {
        Image(
            painter = painterResource(R.drawable.ab1_inversions),
            contentDescription = null
        )
        Text(
            text = stringResource(R.string.ab1_inversions)
        )
    }
}

请留意:

  • 您将图片的contentDescription设为null,因为这张图片是纯装饰性的。图片下方的文本充分描述了图片的意义,因而无需为图片增加额外的阐明。
  • 您运用的是经过硬编码的图片和文本。在下一步,您要为这些内容改用AlightYourBodyElement可组合项中供给的形象,使其变为动态方法。

查看此可组合项的预览:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

您需求进行一些改进。最值得留意的是,图片过大,且形状不是圆形。您能够运用sizeclip修饰符以及contentScale形参调整Image可组合项。

size修饰符会调整可组合项以适应特定尺度,这相似于您在上一步看到的fillMaxWidthheightIn修饰符。clip修饰符的作业原理有所不同,用于调整可组合项的外观。您能够将该修饰符设置为任何Shape,然后它会依照相应形状对可组合项的内容进行裁剪。

图片也需求正确缩放。为此,咱们能够运用ImagecontentScale形参。详细选项有很多,最值得留意的是:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

在此示例中,裁剪类型便是要运用的正确类型。运用修饰符和形参后,您的代码应如下所示:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.CircleShape
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
@Composable
fun AlignYourBodyElement(
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
    ) {
        Image(
            painter = painterResource(R.drawable.ab1_inversions),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .size(88.dp)
                .clip(CircleShape)
        )
        Text(
            text = stringResource(R.string.ab1_inversions)
        )
    }
}

现在,您的规划应如下所示:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

接下来,经过设置Column的对其办法来水平对其文本。

一般来说,若要对其父容器中的可组合项,您应设置该父容器的对齐办法。因而,您应奉告父项怎么对齐其子项,而不是奉告子项将其自身放置在父项中。

关于Column,您能够决定其子项的水平对其办法。详细选项包含:

  • Start
  • CenterHorizontally
  • End

关于Row,您能够设置笔直对齐。详细选项相似于Column的选项:

  • Top
  • CenterVertically
  • Bottom

关于Box,您能够一起运用水平对齐和笔直对齐。详细选项包含:

  • TopStart
  • TopCenter
  • TopEnd
  • CenterStart
  • Center
  • CenterEnd
  • BottomStart
  • BottomCenter
  • BottomEnd

容器的一切子项都将遵从这一相同的对其方法。您能够经过单个子项增加align修饰符来替换其行为。

关于此规划,文本应水平居中。为此,请将ColumnhorizontalAlignment设置为水平居中:

import androidx.compose.ui.Alignment
@Compoable
fun AlignYourBodyElement(
    modifier: Modifier = Modifier
) {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier
    ) {
        Image(
            //..
        )
        Image(
            //..
        )
    }
}

完结这些部分,您只需进行一些纤细更改,即可使可组合项与规划完全相同。假如遇到问题,无妨测验自行完结这些部分,也能够引用终究代码。考虑采取以下过程:

  • 将图片和文本变为动态方法。将它们作为实参传递给可组合函数。别忘了更新相应的预览,并传入一些经过硬编码的数据。
  • 更新文本以运用适宜的排版款式。
  • 更新文本元素的基线距离。

履行完这些过程后,您的代码应如下所示:

import androidx.compose.foundation.layout.paddingFromBaseline
@Composable
fun AlignYourBodyElement(
    @DrawableRes drawable: Int,
    @StringRes text: Int,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(
            painter = painterResource(drawable),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .size(88.dp)
                .clip(CircleShape)
        )
        Text(
            text = stringResource(text),
            style = MaterialTheme.typography.h3,
            modifier = Modifier.paddingFromBaseline(
                top = 24.dp, bottom - 8.dp
            )
        )
    }
}

5、“Favorite collection”卡片 – Material Surface

下一个可组合项的事项办法与”Align your body”元素相似。

Jetpack Compose(第四趴)——Compose中的基本布局(上)

此示例供给了可组合项的完整尺度。您能够看到,文本那相同还应为H3。

此容器有某种布景色彩,不同于整个屏幕的布景色彩。它还带有圆角。因为规划人员没有指定色彩,因而咱们能够假定色彩将由主题界说。关于此类容器,咱们运用Material的Surface可组合项。

Surface是Compose Material库中的一个组件。该组件遵从惯例的Material Design方法,您能够经过更改运用主题来调整他。

您能够依据自己的需求调整Surface,只需设置其形参和修饰符即可。在此示例中,表面应有圆角。针对这种情况,您能够运用shape形参。关于上一步中的图片,您将形状设置为shape,但在这一步中,您将运用来自咱们的Material主题的值。

咱们来看一看作用怎么:

import androidx.compose.foundation.layout.Row
import androidx.compose.material.Surface
@Composable
fun FavoriteCollectionCard(
    modifier: Modifier = Modifier
) {
    Surface(
        shape = MaterialTheme.shapes.small,
        modifier = modifier
    ) {
        Row {
            Image(
                painter = painterResource(R.drawable.fc2_nature_meditations),
                contentDescription = null
            )
            Text(
                text = stringRecource(R.string.fc2_nature_meditations)
            )
        }
    }
}

咱们来看一下此完结的预览:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

接下来,运用在上一步中学到的经历。设置图片尺度,然后在容器中对其进行裁剪。设置Row的宽度,并与其子项笔直对齐。先测验自行实施这些更改,然后再查看解决方案代码!

现在,您的代码如下所示:

import androidx.compose.foundation.layout.width
@Composable
fun FavoriteCollectionCard(
    modifier: Modifier = Modifier
) {
    Surface(
        shape = MaterialTheme.shapes.small,
        modifier = modifier
    ) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.width(192.dp)
        ) {
            Image(
                painter = painterResource(R.drawable.fc2_nature__meditations),
                contentDescription = null,
                contentScale = ContentScale.Crop,
                modifier = Modifier.size(56.dp)
            )
            Text(
                text = stringResource(R.string.fc2_nature_meditations)
            )
        }
    }
}

预览现在应如下所示:

Jetpack Compose(第四趴)——Compose中的基本布局(上)

如需完结此可组合项,wing实施以下过程:

  • 将图片和文本变为动态方法。将它们作为实参传入可组合函数。
  • 更新文本以运用适宜的排版款式。
  • 更新图片与文本之间的距离。

终究成果应如下所示:

@Composable
fun FavoriteCollectionCard(
    @DrawableRes drawable: Int,
    @StringRes text: Int,
    modifier: Modifier = Modifier
) {
    Surface(
        shape = MaterialTheme.shapes.small,
        modifier = modifier
    ) {
        Image(
            painter = painterResource(drawable),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier.size(56.dp)
        )
        Text(
            text = stringResource(text),
            style = MaterialTheme.typography.h3,
            modifier = Modifier.padding(horizontal = 16.dp)
        )
    }
}
// ..
@Previrew(showBackground = true, backgroundColor = 0xFFF0EAE2)
@Composable
fun FavoriteCollectionCardPreview() {
    MySootheTheme {
        FavoriteCollectionCard(
            text = R.string.fc2_nature_meditations,
            drawable = R.drawable.fc2_nature_meditations,
            modifier = Modifier.padding(8.dp)
        )
    }
}

翻译原文:Compose 基础知识