【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App

文章目录

  • 一、新建项目
  • 二、搜索栏
  • 三、Align 对齐
  • 四、设置 Surface
  • 五、横向列表
  • 六、实现 LazyHorizontalGrid
  • 七、首页的槽位 API
  • 八、主屏幕的滚动
  • 九、底部导航栏
  • 十、整体 App 集成

一、新建项目

通过 git clone https://github.com/googlecodelabs/android-compose-codelabs 克隆代码,打开 BasicLayoutCodelab 项目,首先,布局分为上下两部分:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第1张图片

其次,上半部分又细分为如下三个模块:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第2张图片

最细粒度的是如下2个元素,都可水平滚动:
【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第3张图片
【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第4张图片

二、搜索栏

// Step: Search bar - Modifiers
@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)
    )
}

效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第5张图片

三、Align 对齐

接下来,您要实现的可组合项是“Align your body”元素。我们来看看该元素的设计,包括它旁边的红线设计:

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

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第6张图片

代码实现如下:

@Preview(showBackground = true, backgroundColor = 0xFFF0EAE2)
@Composable
fun AlignYourBodyElementPreview() {
    MySootheTheme {
        AlignYourBodyElement(
            drawable = R.drawable.ab1_inversions,
            text = R.string.ab1_inversions,
            modifier = Modifier.padding(8.dp),
        )
    }
}

// Step: Align your body - Alignment
@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
            )
        )
    }
}

预览效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第7张图片

四、设置 Surface

接下来,设计矩形卡片,效果图如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第8张图片

代码如下:

// Step: Favorite collection card - Material Surface
@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),
                style = MaterialTheme.typography.h3,
                modifier = Modifier.padding(horizontal = 16.dp)
            )
        }
    }
}

预览效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第9张图片

五、横向列表

现在已经创建了屏幕上显示的基本可组合项,接下来可以实现横向列表了,布局如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第10张图片

每个网格是 8dp,所以第一项和最后一项距边缘为 16dp,各图之间为 8dp,代码如下:

// Step: Align your body row - Arrangements
@Composable
fun AlignYourBodyRow(
    modifier: Modifier = Modifier
) {
    LazyRow(
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        contentPadding = PaddingValues(horizontal = 16.dp),
        modifier = modifier
    ) {
        items(alignYourBodyData) { item ->
            AlignYourBodyElement(item.drawable, item.text)
        }
    }
}

预览后,效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第11张图片

六、实现 LazyHorizontalGrid

接下来要实现的是 Grid,而不是上文的 Row。

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

// Step: Favorite collection card - Material Surface
@Composable
fun FavoriteCollectionCard(
    modifier: Modifier = Modifier,
    @DrawableRes drawable: Int,
    @StringRes text: Int
) {
    Surface(shape = MaterialTheme.shapes.small, modifier = modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.width(192.dp)
        ) {
            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)
            )
        }
    }
}

预览后,效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第12张图片

七、首页的槽位 API

在 MySoothe 主屏幕中,有多个版块都遵循同一模式。每个版块都有一个标题,其中包含的内容因版块而异。我们想要实现的设计如下所示:
【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第13张图片

因为每个板块,都有一个标题,一个槽位。标题包含一些与其相关的间距和样式信息。可以使用不同的内容动态填充槽位,具体取决于版块。如需实现这个灵活的版块容器,可以用槽位 API,代码如下:

// Step: Home section - Slot APIs
@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()
        }
    }
}

效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第14张图片

八、主屏幕的滚动

现在,已经创建了所有单独的构建块,接下来可以将它们组合成一个全屏实现了,效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第15张图片

代码如下:

@Preview(showBackground = true, backgroundColor = 0xFFF0EAE2)
@Composable
fun BottomNavigationPreview() {
    MySootheTheme { SootheBottomNavigation(Modifier.padding(top = 24.dp)) }
}

// Step: Home screen - Scrolling
@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
    Column(
        modifier
            .verticalScroll(rememberScrollState())
            .padding(vertical = 16.dp)
    ) {
        SearchBar(Modifier.padding(horizontal = 16.dp))
        HomeSection(title = R.string.align_your_body) {
            AlignYourBodyRow()
        }
        HomeSection(title = R.string.favorite_collections) {
            FavoriteCollectionsGrid()
        }
    }
}

效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第16张图片

九、底部导航栏

// Step: Bottom navigation - Material
@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
    BottomNavigation(modifier, backgroundColor = MaterialTheme.colors.background) {
        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.AccountCircle, contentDescription = null)
            },
            label = {
                Text(stringResource(R.string.bottom_navigation_profile))
            },
            selected = false,
            onClick = {}
        )
    }
}

效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第17张图片

十、整体 App 集成

// Step: MySoothe App - Scaffold
@Composable
fun MySootheApp() {
    MySootheTheme {
        Scaffold(bottomBar = { SootheBottomNavigation() }) { padding ->
            HomeScreen(Modifier.padding(padding))
        }
    }
}

整体 App 效果如下:

【Android-JetpackCompose】10、基于 Compose 基本布局的健身 App_第18张图片

你可能感兴趣的:(android,jetpack,android,kotlin)