#swiftui
#swiftui
Вопрос:
Обычно я предпочитаю использовать параметры цвета по умолчанию по соображениям доступности, но у меня конкретный вариант использования, и я не могу изменить отдельный цвет .toolbar ToolbarItem .
Я могу переопределить все цвета 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
}
}
}
Идея состоит в том, чтобы отображать не только кнопки, но и другие элементы пользовательского интерфейса. Для меня это похоже на ошибку SwiftUI. (Или просто пытаюсь перехитрить вас.)
Комментарии:
1. Странно, но работает как шарм !!, Как примечание, проблема возникла только на устройствах 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
}
}
}
}
}
}
Вывод:
Комментарии:
1. 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
}
}
}
Затем вы можете добавить отдельные представления кнопок с разными цветами.
.toolbar {
ToolbarItem(placement: .cancellationAction) {
ButtonRepresentation(sfSymbolName: closeIcon, titleColor: closeIconColor) {
presentationMode.wrappedValue.dismiss()
}
}
Ответ №5:
К сожалению, этот трюк работает только на iOS.
Но с другой стороны, это также работает и для Menu:
Menu {
Button("A title") {}
} label : {
HStack {
Label("Star"), systemImage: "star")
.labelStyle(.iconOnly)
.foregroundColor(.red)
Spacer(minLength: 0)
}
}