#button #view #swiftui #action
#кнопка #Вид #swiftui #Экшен
Вопрос:
Я пытаюсь решить следующую проблему.
У меня есть представление сетки, которое генерирует массив представлений. Смотрите ниже:
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
В настоящее время у меня есть этот рабочий код, который отправляет значение массива в целочисленную переменную ‘upTo’ в моем основном коде:
GridStack(rows: 3, columns: 4){ rows, cols in
Button(action: {
upTo = rows * 4 cols 1
}, label: {
Text("Number (rows * 4 cols 1)")
})
}
Я хотел бы сделать этот текст анимированным, однако, если я добавлю анимацию непосредственно к тексту, каждый из текстов перемещается при нажатии там, где я хотел бы анимировать только тот, который я нажимаю.
Я попытался превратить текст в вид кнопки и передать его в метку главной кнопки, но, по-видимому, встраивание кнопок является преступлением, наказуемым смертной казнью.
У кого-нибудь есть идеи? Заранее спасибо!
Комментарии:
1. Вы пытаетесь поместить кнопку в кнопку — в SwiftUI, который реагирует, работает только один, который реагирует первым. Зачем это нужно делать?
2. Вы вкладываете кнопки? Это не очень хорошая идея, поскольку система не будет знать, какую кнопку активировать. Кроме того, вы создаете два экземпляра своего
test
представления вCententview
.3. Нет ли способа сообщить системе активировать обе кнопки?
4. Для меня это скорее похоже на проблему XY . Как сказал другой, и вы испытали, вложенные кнопки — не очень хорошая идея. Не было бы более подходящим поместить анимацию в модификатор
onTapGesture
представления?5. Вот хороший обновленный вопрос для всех вас, надеюсь, он внесет больше ясности
Ответ №1:
Я думаю, что возможны два решения. Пожалуйста, посмотрите мои рабочие примеры ниже.
Вы бы хотели, чтобы примененный эффект сохранялся после нажатия кнопки? В этом случае я бы рекомендовал создать пользовательское представление, в котором хранится состояние.
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomView: View {
let upTo: Int
let callback: () -> Void
@State var animate = false
var body: some View {
Button(action: {
self.callback()
self.animate.toggle()
}) {
Text("Number (self.upTo)")
.background(self.animate ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
MyCustomView(upTo: rows * 4 cols 1, callback: {
self.upTo = rows * 4 cols 1
})
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}
В противном случае подойдет пользовательский стиль кнопки. В этом случае вы можете получить доступ isPressed
к свойству конфигурации.
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.background(configuration.isPressed ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
Button(action: {
self.upTo = rows * 4 cols 1
}) {
Text("Number (rows * 4 cols 1)")
}
.buttonStyle(MyCustomButtonStyle())
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}
Комментарии:
1. Потрясающе! Еще раз спасибо, Николай. Я использовал первый пример, поскольку второй мне немного непонятен. Честно говоря, я не совсем понимаю, какую роль играет переменная обратного вызова? Это переменная? И это то, что позволяет ContentView2 считывать значение, выбранное при нажатии кнопки?
2. Добро пожаловать! Кнопка помещается внутрь
MyCustomView
представления. Ваша цель — выполнить действие, нажав на кнопку. Но на самом деле, что целочисленное состояниеupTo
недоступно изнутриMyCustomView
, передается замыкание, которое «описывает», что делатьContentView2
. И, наконец, это закрытие вызывается закрытием действия кнопки. Подробнее о замыканиях читайте здесь .3. Хорошо, я буду практиковать свои замыкания! Это немного отчаянно, но не могли бы вы взглянуть на мой другой вопрос в моем профиле относительно поэлементного умножения некоторых массивов? Что-то в моем вычислении массивов превращает их в любой операнд, что означает, что я не могу умножать элементы массива.