1 /*
2 * Copyright (C) 2024 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 com.android.settingslib.spa.widget.preference
18
19 import androidx.compose.foundation.background
20 import androidx.compose.foundation.layout.Box
21 import androidx.compose.foundation.layout.Column
22 import androidx.compose.foundation.layout.padding
23 import androidx.compose.foundation.layout.size
24 import androidx.compose.material.icons.Icons
25 import androidx.compose.material.icons.filled.History
26 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
27 import androidx.compose.material3.Icon
28 import androidx.compose.material3.MaterialTheme
29 import androidx.compose.material3.Text
30 import androidx.compose.runtime.Composable
31 import androidx.compose.runtime.remember
32 import androidx.compose.ui.Alignment
33 import androidx.compose.ui.Modifier
34 import androidx.compose.ui.draw.clip
35 import androidx.compose.ui.geometry.Size
36 import androidx.compose.ui.graphics.Matrix
37 import androidx.compose.ui.graphics.Outline
38 import androidx.compose.ui.graphics.Path
39 import androidx.compose.ui.graphics.Shape
40 import androidx.compose.ui.graphics.asComposePath
41 import androidx.compose.ui.graphics.vector.ImageVector
42 import androidx.compose.ui.text.style.TextAlign
43 import androidx.compose.ui.tooling.preview.Preview
44 import androidx.compose.ui.unit.Density
45 import androidx.compose.ui.unit.LayoutDirection
46 import androidx.compose.ui.unit.dp
47 import androidx.graphics.shapes.CornerRounding
48 import androidx.graphics.shapes.RoundedPolygon
49 import androidx.graphics.shapes.star
50 import androidx.graphics.shapes.toPath
51
52 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
53 @Composable
ZeroStatePreferencenull54 fun ZeroStatePreference(icon: ImageVector, text: String? = null, description: String? = null) {
55 val zeroStateShape = remember {
56 RoundedPolygon.star(
57 numVerticesPerRadius = 6,
58 innerRadius = 0.8f,
59 rounding = CornerRounding(0.3f)
60 )
61 }
62 val clip = remember(zeroStateShape) {
63 RoundedPolygonShape(polygon = zeroStateShape)
64 }
65 Column(horizontalAlignment = Alignment.CenterHorizontally) {
66 Box(
67 modifier = Modifier
68 .clip(clip)
69 .background(MaterialTheme.colorScheme.primary)
70 .size(160.dp)
71 ) {
72 Icon(
73 imageVector = icon,
74 modifier = Modifier
75 .align(Alignment.Center)
76 .size(72.dp),
77 tint = MaterialTheme.colorScheme.onPrimary,
78 contentDescription = null,
79 )
80 }
81 if (text != null) {
82 Text(
83 text = text,
84 textAlign = TextAlign.Center,
85 style = MaterialTheme.typography.titleMediumEmphasized,
86 color = MaterialTheme.colorScheme.onSurfaceVariant,
87 modifier = Modifier.padding(top = 24.dp),
88 )
89 }
90 if (description != null) {
91 Box {
92 Text(
93 text = description,
94 textAlign = TextAlign.Center,
95 style = MaterialTheme.typography.bodyMedium,
96 color = MaterialTheme.colorScheme.onSurfaceVariant,
97 )
98 }
99 }
100 }
101 }
102
103 @Preview
104 @Composable
ZeroStatePreferencePreviewnull105 private fun ZeroStatePreferencePreview() {
106 ZeroStatePreference(
107 Icons.Filled.History,
108 "No recent search history",
109 "Description"
110 )
111 }
112
113 class RoundedPolygonShape(
114 private val polygon: RoundedPolygon,
115 private var matrix: Matrix = Matrix()
116 ) : Shape {
117 private var path = Path()
createOutlinenull118 override fun createOutline(
119 size: Size,
120 layoutDirection: LayoutDirection,
121 density: Density
122 ): Outline {
123 path.rewind()
124 path = polygon.toPath().asComposePath()
125
126 matrix.reset()
127 matrix.scale(size.width / 2f, size.height / 2f)
128 matrix.translate(1f, 1f)
129 matrix.rotateZ(30.0f)
130
131 path.transform(matrix)
132 return Outline.Generic(path)
133 }
134 }