|
1 | 1 | package com.pureswift.swiftui |
2 | 2 |
|
3 | 3 | import androidx.compose.foundation.background |
| 4 | +import androidx.compose.foundation.border |
4 | 5 | import androidx.compose.foundation.clickable |
5 | 6 | import androidx.compose.foundation.rememberScrollState |
6 | 7 | import androidx.compose.foundation.horizontalScroll |
@@ -94,6 +95,7 @@ import androidx.compose.ui.draw.alpha |
94 | 95 | import androidx.compose.ui.draw.clip |
95 | 96 | import androidx.compose.ui.draw.rotate |
96 | 97 | import androidx.compose.ui.draw.scale |
| 98 | +import androidx.compose.ui.draw.shadow |
97 | 99 | import androidx.compose.ui.graphics.Brush |
98 | 100 | import androidx.compose.ui.graphics.Color |
99 | 101 | import androidx.compose.ui.graphics.RectangleShape |
@@ -193,13 +195,27 @@ fun Render(node: ViewNode) { |
193 | 195 | } |
194 | 196 | } |
195 | 197 |
|
| 198 | + // A Color greedily fills the space offered it (SwiftUI semantics); |
| 199 | + // fillMaxWidth is applied after the chain so an explicit frame width |
| 200 | + // still constrains it. |
196 | 201 | "Color" -> Box( |
197 | 202 | modifier = node.composeModifiers() |
| 203 | + .fillMaxWidth() |
198 | 204 | .background(Color((node.long("color") ?: 0).toInt())) |
199 | 205 | ) |
200 | 206 |
|
201 | 207 | "Image" -> RenderImage(node) |
202 | 208 |
|
| 209 | + "Overlay" -> Box( |
| 210 | + contentAlignment = zStackAlignment(node), |
| 211 | + modifier = node.composeModifiers(), |
| 212 | + ) { |
| 213 | + node.children.getOrNull(0)?.let { Render(it) } |
| 214 | + Box(modifier = Modifier.matchParentSize(), contentAlignment = zStackAlignment(node)) { |
| 215 | + node.children.getOrNull(1)?.let { Render(it) } |
| 216 | + } |
| 217 | + } |
| 218 | + |
203 | 219 | "Shape" -> RenderShape(node) |
204 | 220 |
|
205 | 221 | "LinearGradient" -> RenderGradient(node) |
@@ -529,10 +545,10 @@ private fun RenderGradient(node: ViewNode) { |
529 | 545 | startX == endX -> Brush.verticalGradient(colors) |
530 | 546 | else -> Brush.linearGradient(colors) |
531 | 547 | } |
532 | | - // A gradient fills the available width by default (SwiftUI semantics); an |
533 | | - // explicit frame width in the chain still constrains it. fillMaxWidth is |
534 | | - // first so a cornerRadius clip in the chain sees the full width. |
535 | | - Box(modifier = Modifier.fillMaxWidth().then(node.composeModifiers()).background(brush)) |
| 548 | + // A gradient fills the available width by default (SwiftUI semantics); |
| 549 | + // fillMaxWidth is applied after the chain so an explicit frame width still |
| 550 | + // constrains it. |
| 551 | + Box(modifier = node.composeModifiers().fillMaxWidth().background(brush)) |
536 | 552 | } |
537 | 553 |
|
538 | 554 | @Composable |
@@ -720,6 +736,23 @@ internal fun ViewNode.composeModifiers(): Modifier { |
720 | 736 |
|
721 | 737 | "opacity" -> modifier.alpha((entry.args.double("opacity") ?: 1.0).toFloat()) |
722 | 738 |
|
| 739 | + "border" -> { |
| 740 | + val color = entry.args.long("color")?.let { Color(it.toInt()) } ?: Color.Black |
| 741 | + modifier.border((entry.args.double("width") ?: 1.0).dp, color) |
| 742 | + } |
| 743 | + |
| 744 | + "shadow" -> modifier.shadow((entry.args.double("radius") ?: 0.0).dp) |
| 745 | + |
| 746 | + "clipShape" -> { |
| 747 | + val shape = when (entry.args.string("shape")) { |
| 748 | + "circle" -> CircleShape |
| 749 | + "capsule" -> RoundedCornerShape(percent = 50) |
| 750 | + "roundedRectangle" -> RoundedCornerShape((entry.args.double("cornerRadius") ?: 0.0).dp) |
| 751 | + else -> RectangleShape |
| 752 | + } |
| 753 | + modifier.clip(shape) |
| 754 | + } |
| 755 | + |
723 | 756 | "onTapGesture" -> { |
724 | 757 | val id = entry.args.long("action") |
725 | 758 | if (id != null) modifier.clickable { SwiftBridge.sink.invokeVoid(id) } else modifier |
|
0 commit comments