6、“Align your body”行 – 摆放

现在,您现已创立了屏幕上显现的节本可组合项,接下来能够创立屏幕的不同不同部分了。

先从”Align your body”可翻滚着手。

Jetpack Compose(第四趴)——Compose中的基本布局(下)
此组件的红线规划如下所示:

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

请注意,一个网格块代表8dp。因而,在此规划中,该行中的第一项内容和终究一项内容留有16dp的距离。各项呢绒之间的距离为8dp。

在Compose中,您能够运用LazyRow可组合项完结这种可翻滚行。了解LazyRow只会烘托屏幕上显现的元素(而不是同时烘托一切元素)这足够了,这有助于让运用坚持出色的性能。

先从此LazyRow的根本完结着手:

import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
@Composable
fun AlignYourBodyRow(
    modifier: Modifier = Modifier
) {
    LazyRow(
        modifier = modifier
    ) {
        items(alignYourBodyData) { item ->
            AlignYourBodyElement(item.drawable, item.text)
        }
    }
}

如您所见,LazyRow的子项不是可组合项。您应该用推迟列表DSL,它可供给itemitems等办法,这些办法会以列表项的办法宣布可组合项。关于所供给的alignYourBodyData中的各项,您能够宣布之前完结的AlignYourBodyElement可组合项。

请注意显现办法:

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

咱们在红线规划中看到的距离仍未显现。若要完结这些部分,您有必要了解摆放办法

在上一步中,您了解了对其办法,它用于在穿插轴上对其容器的子项。关于Column,穿插轴是水平轴;关于Row,穿插轴则是笔直轴。

不过,咱们也能够决定如安在容器的主轴(关于Row,是水平轴;关于Column,是笔直轴)上避免可组合项。

关于Row,您能够挑选以下摆放办法:

Jetpack Compose(第四趴)——Compose中的基本布局(下)
关于Column:

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

除了这些摆放办法之外,您还能够运用Arrangement.spaceBy()办法,在每个可组合项之间增加固定距离。

在此示例中,您需求运用spaceBy办法,因为您需求在LazyRow中的各项之间留出8dp的距离。

import androidx.compose.foundation.layout.Arrangement
@Composable
fun AlighYourBodyRow(
    modifier: Modifier = Modifier
) {
    LazyRow(
        horizontalArrangement = Arrangement.spaceBy(8.dp),
        modifier = modifier
    ) {
        items(alignYourBodyData) { item ->
            AlignYourBodyElement(item.drawable, item.text)
        }
    }
}

现在,规划如下所示:

Jetpack Compose(第四趴)——Compose中的基本布局(下)
此外,您需求在LazyRow两边增加一定尺寸的内边距。在此示例中,增加一个简单的内部安居修饰符并不能到达目的。请测验向LazyRow增加内边距,看看其行为办法:

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

如您所见,翻滚时,第一个和终究一个可见项在屏幕两边被截断。

为了坚持相同的内边距,同时确保在父级列表的边界内翻滚时内容不会被截断,一切列表都需供给一个名为contentPadding的形参。

@Composable
fun AlignYourBodyRow(
    modifier: Modifier = Modifier
) {
    LazyRow(
        horizontalArrangement = Arrangement.spaceBy(8.dp),
        contentPadding = PaddingValues(horizontal = 16.dp),
        modifier = modifier
    ) {
        items(alignYourBodyData) { item ->
            AlignYourBodyElement(item.drawable, item.text)
        }
    }
}

7、“Favorite collections”网格 – 推迟网络

接下来,您要完结的是屏幕的”Favorite collections”板块。这个可组合项需求的是网格,而不是单个行:

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

您能够按照与上一部分类似的办法完结此模块,具体办法是创立一个LazyRow,让各项都包括一个具有两个FavoriteCollectionCard实例的Column。但在此步骤中,您需求运用LazyHorizontalGrid,以便更好地将各项映射到网络元素。

首要完结包括两个固定行的简单网络:

import androidx.compose.foundation.lazy.grif.GirdCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.items
@Composable
fun FavoriteCollectionsGrid(
    modifier: Modifier = Modifier
) {
    LazyHorizontalGrid(
        rows = GridCells.Fixed(2),
        modifier = modifier
    ) {
        items(favoriteCollectionsData) { item ->
            FavoriteCollectionCard(item.drawable, item.text)
        }
    }
}

如您所见,只需将上一步中的LazyRow替换为LazyHorizontalGrid即可。

LazyHorizontalGrid是Jetpack Compose 1.2.0-alpha05中发布的推迟布局API的一部分。运用此网格时,您至少需求运用此版本。

不过,这样还无法得到正确的成果:

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

网格占用的空间与其父项相同,这意味着, “favorite collection”卡片会在笔直方向上被过度拉伸。调整可组合项,以便网格单元的巨细以及各单元之间的距离正确无误。

成果应如下所示:

@Composable
fun FavoriteCollectionsGrid(
    modifier: Modifier = Modifier
) {
    LazyHorizontalGrid(
        rows = GridCells.Fixed(2),
        contentPadding = PaddingValues(horizontal = 16.dp),
        horizontalArrangement = Arrangement.spaceBy(8.dp),
        verticalArrangement = Arrangement.spaceBy(8.dp),
        modifier = modifier.height(120.dp)
    ) {
        items(favoriteCollectionsData) { item ->
            FavoriteCollectionCard(
                drawable = item.drawable,
                text = item.text,
                modifier = Modifier.height(56.dp)
            )
        }
    }
}

8、主页部分 – 槽位API

在MySoothe主屏幕中,有多个板块都遵循一致形式。每个板块都有一个标题,其间包括的内容因板块而异。咱们想要完结的规划如下所示:

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

如您所见,每个版块都有一个标题和一个槽位。标题包括一些与其相关的距离和款式信息。能够运用不同的内容填充槽位,具体取决于板块。

调整HomeSection可组合项以接纳标题和槽位内容。您还应调整关联的预览,以调用这个包括“Align your body”标题及相关内容的HomeSection

@Composable
fun HomeSection(
    @StringRes title: Int,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Column(modifier) {
        Text(stringResource(title))
        content()
    }
}
@Preview(showBackground = true, backgroundColor = 0xFFF0EAE2)
@Composable
fun HomeSectionPreview() {
    MySootheTheme {
        HomeSection(R.string.align_your_body) {
            AlignYourBodyRow()
        }
    }
}

您能够为可组合项的槽位运用content形参。这样一来,当您运用HomeSection可组合项时,便可运用跟随lambda填充内容槽位。当可组合项供给多个要填充的槽位时,您可为这些槽位指定有意义的名称,用于在更大的可组合项容器中代表其功用。例如,Material的TopAppBartitlenavigationIconactions供给槽位。

咱们来看一下这个板块选用该完结后的作用:

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

Text可组合项需求更多信息才能与规划坚持一致。更新该可组合项,以便它:

  • 选用全部大写的办法显现(提示:您能够运用Stringuppercase()办法完结此目的)。
  • 选用H2排版。
  • 留有契合红线规划的内边距。

您的终究解决方案应如下所示:

import java.util.*
@Composable
fun HomeSection(
    String title: Int,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Column(modifier) {
        Text(
            text = stringResource(title).uppercase(Locale.getDefault()),
            style = MaterialTheme.typography.h2,
            modifier = Modifier
                .paddingFromBaseline(top = 40.dp, bottom = 8.dp)
                .padding(horizontal = 16.dp)
        )
        content()
    }
}

9、 主屏幕 – 翻滚

现在,您现已创立了一切独自的构建块,接下来能够将它们组合成一个全屏完结了。

您测验完结的规划如下所示:

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

只需依序放置搜索栏和这两个板块。您需求增加一定尺寸的距离,以确保一切都契合规划。咱们之前没有运用过Spacer和组合项,它可帮助咱们在Column中增加额定的距离。假如您改为设置Column的内边距,便会看到之前”Favorite Collections”网格中出现的相同截断行为。

@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
    Column(modifier) {
        Spacer(Modifier.height(16.dp))
        SearchBar(Modifier.padding(horizontal = 16.dp))
        HomeSection(title = R.string.align_your_body) {
            AlignYourBodyRow()
        }
        HomeSection(title = R.string.favorite_collections) {
            FavoriteCollectionsGrid()
        }
        Spacer(Modifier.height(16.dp))
    }
}

虽然规划与大多数设备尺寸都十分契合,但假如设备的高度缺乏(例如在横屏形式下),规划需求能够笔直翻滚。这就需求您增加翻滚行为。

如前所述,LazyRowLazyHorizontalGrid等推迟布局会主动增加翻滚行为。但是,您不一定总是需求推迟布局。一般来说,在列表中有许多元素或需求加载大型数据集时,您需求运用推迟布局,因而一次宣布一切项不只会下降性能,还会拖慢运用的运转速度。假如列表中的元素数量有限,您也能够挑选运用简单的ColumnRow,然后手动增加翻滚行为。因而,您能够运用verticalScrollhorizontalScroll修饰符。这些修饰符需求ScrollState,后者包括当时的翻滚状况,可用于从外部修改翻滚状况。在此示例中,您不需求修改翻滚状况,只需运用rememberScrollState创立一个耐久的ScrollState实例。

终究成果应如下所示:

import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
    Column(
        modifier.verticalScroll(rememberScrollState())
        .padding(vertical = 16.dp)
    ) {
        Spacer(Modifier.height(16.dp))
        SearchBar(Modifier.padding(horizontal = 16.dp))
        HomeSection(title = R.string.align_your_body) {
            AlignYourBodyRow()
        }
        HomeSection(title = R.string.favorite_collections) {
            FavoriteCollectionsGrid()
        }
        Spacer(Modifier.height(16.dp))
    }
}

如需验证可组合项的翻滚行为,请约束预览的高度,并在互动式预览中运转它。

@Preview(showBackground = true, backgroundColor = 0xFFF0EAE2, heightDp = 100)
@Composable
fun ScreenContentPreview() {
    MySootheTheme { HomeScreen() }
}

10、底部导航栏 – Material

现在,您现已完结了屏幕内容,能够开端增加窗口装饰了。就MySoothe而言,用户能够经过底部导航栏在不同的屏幕之间切换。

首要,完结此底部导航栏可组合项自身,然后将其增加到运用中。 咱们来看一下规划:

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

幸运的是,您无需自己从头开端完结整个可组合项。您能够运用Compose Material库中的BottomNavigation可组合项。在BottomNavigation可组合项内,您能够增加一个或多个BottomNavigationItem元素,然后Material库会主动为其设置款式。

先从此底部导航栏的根本所完结着手:

import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavittationItem
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Spa
@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
    BottomNavigation(modifier) {
        BottomNavigationItem(
            icon = {
                Icon(
                    imageVector = Icons.Default.Spa,
                    contentDescription = null
                )
            },
            label = {
                Text(stringResource(R.string.bottom_navigation_home))
            },
            selected = true,
            onClick = {}
        )
        BottomNavigationItem(
            icon = {
                Icon(
                    imageVector = Icons.Default.AccoutCircle,
                    contentDescription = null
                )
            },
            label = {
                Text(stringResource(R.string.bottom_navigation_profile))
            },
            selected = false,
            onClick = {}
        )
    }
}

此根本完结如下所示:

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

您应该进行一些款式调整。首要,您能够经过设置底部导航栏的backgroundColor形参来更新其北京色彩。为此,您能够运用Material主题中的布景色彩。经过设置布景色彩,图标和文本的色彩会主动适应主题的onBackground色彩。终究解决方案应如下所示:

@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
    BottomNavigation(
        backgroundColor = MaterialTheme.colors.background,
        modifier = modifier
    ) {
        BottomNavigationItem(
            icon = {
                Icon(
                    imageVector = Icons.Default.Spa,
                    contentDescription = null
                )
            },
            label = {
                Text(stringResource(R.string.bottom_navigation_home))
            },
            selected = true,
            onClick = {}
        )
        BottomNavigationItem(
            icon = {
                Icon(
                    imageVector = Icons.Default.AccountCirclr,
                    contentDescription = null
                )
            },
            label = {
                Text(stringResource(R.string.bottom_navigation_profile))
            },
            selected = false,
            onClick = {}
        )
    }
}

11、MySoothe运用 – Scaffold

在这终究一步中,创立全屏完结,包括底部导航栏。运用Material的Scaffold可组合项。关于完结Material Design的运用,Scaffold供给了可配置的顶级可组合项。它包括可用于各种Material概念的槽位,其间一个就是底部栏。在此底部栏中,您能够放置在上一步中创立的底部导航栏可组合项。

完结MysootheApp可组合项。这是运用的顶级可组合项,因而您应该:

  • 运用MySootheTheme Material主题
  • 增加Scaffold
  • 将底部栏设置为SootheBottomNavigation可组合项。
  • 将内容设置为HomeScreen可组合项。

终究成果应如下所示:

import androidx.compose.material.Scaffold
@Composable
fun MySootheTheme() {
    MySootheTheme {
        Scaffold(
            bottomBar = { SootheBottomNavigation() }
        ) { padding ->
            HomeScreen(Modifier.padding(padding))
        }
    }
}

您的完结现已完结!假如想要检查您的完结的规划是否能让像素完美出现,能够下载下面的图片,然后将其与您自己的预览完结进行比较。

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

12、恭喜!

翻译原文:Compose 基础知识