SwiftUI:为 .toolbar ToolbarItem 设置单独的颜色?
Posted
技术标签:
【中文标题】SwiftUI:为 .toolbar ToolbarItem 设置单独的颜色?【英文标题】:SwiftUI: Setting individual colors for .toolbar ToolbarItem? 【发布时间】:2020-09-20 13:06:26 【问题描述】:一般来说,出于可访问性的原因,我喜欢坚持使用默认颜色选项,但我有一个特定的用例,我无法更改单个 .toolbar ToolbarItem 颜色。
我可以使用我的 sn-p 顶部的注释掉代码来覆盖 所有 ToolbarItem 颜色,但我想为单个图标着色。
import SwiftUI
struct ContentView: View
// init()
// UIBarButtonItem.appearance(whenContainedInInstancesOf: [UIToolbar.self]).tintColor = .systemRed
//
var body: some View
NavigationView
Text("Hello, world!")
.toolbar
// To be colored RED
ToolbarItem(placement: .bottomBar)
Button(action: , label: Label("Icon One", systemImage: "stop.fill"))
// To be colored BLACK
ToolbarItem(placement: .bottomBar)
Button(action: , label: Label("Icon Two", systemImage: "play.fill"))
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
【参考方案1】:是的,我一直在为同样的事情苦苦挣扎。看起来Buttons
正在使用系统色调颜色及其整体风格。
这是我的看法:
content
.toolbar
ToolbarItem(placement: .navigationBarLeading)
HStack
StyledButton(image: .system("arrow.left")) ...
Spacer(minLength: 0) // important to not fell button to default styling
我们的想法是不只显示 Button,而是与其他 UI 元素一起显示。对我来说看起来像一个 SwiftUI 错误。 (或者只是想比你聪明。)
【讨论】:
很奇怪,但就像一个魅力!!,请注意,这个问题只发生在 iphone 11 设备上,onTapGesture 不起作用。我们需要使用一个按钮。【参考方案2】:我找到的最简单的解决方案是放弃 Button
并改用 .onTapGesture
。
struct ContentView: View
var body: some View
NavigationView
Text("Hello World!")
.toolbar
// To be colored RED
ToolbarItem(placement: .bottomBar)
Label("Icon One", systemImage: "stop.fill")
.foregroundColor(.red)
.onTapGesture
// Respond to tap
// To be colored BLACK
ToolbarItem(placement: .bottomBar)
Label("Icon One", systemImage: "play.fill")
.foregroundColor(.black)
.onTapGesture
// Respond to tap
输出:
【讨论】:
ToolbarItem 似乎忽略了 .onTapGesture。换句话说,我认为您的解决方案行不通。颜色正确更改,但您的新“按钮”不会调用任何操作。此外,标签在点击期间不会像普通按钮那样变暗。【参考方案3】:看起来所有标准类型(按钮、图像、文本等)都被 ToolbarItem 拦截并转换为适当的内部表示。但自定义视图(例如基于形状)......不是。因此,请参阅下面的可能方法演示。
使用 Xcode 12 / ios 14 准备和测试演示。
ToolbarItem(placement: .bottomBar)
ShapeButton(shape: Rectangle(), color: .red)
print(">> works")
以及简单的基于形状的自定义按钮
struct ShapeButton<S:Shape>: View
var shape: S
var color: Color
var action: () -> ()
@GestureState private var tapped = false
var body: some View
shape
.fill(color).opacity(tapped ? 0.4 : 1)
.animation(.linear(duration: 0.15), value: tapped)
.frame(width: 18, height: 18)
.gesture(DragGesture(minimumDistance: 0)
.updating($tapped) value, state, _ in
state = true
.onEnded _ in
action()
)
【讨论】:
【参考方案4】:如果你使用 UIKit,它对我有用。
struct ButtonRepresentation: UIViewRepresentable
let sfSymbolName: String
let titleColor: UIColor
let action: () -> ()
func makeUIView(context: Context) -> UIButton
let b = UIButton()
let largeConfig = UIImage.SymbolConfiguration(scale: .large)
let image = UIImage(systemName: sfSymbolName, withConfiguration: largeConfig)
b.setImage(image, for: .normal)
b.tintColor = titleColor
b.addTarget(context.coordinator, action: #selector(context.coordinator.didTapButton(_:)), for: .touchUpInside)
return b
func updateUIView(_ uiView: UIButton, context: Context)
func makeCoordinator() -> Coordinator
return Coordinator(action: action)
typealias UIViewType = UIButton
class Coordinator
let action: () -> ()
@objc
func didTapButton(_ sender: UIButton)
self.action()
init(action: @escaping () -> ())
self.action = action
然后您可以添加不同颜色的单独 ButtonRepresentations。
.toolbar
ToolbarItem(placement: .cancellationAction)
ButtonRepresentation(sfSymbolName: closeIcon, titleColor: closeIconColor)
presentationMode.wrappedValue.dismiss()
【讨论】:
【参考方案5】:遗憾的是,这个技巧只适用于 iOS。
但从好的方面来说,它也适用于菜单:
Menu
Button("A title")
label :
HStack
Label("Star"), systemImage: "star")
.labelStyle(.iconOnly)
.foregroundColor(.red)
Spacer(minLength: 0)
【讨论】:
以上是关于SwiftUI:为 .toolbar ToolbarItem 设置单独的颜色?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI .toolbar ToolbarItem 自定义按钮设计
iOS 16 中 SwiftUI 4.0 Toolbar 自定义背景色以及 List 自动编辑操作的原生支持
iOS 16 中 SwiftUI 4.0 Toolbar 自定义背景色以及 List 自动编辑操作的原生支持
iOS 16 中 SwiftUI 4.0 Toolbar 自定义背景色以及 List 自动编辑操作的原生支持
SwipeActions 按钮和 ToolBar 按钮触发的多个工作表(项目:)在 SwiftUI 中首次获取 nil 对象