Skip to content

Commit

Permalink
Merge pull request #75 from skiptools/layoutfixes2
Browse files Browse the repository at this point in the history
Layout fixes + fix regression in views with minHeight in ScrollView
  • Loading branch information
aabewhite authored Oct 15, 2024
2 parents 63d270e + fa9e3ef commit 81f10ed
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 32 deletions.
6 changes: 3 additions & 3 deletions Sources/SkipUI/SkipUI/Compose/ComposeContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import androidx.compose.ui.Modifier
/// that if the container content uses them, the container itself can recompose with the appropriate expansion to match its
/// content. Note that this generally only affects final layout when an expanding child is in a container that is itself in a
/// container, and it has to share space with other members of the parent container.
@Composable public func ComposeContainer(axis: Axis? = nil, eraseAxis: Bool = false, scrollAxes: Axis.Set = [], modifier: Modifier = Modifier, fillWidth: Bool = false, fixedWidth: Bool = false, fillHeight: Bool = false, fixedHeight: Bool = false, then: Modifier = Modifier, content: @Composable (Modifier) -> Void) {
@Composable public func ComposeContainer(axis: Axis? = nil, eraseAxis: Bool = false, scrollAxes: Axis.Set = [], modifier: Modifier = Modifier, fillWidth: Bool = false, fixedWidth: Bool = false, minWidth: Bool = false, fillHeight: Bool = false, fixedHeight: Bool = false, minHeight: Bool = false, then: Modifier = Modifier, content: @Composable (Modifier) -> Void) {
// Use remembered expansion values to recompose on change
let isFillWidth = remember { mutableStateOf(fillWidth) }
let isFillHeight = remember { mutableStateOf(fillHeight) }
Expand All @@ -45,7 +45,7 @@ import androidx.compose.ui.Modifier
var modifier = modifier
let inheritedLayoutScrollAxes = EnvironmentValues.shared._layoutScrollAxes
var totalLayoutScrollAxes = inheritedLayoutScrollAxes
if fixedWidth || axis == .vertical {
if fixedWidth || minWidth || axis == .vertical {
totalLayoutScrollAxes.remove(Axis.Set.horizontal)
}
if !fixedWidth && isFillWidth.value {
Expand All @@ -57,7 +57,7 @@ import androidx.compose.ui.Modifier
modifier = modifier.fillWidth()
}
}
if fixedHeight || axis == .horizontal {
if fixedHeight || minHeight || axis == .horizontal {
totalLayoutScrollAxes.remove(Axis.Set.vertical)
}
if !fixedHeight && isFillHeight.value {
Expand Down
58 changes: 29 additions & 29 deletions Sources/SkipUI/SkipUI/Compose/ComposeLayouts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ import androidx.compose.ui.unit.dp
} else if minHeight != nil || maxHeight != nil {
thenModifier = thenModifier.requiredHeightIn(min: minHeight != nil ? minHeight!.dp : Dp.Unspecified, max: maxHeight != nil ? maxHeight!.dp : Dp.Unspecified)
}
ComposeContainer(modifier: context.modifier, fillWidth: maxWidth == Double.infinity, fixedWidth: maxWidth != nil && maxWidth != Double.infinity, fillHeight: maxHeight == Double.infinity, fixedHeight: maxHeight != nil && maxHeight != Double.infinity, then: thenModifier) { modifier in
ComposeContainer(modifier: context.modifier, fillWidth: maxWidth == Double.infinity, fixedWidth: maxWidth != nil && maxWidth != Double.infinity, minWidth: minWidth != nil && minWidth != Double.infinity && minWidth! > 0.0, fillHeight: maxHeight == Double.infinity, fixedHeight: maxHeight != nil && maxHeight != Double.infinity, minHeight: minHeight != nil && minHeight != Double.infinity && minHeight! > 0.0, then: thenModifier) { modifier in
let contentContext = context.content()
Box(modifier: modifier, contentAlignment: alignment.asComposeAlignment()) {
view.Compose(context: contentContext)
Expand All @@ -80,35 +80,35 @@ import androidx.compose.ui.unit.dp
}

@Composable func TargetViewLayout(context: ComposeContext, isOverlay: Bool, alignment: Alignment, target: @Composable (ComposeContext) -> Void, dependent: @Composable (ComposeContext) -> Void) {
Layout(modifier: context.modifier, content: {
// ComposeContainer is needed to properly handle content that fills width/height
ComposeContainer { modifier in
target(context.content(modifier: modifier))
}
// Dependent view lays out with fixed bounds dictated by the target view size
ComposeContainer(fixedWidth: true, fixedHeight: true) { modifier in
dependent(context.content(modifier: modifier))
}
}) { measurables, constraints in
guard !measurables.isEmpty() else {
return layout(width: 0, height: 0) {}
}
// Base layout entirely on the target view size
let targetPlaceable = measurables[0].measure(constraints)
let dependentConstraints = Constraints(maxWidth: targetPlaceable.width, maxHeight: targetPlaceable.height)
let dependentPlaceables = measurables.drop(1).map { $0.measure(dependentConstraints) }
layout(width: targetPlaceable.width, height: targetPlaceable.height) {
if !isOverlay {
for dependentPlaceable in dependentPlaceables {
let (x, y) = placeView(width: dependentPlaceable.width, height: dependentPlaceable.height, inWidth: targetPlaceable.width, inHeight: targetPlaceable.height, alignment: alignment)
dependentPlaceable.placeRelative(x: x, y: y)
}
// ComposeContainer is needed to properly handle content that fills width/height
ComposeContainer(modifier: context.modifier) { modifier in
Layout(modifier: modifier, content: {
target(context.content())
// Dependent view lays out with fixed bounds dictated by the target view size
ComposeContainer(fixedWidth: true, fixedHeight: true) { modifier in
dependent(context.content(modifier: modifier))
}
}) { measurables, constraints in
guard !measurables.isEmpty() else {
return layout(width: 0, height: 0) {}
}
targetPlaceable.placeRelative(x: 0, y: 0)
if isOverlay {
for dependentPlaceable in dependentPlaceables {
let (x, y) = placeView(width: dependentPlaceable.width, height: dependentPlaceable.height, inWidth: targetPlaceable.width, inHeight: targetPlaceable.height, alignment: alignment)
dependentPlaceable.placeRelative(x: x, y: y)
// Base layout entirely on the target view size
let targetPlaceable = measurables[0].measure(constraints)
let dependentConstraints = Constraints(maxWidth: targetPlaceable.width, maxHeight: targetPlaceable.height)
let dependentPlaceables = measurables.drop(1).map { $0.measure(dependentConstraints) }
layout(width: targetPlaceable.width, height: targetPlaceable.height) {
if !isOverlay {
for dependentPlaceable in dependentPlaceables {
let (x, y) = placeView(width: dependentPlaceable.width, height: dependentPlaceable.height, inWidth: targetPlaceable.width, inHeight: targetPlaceable.height, alignment: alignment)
dependentPlaceable.placeRelative(x: x, y: y)
}
}
targetPlaceable.placeRelative(x: 0, y: 0)
if isOverlay {
for dependentPlaceable in dependentPlaceables {
let (x, y) = placeView(width: dependentPlaceable.width, height: dependentPlaceable.height, inWidth: targetPlaceable.width, inHeight: targetPlaceable.height, alignment: alignment)
dependentPlaceable.placeRelative(x: x, y: y)
}
}
}
}
Expand Down

0 comments on commit 81f10ed

Please sign in to comment.