【问题标题】:SwiftUI: Setting individual colors for .toolbar ToolbarItem?SwiftUI:为 .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()
    }
}

【问题讨论】:

    标签: swiftui


    【解决方案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)
            }
        }
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-27
          相关资源
          最近更新 更多