Skip to content

Commit

Permalink
- Fix keyboard inset bug in sheets for non-edge-to-edge apps
Browse files Browse the repository at this point in the history
- Give text fields a lighter border
- Make search fields capsule shaped
- Make confiration placement ToolbarItems bold by default
- Fix potential crashers with negative-sized Shapes
- Support NavigationLink(destination: View, ...)
  • Loading branch information
aabewhite committed Jul 11, 2024
1 parent 1d224da commit bf0b33c
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 19 deletions.
6 changes: 6 additions & 0 deletions Sources/SkipUI/SkipUI/Color/Color.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ public struct Color: ShapeStyle, Hashable, Sendable {
MaterialTheme.colorScheme.surface.copy(alpha: Float(0.9))
})

/// Use for separators, etc.
static var separator: Color = Color(colorImpl: {
MaterialTheme.colorScheme.surfaceVariant
})

/// Use for placeholder content.
static let placeholder = Color(colorImpl: {
// Close to iOS's AsyncImage placeholder values
ComposeColor(light: 0xFFDDDDDD, dark: 0xFF777777)
Expand Down
5 changes: 3 additions & 2 deletions Sources/SkipUI/SkipUI/Commands/Search.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
Expand Down Expand Up @@ -100,7 +101,7 @@ let searchFieldHeight = 56.0
/// Renders a search field.
// SKIP INSERT: @OptIn(ExperimentalMaterial3Api::class)
@Composable func SearchField(state: SearchableState, context: ComposeContext) {
let colors = TextField.colors(context: context)
let colors = TextField.colors(outline: Color.primary.opacity(0.5), context: context)
let disabledTextColor = TextField.textColor(enabled: false, context: context)
let prompt = state.prompt ?? Text(verbatim: stringResource(android.R.string.search_go))
let focusManager = LocalFocusManager.current
Expand Down Expand Up @@ -135,7 +136,7 @@ let searchFieldHeight = 56.0
focusRequester.requestFocus()
})
}
}, keyboardOptions: keyboardOptions, keyboardActions: keyboardActions, singleLine: true, colors: colors)
}, keyboardOptions: keyboardOptions, keyboardActions: keyboardActions, singleLine: true, colors: colors, shape: Capsule().asComposeShape(density: LocalDensity.current))
AnimatedVisibility(visible: state.isSearching.value == true) {
ComposeTextButton(label: Text(verbatim: stringResource(android.R.string.cancel)), context: contentContext) {
state.text.wrappedValue = ""
Expand Down
8 changes: 7 additions & 1 deletion Sources/SkipUI/SkipUI/Commands/Toolbar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ public struct ToolbarItem : CustomizableToolbarContent {

#if SKIP
@Composable public override func ComposeContent(context: ComposeContext) {
content.Compose(context: context)
EnvironmentValues.shared.setValues {
if placement == .confirmationAction {
$0.set_fontWeight(Font.Weight.bold)
}
} in: {
content.Compose(context: context)
}
}
#else
public var body: some View {
Expand Down
5 changes: 2 additions & 3 deletions Sources/SkipUI/SkipUI/Containers/List.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.GenericShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.SwipeToDismissBoxDefaults
Expand Down Expand Up @@ -310,7 +309,7 @@ public final class List : View {
}

@Composable static func ComposeSeparator() {
Box(modifier: Modifier.padding(start: Self.horizontalItemInset.dp).fillMaxWidth().height(1.dp).background(MaterialTheme.colorScheme.surfaceVariant))
Box(modifier: Modifier.padding(start: Self.horizontalItemInset.dp).fillMaxWidth().height(1.dp).background(Color.separator.colorImpl()))
}

@Composable private func ComposeItem(view: View, context: ComposeContext, modifier: Modifier = Modifier, styling: ListStyling, isItem: Bool = true) {
Expand Down Expand Up @@ -537,7 +536,7 @@ public final class List : View {
@Composable private func ComposeSearchField(state: SearchableState, context: ComposeContext, styling: ListStyling) {
var modifier = Modifier.background(BackgroundColor(styling: styling, isItem: false))
if styling.style == ListStyle.plain {
modifier = modifier.padding(start: Self.horizontalInset.dp, end: Self.horizontalInset.dp)
modifier = modifier.padding(top: Self.verticalInset.dp, start: Self.horizontalInset.dp, end: Self.horizontalInset.dp, bottom: Self.verticalInset.dp)
} else {
modifier = modifier.padding(top: Self.verticalInset.dp)
}
Expand Down
4 changes: 4 additions & 0 deletions Sources/SkipUI/SkipUI/Containers/Navigation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,10 @@ public struct NavigationLink : View, ListItemAdapting {
self.label = ComposeBuilder.from(label)
}

public init(destination: any View, @ViewBuilder label: () -> any View) {
self.init(destination: { destination }, label: label)
}

public init(_ titleKey: LocalizedStringKey, @ViewBuilder destination: () -> any View) {
self.init(destination: destination, label: { Text(titleKey) })
}
Expand Down
3 changes: 1 addition & 2 deletions Sources/SkipUI/SkipUI/Containers/Table.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.requiredWidthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -154,7 +153,7 @@ public final class Table<ObjectType, ID> : View where ObjectType: Identifiable<I
let itemID = rememberUpdatedState(data[index].id)
let isSelected = isSelected(id: itemID.value)
if isSelected {
let selectionColor = isCompact ? MaterialTheme.colorScheme.surfaceVariant : (EnvironmentValues.shared._tint?.colorImpl() ?? Color.accentColor.colorImpl())
let selectionColor = isCompact ? Color.separator.colorImpl() : (EnvironmentValues.shared._tint?.colorImpl() ?? Color.accentColor.colorImpl())
modifier = modifier.background(selectionColor)
}
if selection != nil {
Expand Down
5 changes: 3 additions & 2 deletions Sources/SkipUI/SkipUI/Graphics/Shape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ extension Shape {

public func asComposePath(size: Size, density: Density) -> androidx.compose.ui.graphics.Path {
let px = with(density) { 1.dp.toPx() }
let path = path(in: CGRect(x: 0.0, y: 0.0, width: Double(size.width / px), height: Double(size.height / px)))
let path = path(in: CGRect(x: 0.0, y: 0.0, width: max(0.0, Double(size.width / px)), height: max(0.0, Double(size.height / px))))
return path.asComposePath(density: density)
}

Expand Down Expand Up @@ -189,7 +189,8 @@ public struct ModifiedShape : Shape {
if strokeInset == Float(0.0) {
scope.drawPath(path, brush: strokeBrush.0, style: strokeBrush.1)
} else {
scope.inset(strokeInset) {
// Insetting to a negative size causes a crash
scope.inset(min(scope.size.width / 2, min(scope.size.height / 2, strokeInset))) {
let strokePath = asComposePath(size: scope.size, density: density)
scope.drawPath(strokePath, brush: strokeBrush.0, style: strokeBrush.1)
}
Expand Down
7 changes: 4 additions & 3 deletions Sources/SkipUI/SkipUI/Layout/Presentation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeightIn
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CornerBasedShape
import androidx.compose.foundation.shape.CornerSize
Expand Down Expand Up @@ -149,10 +151,9 @@ let overlayPresentationCornerRadius = 16.0
}
}
}

if !isEdgeToEdge {
// Move the presentation root content area above the bottom bar
let inset = WindowInsets.safeDrawing.asPaddingValues().calculateBottomPadding()
let inset = max(0.dp, WindowInsets.systemBars.asPaddingValues().calculateBottomPadding() - WindowInsets.ime.asPaddingValues().calculateBottomPadding())
androidx.compose.foundation.layout.Spacer(modifier: Modifier.height(inset))
}
}
Expand Down Expand Up @@ -205,7 +206,7 @@ let overlayPresentationCornerRadius = 16.0
let stateSaver = remember { ComposeStateSaver() }
let scrollState = rememberScrollState()
let isEdgeToEdge = EnvironmentValues.shared._isEdgeToEdge == true
let bottomSystemBarPadding = WindowInsets.safeDrawing.asPaddingValues().calculateBottomPadding()
let bottomSystemBarPadding = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
let modifier = Modifier
.fillMaxWidth()
.padding(start: 8.dp, end: 8.dp, bottom: isEdgeToEdge ? 0.dp : bottomSystemBarPadding)
Expand Down
13 changes: 7 additions & 6 deletions Sources/SkipUI/SkipUI/Text/TextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ContentAlpha
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.TextFieldColors
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalFocusManager
Expand Down Expand Up @@ -91,24 +91,25 @@ public struct TextField : View {
}

// SKIP INSERT: @OptIn(ExperimentalMaterial3Api::class)
@Composable static func colors(context: ComposeContext) -> TextFieldColors {
@Composable static func colors(outline: Color? = nil, context: ComposeContext) -> TextFieldColors {
let textColor = textColor(enabled: true, context: context)
let disabledTextColor = textColor(enabled: false, context: context)
let isPlainStyle = EnvironmentValues.shared._textFieldStyle == TextFieldStyle.plain
if isPlainStyle {
let clearColor = androidx.compose.ui.graphics.Color.Transparent
if let tint = EnvironmentValues.shared._tint {
let tintColor = tint.colorImpl()
return TextFieldDefaults.outlinedTextFieldColors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, cursorColor: tintColor, focusedBorderColor: clearColor, unfocusedBorderColor: clearColor, disabledBorderColor: clearColor, errorBorderColor: clearColor)
return OutlinedTextFieldDefaults.colors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, cursorColor: tintColor, focusedBorderColor: clearColor, unfocusedBorderColor: clearColor, disabledBorderColor: clearColor, errorBorderColor: clearColor)
} else {
return TextFieldDefaults.outlinedTextFieldColors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, focusedBorderColor: clearColor, unfocusedBorderColor: clearColor, disabledBorderColor: clearColor, errorBorderColor: clearColor)
return OutlinedTextFieldDefaults.colors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, focusedBorderColor: clearColor, unfocusedBorderColor: clearColor, disabledBorderColor: clearColor, errorBorderColor: clearColor)
}
} else {
let borderColor = (outline ?? Color.primary.opacity(0.3)).colorImpl()
if let tint = EnvironmentValues.shared._tint {
let tintColor = tint.colorImpl()
return TextFieldDefaults.outlinedTextFieldColors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, cursorColor: tintColor, focusedBorderColor: tintColor)
return OutlinedTextFieldDefaults.colors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, cursorColor: tintColor, focusedBorderColor: tintColor, unfocusedBorderColor: borderColor, disabledBorderColor: Color.separator.colorImpl())
} else {
return TextFieldDefaults.outlinedTextFieldColors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor)
return OutlinedTextFieldDefaults.colors(focusedTextColor: textColor, unfocusedTextColor: textColor, disabledTextColor: disabledTextColor, unfocusedBorderColor: borderColor, disabledBorderColor: Color.separator.colorImpl())
}
}
}
Expand Down

0 comments on commit bf0b33c

Please sign in to comment.