Skip to content
This repository was archived by the owner on Dec 27, 2024. It is now read-only.

Commit d569887

Browse files
authored
Add support for user-customizable design elements (#350)
1 parent a0ee41a commit d569887

File tree

3 files changed

+111
-36
lines changed

3 files changed

+111
-36
lines changed

constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintLayout.kt

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,29 @@ import android.os.Looper
2222
import android.util.Log
2323
import androidx.annotation.FloatRange
2424
import androidx.compose.foundation.Canvas
25-
//import androidx.compose.foundation.Image
25+
import androidx.compose.foundation.Image
26+
import androidx.compose.foundation.background
2627
import androidx.compose.foundation.layout.Box
2728
import androidx.compose.foundation.layout.BoxScope
2829
import androidx.compose.foundation.layout.LayoutScopeMarker
29-
//import androidx.compose.material.Button
30-
//import androidx.compose.material.Text
30+
import androidx.compose.foundation.layout.padding
31+
import androidx.compose.foundation.shape.RoundedCornerShape
32+
import androidx.compose.foundation.text.BasicText
33+
import androidx.compose.foundation.text.BasicTextField
3134
import androidx.compose.runtime.*
3235
import androidx.compose.runtime.snapshots.SnapshotStateObserver
3336
import androidx.compose.ui.Modifier
37+
import androidx.compose.ui.draw.clip
3438
import androidx.compose.ui.draw.scale
3539
import androidx.compose.ui.geometry.Offset
3640
import androidx.compose.ui.graphics.*
3741
import androidx.compose.ui.layout.*
3842
import androidx.compose.ui.platform.InspectorValueInfo
3943
import androidx.compose.ui.platform.debugInspectorInfo
44+
import androidx.compose.ui.res.painterResource
4045
import androidx.compose.ui.semantics.semantics
41-
import androidx.compose.ui.unit.Constraints
42-
import androidx.compose.ui.unit.Density
43-
import androidx.compose.ui.unit.Dp
44-
import androidx.compose.ui.unit.IntOffset
45-
import androidx.compose.ui.unit.IntSize
46-
import androidx.compose.ui.unit.LayoutDirection
47-
import androidx.compose.ui.unit.dp
46+
import androidx.compose.ui.text.TextStyle
47+
import androidx.compose.ui.unit.*
4848
import androidx.compose.ui.util.fastForEach
4949
import androidx.compose.ui.util.fastForEachIndexed
5050
import androidx.constraintlayout.core.parser.CLKey
@@ -63,7 +63,6 @@ import androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviou
6363
import androidx.constraintlayout.core.widgets.analyzer.BasicMeasure
6464
import androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure.TRY_GIVEN_DIMENSIONS
6565
import androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure.USE_GIVEN_DIMENSIONS
66-
//import com.google.accompanist.coil.rememberCoilPainter
6766
import org.intellij.lang.annotations.Language
6867
import java.lang.StringBuilder
6968
import java.util.*
@@ -1567,7 +1566,7 @@ open class EditableJSONLayout(@Language("json5") content: String) :
15671566
}
15681567
}
15691568

1570-
data class DesignElement(var id: String, var type: String, var param: String)
1569+
data class DesignElement(var id: String, var type: String, var params: HashMap<String, String>)
15711570

15721571
class JSONConstraintSet(@Language("json5") content: String,
15731572
@Language("json5") overrideVariables: String? = null)
@@ -2183,27 +2182,53 @@ internal open class Measurer : BasicMeasure.Measurer, DesignInfoProvider {
21832182
fun createDesignElements() {
21842183
for (element in designElements) {
21852184
var id = element.id
2186-
when (element.type) {
2187-
/* // commenting for now until we provide hooks
2188-
"button" -> {
2189-
Button(
2190-
modifier = Modifier.layoutId(id),
2191-
onClick = {},
2192-
) {
2193-
Text(text = element.param)
2185+
var function = DesignElements.map[element.type]
2186+
if (function != null) {
2187+
function(id, element.params)
2188+
} else {
2189+
when (element.type) {
2190+
"button" -> {
2191+
val text = element.params["text"] ?: "text"
2192+
var style = TextStyle.Default
2193+
val fontSizeString = element.params["size"]
2194+
if (fontSizeString != null) {
2195+
val fontSize = fontSizeString.toFloat().sp
2196+
style = TextStyle(fontSize = fontSize)
2197+
}
2198+
BasicText(modifier = Modifier
2199+
.layoutId(id)
2200+
.clip(RoundedCornerShape(20))
2201+
.background(Color.LightGray)
2202+
.padding(8.dp),
2203+
text = text, style = style)
2204+
}
2205+
"text" -> {
2206+
val text = element.params["text"] ?: "text"
2207+
var style = TextStyle.Default
2208+
val fontSizeString = element.params["size"]
2209+
if (fontSizeString != null) {
2210+
val fontSize = fontSizeString.toFloat().sp
2211+
style = TextStyle(fontSize = fontSize)
2212+
}
2213+
BasicText(modifier = Modifier.layoutId(id),
2214+
text = text, style = style)
2215+
}
2216+
"textfield" -> {
2217+
val text = element.params["text"] ?: "text"
2218+
BasicTextField(
2219+
modifier = Modifier.layoutId(id),
2220+
value = text,
2221+
onValueChange = {}
2222+
)
2223+
}
2224+
"image" -> {
2225+
Image(
2226+
modifier = Modifier.layoutId(id),
2227+
painter = painterResource(id = android.R.drawable.ic_menu_gallery),
2228+
contentDescription = "Placeholder Image"
2229+
)
21942230
}
21952231
}
2196-
"text" -> {
2197-
Text(modifier = Modifier.layoutId(id),
2198-
text=element.param)
2199-
}
2200-
"image" -> {
2201-
Image(modifier = Modifier.layoutId(id),
2202-
painter = rememberCoilPainter(element.param),
2203-
contentDescription = ""
2204-
)
2205-
}
2206-
*/
22072232
}
22082233
}
22092234
}
@@ -2215,6 +2240,13 @@ internal open class Measurer : BasicMeasure.Measurer, DesignInfoProvider {
22152240
}
22162241
}
22172242

2243+
object DesignElements {
2244+
var map = HashMap<String, @Composable (String, HashMap<String, String>) -> Unit >()
2245+
fun define(name: String, function : @Composable (String, HashMap<String, String>) -> Unit) {
2246+
map[name] = function
2247+
}
2248+
}
2249+
22182250
internal fun buildMapping(state: State, measurables: List<Measurable>) {
22192251
measurables.fastForEach { measurable ->
22202252
val parentData = measurable.parentData as? ConstraintLayoutParentData

constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintSetParser.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -695,11 +695,20 @@ fun parseDesignElementsJSON(content: String, list: ArrayList<DesignElement>) {
695695
val element = element.get(elementName) as CLObject
696696
System.out.printf("element found <$elementName>")
697697
val type = element.getStringOrNull("type")
698-
val param = element.getStringOrNull("param")
699-
val text = element.getStringOrNull("text")
700-
val parameter = if (param != null) param else text
701-
var designElement = DesignElement(elementName, type, parameter)
702-
list.add(designElement)
698+
if (type != null) {
699+
var parameters = HashMap<String, String>()
700+
val size = element.size()
701+
for (j in 0.. size -1) {
702+
val key = element[j] as CLKey
703+
val paramName = key.content()
704+
val paramValue = key.value?.content()
705+
if (paramValue != null) {
706+
parameters[paramName] = paramValue
707+
}
708+
}
709+
var designElement = DesignElement(elementName, type, parameters)
710+
list.add(designElement)
711+
}
703712
}
704713
}
705714
}

projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/MainActivity.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import android.view.View
55
import android.widget.FrameLayout
66
import android.widget.TextView
77
import androidx.appcompat.app.AppCompatActivity
8+
import androidx.compose.foundation.Image
9+
import androidx.compose.material.Button
10+
import androidx.compose.material.Text
811
import androidx.compose.material.ExperimentalMaterialApi
12+
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.layout.layoutId
914
import androidx.compose.ui.platform.ComposeView
1015
import androidx.constraintlayout.compose.*
1116
import androidx.constraintlayout.coreAndroid.PhoneState
17+
import com.google.accompanist.coil.rememberCoilPainter
1218

1319
class MainActivity : AppCompatActivity() {
1420
private var mFrameLayout: FrameLayout? = null
@@ -29,9 +35,37 @@ class MainActivity : AppCompatActivity() {
2935
map.put(30, "Cycle RotationZ")
3036
map.put(31, "Cycle RotationXY")
3137

38+
defineDesignElements()
3239
debugServer.start()
3340
}
3441

42+
private fun defineDesignElements() {
43+
DesignElements.define("wow") {
44+
id, params ->
45+
val text = params["text"] ?: "text"
46+
Text(modifier = Modifier.layoutId(id),
47+
text= text)
48+
}
49+
DesignElements.define("button") {
50+
id, params ->
51+
val text = params["text"] ?: "text"
52+
Button(modifier = Modifier.layoutId(id),
53+
onClick = {},
54+
) {
55+
Text(text = text)
56+
}
57+
}
58+
DesignElements.define("image") {
59+
id, params ->
60+
val url = params["url"] ?: "url"
61+
val description = params["description"] ?: "Image Description"
62+
Image(modifier = Modifier.layoutId(id),
63+
painter = rememberCoilPainter(url),
64+
contentDescription = description
65+
)
66+
}
67+
}
68+
3569
@ExperimentalMaterialApi
3670
private fun show(com: ComposeView) {
3771
println(" $composeNum ")

0 commit comments

Comments
 (0)