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