Jetpack Compose(第五趴)——Jetpack Compose主题设置(下)

咱们书接上文,

四、处理颜色

在上一步骤中,我们了解了如何创建自己的主题,以为您的应用设置颜色、字体样式和形状。所有Material组件开箱即可使用这些自定义功能。例如,FloatingActionButton可组合项默认使用主题中的secondary颜色,但您可以通过为此参数指定不同的值来设置备用颜色”

@Composable







fun FloatingActionButton(
    backgroundColor: Color = MaterialTheme.colors.secondary,
    ...


) {



}


有时,您并不想使用默认证书。

4.1、原色

如前所述,Compose提供了一个Color类。您可以在本地创建这些类,并将其保留在object等元素中:

Surface(color = Color.LightGray) {
    Text(

        text = "Hard coded colors don't respond to theme changes :(",
        textColor = Color(0xffff00ff)
    )


}


Color中有许多有用的方法,例如copy,您可以通过此方法使用不同的alpha/red/green/blue值来创建新的颜色。

4.2、主题颜色

一种更灵活的方法是从主题中检索颜色:

Surface(color = MaterialTheme.colors.primary)

下面,我们要使用MaterialTheme object,其colors属性会返回在MaterialTheme可组合项中设置的Colors。这意味着,我们只需为主题提供不同的颜色集,即可支持不同的外观和风格,而无需处理应用代码。例如,我们的AppBar使用primary颜色,屏幕北京使用surface颜色;如果更改主题颜色,相应设置会反映在以下可组合项中:

image.png

image.png

由于主题中的每种颜色都是Color实例,因此我们还可以使用copy方法轻松地”派生“颜色:

val deriverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.1f)

下面,我们要复制onSurface颜色,但要将透明度设为10%。此方法可确保颜色能够在不同主题下正常显示,而无需硬编码静态颜色。

4.3、Surface颜色和内容颜色

许多组件都接受一对颜色和”内容颜色“:

Surface(

    color: Color = MaterialTheme.colors.surface,
    contentColor: Color = contentColorFor(color),
    ...


)


TopAppBar(
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor),
    ...
)

这样一来,您不仅可以设置可组合项的颜色,而且还能为“内容”(即包含在其中的可组合项)提供默认颜色。默认情况下,许多可组合项都使用这种颜色,例如Text颜色或Icon色调。contentColorFor方法可以为任何主题颜色检索适当的”on”颜色,例如,如果您设置primary背景,它就会返回onPrimary作为内容颜色。如果您设置非主体背景颜色,则应自行提供合理的内容颜色。

Surface(color = MaterialTheme.colors.primary) {
    Text(...) // default text color is 'onPrimary'
}

Surface(color = MaterialTheme.colors.error) {
    Icon(...) // default tint is 'onError'
}


您可以使用LocalContentColor CompositionLocal来检索与当前背景形成对比的颜色:

BottomNavigationItem(
    unselectedContentColor = LocalContentColor.current ...
)


当设置任何元素的颜色时,最好使用Surface来实现此目的,因为它会设置适当的内容颜色CompositionLocal值。请慎用直接Modifier.background调用,这种调用不会设置适当的内容颜色。

-Row(Modifier.background(MaterialTheme.colors.primary)) {
+Surface(color = MaterialTheme.colors.primary) {
+ Row(
...

目前,我们的Header组件始终具有Color.LightGray背景。在这浅色主题中看起来没有问题,但在深色主题中,就会与背景成高度对比。此外,它们也不指定特定的文本颜色,因此会集成可能不会与背景形成对比的当前内容颜色:

image.png

接下来,让我们解决这个问题。在Home.ktHeader可组合项中,移出用于指定硬编码颜色的background修饰符。改为将Text封装在包含主题派生颜色的Surface中,并指定相应内容应采用primary颜色:

+ Surface(
+   color = MaterialTheme.colors.onSurface.copy(alpha = 0.1f),
+   contentColor = MaterialTheme.colors.primary,
+   modifier = modifier
+ ) {
    Text(
        text = text,
        modifier = Modifier
            .fillMaxWitdh()
-           .background(Color.LightGray)
            .padding(horizontal = 16.dp, vertical = 8.dp)
    )
+}

4.4、内容Alpha值

通常情况下,我们希望通过强调或弱化内容来突出重点并体现出视觉上的层次感。Material Design建议采用不同的透明度来传达这些不同的重要程度。

Jetpack Compose通过LocalContentAlpha实现此功能。您可以通过为此CompositionLocal提供一个值来为层次结构指定内容Alpha值。子可组合项可以使用此值,例如TextIcon默认使用LocalContentColor的组合,已调整为使用LocalContentAlpha。Material指定了一些标准Alpha值(highmediumdisabled),这些值由ContentAlpha对象建模。请注意,MaterialTheme默认将LocalContentAlpha设置为ContentAlpha.high

// By default, both Icon & Text use the combination of LocalContentColor & 
// LocalContentAlpha. De-emphasize content by setting a different content alpha
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(...)
}
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Icon(...)
    Text(...)
}



这样即可方便又一致地突出组件的重要性。

我们将使用内容Alpha值来阐明精选博文的信息层次结构。在Home.ktPostMetadata可组合项中,重点突出元数据medium:

+ CompositioLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(

        text = text,
        modifier = modifier
    )


+}

image.png

### 4.5、深色主题
如我们所见,若要在Compose中实现深色主题,您只需提供不同的颜色集并通过主题查询颜色即可。下面是一些需要注意的例外情况:

您可以检查您是否在浅色主题中运行:

val isLightTheme = MaterialTheme.colors.isLight

此值由lightColors/darkColors构建器函数设置。

在Material中,如果采用的是深色主题,高度较高的Surface会获得高度层加层(其背景颜色会变浅)。
在使用深色调色板时,系统会自动实现此效果:

Surface(

    elevation = 2.dp,
    color = MaterialTheme.colors.surface, // color will be adjusted for elevation
    ...


在我们的应用中,我们可以在我们使用的TopAppBarCard组件中看到上述自动行为;默认情况下,这两种组件的高度分别设为4dp和1dp,因此,在深色主题中,它们的背景颜色会自动变浅,以更好地表现相应高度:

image.png

Material Design建议避免在深色主题中使用大面积的明亮颜色。一种常见模式是在浅色主题中将容器设为primary颜色,并在深色追中将其设为surface颜色;许多组件都默认使用此策略,例如应用栏和底部导航栏。为了便于实现,Colors提供了primarySurface颜色,以准确完成上述行为,并且这些组件都默认使用此颜色。

目前,我们的应用将应用栏设置为primary颜色;若要遵循此指南,只需将其切换为primarySurface或移出此形参(因为此形参为默认设置)即可。在AppBar可组合项中,更改TopAppBarbackgroundColor参数:

@Composable







private fun AppBar() {
    TopAppBar(
        ...
-       backgroundColor = MaterialTheme.colors.primary,
+       backgroundColor = MaterialTheme.colors.primarySurface
    )



}


五、处理文本

在处理文本时,我们使用Text可组合项来显示文本,使用TextFiledOutlinedTextField进行文本输入,并使用TextStyle对文本应用单一样式。我们可以使用AnnotatedString对于文本应用多种样式。

正如我们在设置颜色时所看到的那样,用于显示文本的Material组件将获取我们的主题排版自定义设置:

Button(...) {
    Text("This text will use MaterialTheme. typography .button style by default")
}

实现此目的要比使用默认参数(如在设置颜色时所看到的那样)略微复杂一些。这是因为组件本身往往不会显示文本,而是提供槽API,让您能够传入Text可组合项。那么,组件是如何设置主题排版演示的呢?在后台,它们使用ProvideTextStyle可组合项(本身就使用CompositionLocal)来设置”current”TextStyle。如果您未提供具体的testStyle参数,Text可组合项会默认查询此“current”样式。

例如,通过Compose的Button类和Text类:

@Composable







fun Button(
    // many other parameters
    content: @Composable RowScope.() -> Unit
) {



    ...
    ProvideTextStyle(MaterialTheme.typography.button) { // set the "current" text style
        ...
        content()
    }
}

@Composable
fun Text(
    // many, many parameters
    style: TextStyle = LocalTextStyle.current // get the value set by ProvideTextStyle
) { ...

5.1、主题文本样式

就像处理颜色时一样,最好从当前主题检索TextStyle,从而鼓励您使用一组数量数量少且一致的样式,并使其更易于维护。MaterialTheme.typography会检索在MaterialTheme可组合项中设置的Typography实例,让您能够使用自己定义的样式:

Text(


    style = MaterialTheme.typography.subtitle2
)


如果您需要自定义TextStyle,可以对其执行copy操作并替换相关属性(它只是一个data class),或者让Text可组合项接受大量样式形参,这些形参会叠加到任何TextStyle的上层:

Text(


    text = "Hello World",

    style = MaterialTheme.typography.body1.copy(
        background = MaterialTheme.colors.secondary
    )


)
Text(


    text = "Hello World",

    style = MaterialTheme.typography.subtitle2,
    fontSize = 22.sp // explicit size ovverrides the size in the style
)

在我们的应用中,许多地方都会自动应用主题TextStyle,例如,TopAppBar将其title的样式设为h6,并将坐着信息和元数据设为body2

@Composable







fun Header(...) {
    ...


    Text(
        text = text,
+        style = MaterialTheme.typography.subtitle2
    )



}


image.png

5.2、多种样式

如果您需要对某些文本应用多种样式,可以使用AnnotatedString类来应用标记,从而为一系列文本添加SpanStyle。您可以动态添加这些元素,也可以使用DSL语法来创建内容:

val text = buildAnnotatedString {
    append("This is some unstyled text\n")
    withStyle(SpanStyle(color = Color.Red)) {
        append("Red text\n")
    }
    withStyle(SpanStyle(fontSize = 24.sp)) {
        append("Large text")
    }

}



接下来,我们要为描述应用中的各个博文和标签设置样式。目前,它们使用与元数据其余部分相同的文本样式;我们将使用overline文本样式和北京颜色来区分它们。在PostMetadata可组合项中:

+ val tagStyle = + MaterialTheme.typography.overline.toSpanStyle().copy(
+    background = MaterialTheme.colors.primary.copy(alpha = 0.1f)
)


post.tags.forEachIndexed { index, tag ->
    ...
+    withStyle(tagStyle) {
        append(" ${tag.toUpperCase()} ")
 +   }
}



image.png

## 六、处理形状
与颜色和排版一样,如果设置形状主题,相应设置会反映在Material组件中。例如,`Button`会获取为小型组件设置的形状:
“`
@Composable
fun Button( …
shape: Shape = MaterialTheme.shapes.small
)
“`
与颜色一样,Material组件爱你使用默认参数,因此您可以直接查看组件将要使用的形状类别,或提供替代方案。

请注意,有些组件会使用经过修改的主题形状,以适应上下文的要求。例如,默认情况下,TextField使用小型形状逐日,但它会对底角应用零边角大小:

@Composable







fun FilledTextField(
    // other parameters
    shape: Shape = MaterialTheme.shapes.small.copy(
        bottomStart = ZeroCornerSize, // overrides small theme style
        bottomEnd = ZeroCornerSize // overrides small theme style
    )



) {

image.png

6.1、主题形状

当然,在您创建自己的额组件时,您可以自行使用各种形状;为此,您需要使用接受形状的可组合项或Modifier(例如,SurfaceModifier.clipModifier.backgroundModifier.border等)。

@Composable







fun UserProfile(
    ...


    shape: Shape = MaterialTheme.shapes.medium
) {



    Surface(shape = shape) {
        ...
    }

}



接下来,我们要将形状主题添加到PostItem中显示的图片;我们要对齐应用的主题small形状,并使用clip Modifier窃取左上角:

@Composable







fun PostItem(...) {
    ...


    Image (
        painter = painterResource(post.imageThumbId),
+        modifier = Modifier.clip(shape = MaterialTheme.shape.small)
    )



}


image.png

七、组件“样式”

Compose没有提供用于提取组件样式(例如,Android View样式或CSS样式)的明确方法。由于所有Compose组件都是Kotlin编写,因此它可通过其他方法来实现相同的目的。您可以改为创建自己的自定义组件库,并在整个应用中使用这些组件。

我们已经在我们的应用中这样做了:

@Composable
fun Header(
    text: String,
    modifier = Modifier = Modifier
) {



    Surface(
        color = MaterialTheme.colors.onSurface.copy(alpha = 0.1f),
        contentColor = MaterialTheme.colors.primary,
        modifier = modifier.semantics { heading() }
    ) {
        Text(
            text = text,
            style = MaterialTheme.typography.subtitle2,
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontao = 16.dp, vertical = 8.dp)
        )
    }
}

Header可组合项本质上是样式化的Text,可供我们在整个应用中使用。

我们都看到了,所有组件都是由较低级别的构建块构造而成的,您可以使用相同的构建块来自定义Material组件。例如,我们看到Button使用ProvideTextStyle可组合项为传递给它的内容设置默认文本样式。您可以使用完全相同的机制来设置自己的文本样式:

@Composable
fun LoginButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        color = ButtonConstants.defaultButtonColors(
            backgroundColor = MaterialTheme.colors.secondary
        ),
        onClick = onClick,
        modifier = modifier
    ) {
        ProvideTextStyle(...) { // set our own text style
            content()
        }
    }
}

在此实例中,我们创建了自己的LoginButton”样式“,方法是封装标准Button类,然后指定特定属性(例如不同的backgroundColor和文本样式)。

此外,也没有默认样式(即自定义某个组件类型的默认外观的方法)的概念。同样,为实现此目的,您可以创建您自己的组件,用于封装和自定义库组件。例如,您想自定义应用中所有Button的形状,但不想更改小型形状主题,因为更改小型形状主题会影响其他(非Button组件)。
如需实现此目的,您尅创建自己的可组合项并在整个应用中使用此可组合项:

@Composable







fun AcmeButton(
    // expose Button params consumers should be able to change
) {
    val acmeButtonShape: Shape = ...
    Button(
        shape = acmeButtonShape,
        // other params
    )
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYx8Y23w' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片