【问题标题】:Button handling in SwiftUISwiftUI 中的按钮处理
【发布时间】:2021-10-22 13:40:57
【问题描述】:

SwiftUI 应用程序中,我有几个按钮(我们以 3 为例)。其中之一被突出显示。

当我点击未突出显示的按钮时,之前突出显示的按钮会切换为未突出显示,并且点击的按钮会突出显示。如果我点击已经突出显示的按钮,什么都不会发生。

这个场景很简单,我有一个 highlighBtn 变量,当点击按钮时,highlighBtn 会获取点击按钮的值。然后,当下一次点击碰巧关闭先前突出显示的按钮时,将使用此变量。

这个循环没问题,但问题是我第一次点击的时候。由于某些原因,事情无法正常工作。

这就是我处理 highlighBtn 变量创建的方式:

class ActiveButton: ObservableObject {
    @Published var highlighBtn = Button(....)
}

@StateObject var box = ActiveButton()

这里是相关代码,当点击按钮时:

@EnvironmentObject var box: ActiveButton
....
Button(action: {
    // Toggle off the previously highlighted button.
    box.highlighBtn.highLight = false
    .... some useful processing ....
    box.highlighBtn = self
})

我应该给出一个细节:如果我点击突出显示的按钮开始,那么一切都会正常进行。

我尝试了各种方法来解决这个看似简单的问题,但都失败了。

第一种方法是尝试初始化 highlighBtn 变量。 第二个是尝试模拟点击突出显示的按钮。

我一定错过了一些简单的东西。 欢迎任何提示。

经过进一步调查.....

我创建了一个演示应用程序来揭示我的问题。 由于我缺乏使用GitHub 的练习,所以我花了一些时间,但现在here 可用。

为此,我在Xcode 中创建了一个SwiftUI 应用程序。

SceneDelegate.swift 中,紧随其后的四行代码已针对此应用的需求进行了定制:

// Create the SwiftUI view that provides the window contents.

除此之外,我所做的一切都驻留在文件 ContentView.swift 中。

为了节省一些时间给任何想要看看的人;这是直截了当的方法(即我面临的问题)。

  1. 运行应用程序(我是在 iPhone 7 上运行的)。您将看到出现七个按钮。其中之一(随机)将突出显示。从突出显示的按钮开始,依次点击几个按钮,次数不限。您将看到应用程序应该如何工作。

  2. (关闭后)再次运行应用程序。这一次,您还将根据需要依次点击几个按钮;但首先点击其中一个未突出显示的按钮。此时您会看到问题出现了。

【问题讨论】:

  • 你能提供minimal reproducible example吗?我不确定您设置为falsehighLight 变量是什么,并且将SwiftUI 视图存储在ObservableObject 中对我来说似乎不正确..
  • 您的问题似乎很容易回答,而且问题不难,但是您的提问方式和问题示例不清楚,您可以改用最小的工作问题。
  • @Philip_Dukhov,swiftPunk。我已经完成了帖子并在 GitHub 上提供了一个演示应用程序,希望您可以看看并告诉我您的想法。

标签: ios swift button swiftui


【解决方案1】:

这是您问题第一部分的解决方案:最后一个被点击的三个按钮以背景突出显示:

import SwiftUI

struct ContentView: View {

    enum HighlightTag {
        case none, first, second, third
    }

    @State private var highlighted = HighlightTag.none

    var body: some View {
        VStack {
            Button("First") {
                highlighted = .first
            }.background(
                Color.accentColor.opacity(
                    highlighted == .first ? 0.2 : 0.0
                )
            )
            Button("Second") {
                highlighted = .second
            }.background(
                Color.accentColor.opacity(
                    highlighted == .second ? 0.2 : 0.0
                )
            )
            Button("Third") {
                highlighted = .third
            }.background(
                Color.accentColor.opacity(
                    highlighted == .third ? 0.2 : 0.0
                )
            )
        }
    }
}

更新: 在查看了您在 GitHub 上的示例代码后,我尝试理解您的代码,并尝试进行一些简化并尝试找到可行的解决方案。

以下是一些意见:

  • “var butnsPool”前面的属性“@State”不需要且令人困惑。
  • “var initialHilight”前面的属性“@State”不需要且令人困惑。
  • 您的 ActiveButton 存储所选按钮视图的副本,因为它是一个结构,这可能是导致奇怪行为的主要原因。
  • ObservableObject 中的 needInit 至少闻起来很糟糕。如果你真的需要初始化一些东西,你可以考虑在 ContentView 中使用一些 .onAppear() 修饰符。
  • 可能不需要使用.environmentObject 和@EnvironmentObject。您可以考虑使用参数和@ObsservedObject
  • 如果只在内部使用 ActiveButton,可能根本不需要它。您可以考虑使用带有所选 utton 名称的 @State
  • 您的 BtnTxtView 没问题,但如果您想为过渡设置动画,请考虑将条件 (func if) 替换为一些动画属性。

根据您的代码,我创建了一个更简单且有效的解决方案。

我删除了 ActiveButton 类和 BttnView 结构。 我用这个替换了 ContentView:

struct ContentView: View {
    var butnsPool: [String]
    var initialHilight: Int
    @State var selectedBox: String = ""

    var body: some View {
        ForEach(butnsPool, id: \.self) { buttonName in
            Button(action: {
                selectedBox = buttonName
            })
            {
                BtnTxtView(theLabel: buttonName,
                           highLight: buttonName == selectedBox)
            }
        }.onAppear {
            selectedBox = butnsPool[initialHilight]
        }
    }
}

【讨论】:

  • 没错,但我想要一个更通用的解决方案。这个有固定数量的按钮。如果你有时间,你可以看看我刚刚提供的一个演示。查看更新后的帖子。
  • 嘿@Michel,我上面的解决方案适用于您在问题的第一句话中描述的问题。它故意不是通用解决方案。如果您有一组可识别的按钮项,应该很容易找到一个干净的通用解决方案,但这不是您最初要求的。到目前为止,您能在我的解决方案中看到一些价值吗?
  • 嗨@Roland_Schmitz,我不完全确定您在写“问题的第一句话”时在想什么。我能说出我需要什么的最简单方法是:让我的演示工作的解决方案或/和解释为什么它不工作。
  • 我的意思是您问题的前 4 个句子,其中您描述了您想要实现的目标。从我的角度来看,我为您的场景提供了一个可行的解决方案。故意不通用以使其尽可能简单。所以我想知道为什么你在这个解决方案中没有看到任何价值。当时我不能做更多,因为您最初的示例代码没有包含所有相关部分。
  • 嘿@Michel,我查看了您的代码并发现了一些需要考虑的问题以及一个可行的解决方案。看看我更新的答案。我希望这比我原来的答案为你提供更多的价值。试试看!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-11
  • 2022-08-17
  • 2020-08-21
  • 2011-11-02
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多