SwiftUI:为工具栏项设置单独的颜色?
通常,出于可访问性的原因,我喜欢使用默认颜色选项,但我有一个特定的用例,无法更改单个.toolbar工具栏项的颜色 我可以使用代码段顶部的注释代码覆盖所有工具栏项的颜色,但我想给单个图标上色SwiftUI:为工具栏项设置单独的颜色?,swiftui,Swiftui,通常,出于可访问性的原因,我喜欢使用默认颜色选项,但我有一个特定的用例,无法更改单个.toolbar工具栏项的颜色 我可以使用代码段顶部的注释代码覆盖所有工具栏项的颜色,但我想给单个图标上色 import SwiftUI struct ContentView: View { // init() { // UIBarButtonItem.appearance(whenContainedInInstancesOf: [UIToolbar.self]).tintColo
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()
}
}
看起来所有标准类型(按钮、图像、文本等)都是按工具栏项截取的,并转换为适当的内部表示形式。但是自定义视图(例如基于形状的)。。。事实并非如此。下面是一个可能的方法演示 使用Xcode 12/iOS 14准备并测试演示 和简单的自定义形状按钮
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()
})
}
}
struct ShapeButton:视图{
变量形状:S
颜色:颜色
变量作用:()->()
@GestureState private var=false
var body:一些观点{
形状
.填充(颜色).不透明度(抽头?0.4:1)
.animation(.linear(持续时间:0.15),值:点击)
.框架(宽度:18,高度:18)
.手势(牵引力(最小距离:0)
.正在更新($tapped){value,state,uuu中
状态=真
}
.onEnded{uuin
行动()
})
}
}
如果你进入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
}
}
}
然后,您可以添加不同颜色的单独按钮演示文稿
.toolbar {
ToolbarItem(placement: .cancellationAction) {
ButtonRepresentation(sfSymbolName: closeIcon, titleColor: closeIconColor) {
presentationMode.wrappedValue.dismiss()
}
}
我找到的最简单的解决方案是放弃
按钮
,改用.ontapsignate
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
}
}
}
}
}
}
输出:
是的,我一直在为同样的事情挣扎。看起来,
按钮
使用的是系统着色颜色及其整体样式
以下是我的看法:
content
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
HStack {
StyledButton(image: .system("arrow.left")) { ... }
Spacer(minLength: 0) // important to not fell button to default styling
}
}
}
这样做的目的不是只显示按钮,而是与其他UI元素一起显示。在我看来,这是一个迅捷的错误。(或者只是想让你聪明一点。)ToolbarItem似乎忽略了.ontaps手势。换句话说,我认为你的解决方案行不通。颜色会正确更改,但新的“按钮”不会调用任何操作。此外,标签不会像普通按钮那样在点击过程中变暗。
content
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
HStack {
StyledButton(image: .system("arrow.left")) { ... }
Spacer(minLength: 0) // important to not fell button to default styling
}
}
}