我正在使用 List 来实现高度定制的界面。这主要是因为字段header
以及在.plain
模式下标题如何粘在内容上方。
问题是标题似乎有鲜艳效果。这是不理想的,因为在这种情况下,标题应该只是左侧的一个按钮。
有什么方法可以消除这种振动效果吗?或者我应该使用一些复杂的几何读取器逻辑来构建自己的粘性标头实现?
在我的应用中,我有各种按钮。它们有许多共同的特点,但颜色不同。我试图编写一个包含每个按钮样式的类,明确指出它们唯一的不同之处是颜色。
问题是我还想对其中一个使用 .tint。但那是一个ShapeStyle
而不是一个 Color。
struct CommonButtonStyle: ButtonStyle {
@Environment(\.isEnabled) var isEnabled: Bool
@Environment(\.isFocused) var isFocused: Bool
var labelColor: Color
var enabledColor: some ShapeStyle
var pressedColor: Color
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.system(size: 14, weight: .bold))
.padding(.horizontal, 16)
.padding(.vertical, 10)
.foregroundStyle(labelColor)
.frame(maxHeight: 40)
.background((isEnabled && configuration.isPressed) ? pressedColor : enabledColor)
.clipShape(Capsule())
.containerShape(Capsule())
.opacity(isEnabled ? 1 : 0.5)
.focusable()
}
}
这里的问题是不匹配的返回类型和声明,var enabledColor: some ShapeStyle
因为编译器抱怨Property declares an opaque return type, but has no initializer expression from which to infer an underlying type
有没有办法让我得到这个变量来存储一个Color
或一个,ShapeStyle
以便我可以做
CommonButtonStyle(labelColor: .black, enabledColor: .tint, pressedColor: .white)
和
CommonButtonStyle(labelColor: .black, enabledColor: .blue, pressedColor: .white)
我试图实现一个相当简单的动画,其中列表中的选定项会应用背景。目标是选定项后面的灰色框能够平滑地从上一个位置变形到下一个位置。
我使用 来实现这一点,matchedGeometryEffect
以便 SwiftUI 可以匹配两个状态之间的背景视图,即使从技术上讲它们具有不同的 ID 路径。然而,这一努力被以下因素所阻碍:List
这是示例项目。要中断动画,您只需将按钮放在列表中即可。
为什么 List 会破坏此动画?有什么方法可以解决这个问题吗?
struct AnimationButtonStyle: ButtonStyle {
var isCurrent: Bool
var animationNamespace: Namespace.ID
var backgroundView: some View {
Color.gray
.cornerRadius(8)
.matchedGeometryEffect(id: "Shape", in: animationNamespace)
}
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(
isCurrent ? backgroundView : nil
)
.opacity(configuration.isPressed ? 0.5 : 1.0)
}
}
struct ContentView: View {
enum cases: String, CaseIterable {
case foo = "Foo"
case bar = "Barrrrrr"
case bat = "Battttttttttttttt"
}
@Namespace private var animationNamespace
@State var animatedCurrentCase: cases = .foo
@State var currentCase: cases = .foo
@State var isAnimating: Bool = false
var body: some View {
VStack {
// Without the list this animation will work
List {
Section {
VStack(alignment: .leading, spacing: 0) {
ForEach(Array(cases.allCases.enumerated()), id: \.offset) { index, theCase in
var isCurrent: Bool { theCase == animatedCurrentCase }
Button {
isAnimating = true
Task { @MainActor in
animatedCurrentCase = theCase
try? await Task.sleep(nanoseconds: 200_000_000)
currentCase = theCase
isAnimating = false
}
} label: {
Label {
Text(theCase.rawValue)
} icon: {
VStack(alignment: .leading) {
Text("\(index)")
}
.frame(width: isCurrent ? 16 + 4 : 16)
}
}
.disabled(isAnimating)
.buttonStyle(AnimationButtonStyle(isCurrent: isCurrent, animationNamespace: animationNamespace))
.animation(.smooth, value: animatedCurrentCase)
}
}
}
}
Spacer().frame(height: 10)
Text("Selected: \(currentCase.rawValue)")
.font(.title)
}
.padding()
}
}
我正在尝试编写一行,该行的计算结果为 bool,表示可选的 Date 对象是否在未来。
我写了以下声明
let dateIsInFuture = (optionalDate ?? .now) >= .now
我很好奇这是否是一种不好的形式。特别是因为如果第一个和第二个 .now 在不同时间评估,它们可能不再相等。当然,我现在可以拉出到另一行来消除这种歧义......但我很好奇这是否适用于 swift 编译和运行这行代码的方式。
我看到很多关于 AsyncImage 以及如何刷新它的问题。在这种情况下有点不同。图像 URL 保持不变,但图像会定期更改。因此,我希望有一个按钮来刷新它。
问题是oldUrl == newURL。我什至尝试了一些技巧,在父级上设置边框颜色来尝试欺骗 SwiftUI 刷新它,但这些都不起作用。现在我手动显示和隐藏视图来完成这项工作。这当然是不可取的。
可能还有其他办法吗?