1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package androidx.compose.material3
18
19 import androidx.compose.foundation.LocalIndication
20 import androidx.compose.foundation.text.selection.LocalTextSelectionColors
21 import androidx.compose.foundation.text.selection.TextSelectionColors
22 import androidx.compose.runtime.Composable
23 import androidx.compose.runtime.CompositionLocalProvider
24 import androidx.compose.runtime.ReadOnlyComposable
25 import androidx.compose.runtime.remember
26 import androidx.compose.runtime.staticCompositionLocalOf
27
28 /**
29 * Material Theming refers to the customization of your Material Design app to better reflect your
30 * product’s brand.
31 *
32 * Material components such as [Button] and [Checkbox] use values provided here when retrieving
33 * default values.
34 *
35 * All values may be set by providing this component with the [colorScheme][ColorScheme],
36 * [typography][Typography] and [shapes][Shapes] attributes. Use this to configure the overall theme
37 * of elements within this MaterialTheme.
38 *
39 * Any values that are not set will inherit the current value from the theme, falling back to the
40 * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of
41 * your application, and then separate MaterialTheme(s) for different screens / parts of your UI,
42 * overriding only the parts of the theme definition that need to change.
43 *
44 * @sample androidx.compose.material3.samples.MaterialThemeSample
45 * @param colorScheme A complete definition of the Material Color theme for this hierarchy
46 * @param shapes A set of corner shapes to be used as this hierarchy's shape system
47 * @param typography A set of text styles to be used as this hierarchy's typography system
48 * @param content The content inheriting this theme
49 */
50 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
51 @Composable
MaterialThemenull52 fun MaterialTheme(
53 colorScheme: ColorScheme = MaterialTheme.colorScheme,
54 shapes: Shapes = MaterialTheme.shapes,
55 typography: Typography = MaterialTheme.typography,
56 content: @Composable () -> Unit
57 ) =
58 MaterialTheme(
59 colorScheme = colorScheme,
60 motionScheme = MaterialTheme.motionScheme,
61 shapes = shapes,
62 typography = typography,
63 content = content
64 )
65
66 /**
67 * Material Theming refers to the customization of your Material Design app to better reflect your
68 * product’s brand.
69 *
70 * Material components such as [Button] and [Checkbox] use values provided here when retrieving
71 * default values.
72 *
73 * All values may be set by providing this component with the [colorScheme][ColorScheme],
74 * [typography][Typography] attributes. Use this to configure the overall theme of elements within
75 * this MaterialTheme.
76 *
77 * Any values that are not set will inherit the current value from the theme, falling back to the
78 * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of
79 * your application, and then separate MaterialTheme(s) for different screens / parts of your UI,
80 * overriding only the parts of the theme definition that need to change.
81 *
82 * @param colorScheme A complete definition of the Material Color theme for this hierarchy
83 * @param motionScheme A complete definition of the Material Motion scheme for this hierarchy
84 * @param shapes A set of corner shapes to be used as this hierarchy's shape system
85 * @param typography A set of text styles to be used as this hierarchy's typography system
86 */
87 @ExperimentalMaterial3ExpressiveApi
88 @Composable
89 fun MaterialTheme(
90 colorScheme: ColorScheme = MaterialTheme.colorScheme,
91 motionScheme: MotionScheme = MaterialTheme.motionScheme,
92 shapes: Shapes = MaterialTheme.shapes,
93 typography: Typography = MaterialTheme.typography,
94 content: @Composable () -> Unit
95 ) {
96 val rippleIndication = ripple()
97 val selectionColors = rememberTextSelectionColors(colorScheme)
98 CompositionLocalProvider(
99 LocalColorScheme provides colorScheme,
100 LocalMotionScheme provides motionScheme,
101 LocalIndication provides rippleIndication,
102 LocalShapes provides shapes,
103 LocalTextSelectionColors provides selectionColors,
104 LocalTypography provides typography,
105 ) {
106 ProvideTextStyle(value = typography.bodyLarge, content = content)
107 }
108 }
109
110 /**
111 * Contains functions to access the current theme values provided at the call site's position in the
112 * hierarchy.
113 */
114 object MaterialTheme {
115 /**
116 * Retrieves the current [ColorScheme] at the call site's position in the hierarchy.
117 *
118 * @sample androidx.compose.material3.samples.ThemeColorSample
119 */
120 val colorScheme: ColorScheme
121 @Composable @ReadOnlyComposable get() = LocalColorScheme.current
122
123 /**
124 * Retrieves the current [Typography] at the call site's position in the hierarchy.
125 *
126 * @sample androidx.compose.material3.samples.ThemeTextStyleSample
127 */
128 val typography: Typography
129 @Composable @ReadOnlyComposable get() = LocalTypography.current
130
131 /**
132 * Retrieves the current [Shapes] at the call site's position in the hierarchy.
133 *
134 * @sample androidx.compose.material3.samples.ThemeShapeSample
135 */
136 val shapes: Shapes
137 @Composable @ReadOnlyComposable get() = LocalShapes.current
138
139 /** Retrieves the current [MotionScheme] at the call site's position in the hierarchy. */
140 @ExperimentalMaterial3ExpressiveApi
141 val motionScheme: MotionScheme
142 @Composable @ReadOnlyComposable get() = LocalMotionScheme.current
143 }
144
145 /**
146 * Material Expressive Theming refers to the customization of your Material Design app to better
147 * reflect your product’s brand.
148 *
149 * Material components such as [Button] and [Checkbox] use values provided here when retrieving
150 * default values.
151 *
152 * All values may be set by providing this component with the [colorScheme][ColorScheme],
153 * [typography][Typography], [shapes][Shapes] attributes. Use this to configure the overall theme of
154 * elements within this MaterialTheme.
155 *
156 * Any values that are not set will fall back to the defaults. To inherit the current value from the
157 * theme, pass them into subsequent calls and override only the parts of the theme definition that
158 * need to change.
159 *
160 * Alternatively, only call this function at the top of your application, and then call
161 * [MaterialTheme] to specify separate MaterialTheme(s) for different screens / parts of your UI,
162 * overriding only the parts of the theme definition that need to change.
163 *
164 * @sample androidx.compose.material3.samples.MaterialExpressiveThemeSample
165 * @param colorScheme A complete definition of the Material Color theme for this hierarchy
166 * @param motionScheme A complete definition of the Material motion theme for this hierarchy
167 * @param shapes A set of corner shapes to be used as this hierarchy's shape system
168 * @param typography A set of text styles to be used as this hierarchy's typography system
169 * @param content The content inheriting this theme
170 */
171 @ExperimentalMaterial3ExpressiveApi
172 @Composable
MaterialExpressiveThemenull173 fun MaterialExpressiveTheme(
174 colorScheme: ColorScheme? = null,
175 motionScheme: MotionScheme? = null,
176 shapes: Shapes? = null,
177 typography: Typography? = null,
178 content: @Composable () -> Unit
179 ) {
180 if (LocalUsingExpressiveTheme.current) {
181 MaterialTheme(
182 colorScheme = colorScheme ?: MaterialTheme.colorScheme,
183 motionScheme = motionScheme ?: MaterialTheme.motionScheme,
184 typography = typography ?: MaterialTheme.typography,
185 shapes = shapes ?: MaterialTheme.shapes,
186 content = content
187 )
188 } else {
189 CompositionLocalProvider(LocalUsingExpressiveTheme provides true) {
190 MaterialTheme(
191 colorScheme = colorScheme ?: expressiveLightColorScheme(),
192 motionScheme = motionScheme ?: MotionScheme.expressive(),
193 shapes = shapes ?: Shapes(),
194 // TODO: replace with calls to Expressive typography default
195 typography = typography ?: Typography(),
196 content = content
197 )
198 }
199 }
200 }
201
<lambda>null202 internal val LocalUsingExpressiveTheme = staticCompositionLocalOf { false }
203
204 @Composable
205 /*@VisibleForTesting*/
rememberTextSelectionColorsnull206 internal fun rememberTextSelectionColors(colorScheme: ColorScheme): TextSelectionColors {
207 val primaryColor = colorScheme.primary
208 return remember(primaryColor) {
209 TextSelectionColors(
210 handleColor = primaryColor,
211 backgroundColor = primaryColor.copy(alpha = TextSelectionBackgroundOpacity),
212 )
213 }
214 }
215
216 /*@VisibleForTesting*/
217 internal const val TextSelectionBackgroundOpacity = 0.4f
218