ios SwiftUI -带有按钮的复杂滚动视图,并应用带有条件的渐变

z3yyvxxp  于 2023-06-25  发布在  iOS
关注(0)|答案(1)|浏览(100)

我有一个复杂的项目,但我创建了一个示例应用程序来获得帮助,因此用于渐变的代码和颜色可能看起来不专业。无论如何,我有一个滚动视图,其中有按钮列表。我只希望一次显示3个按钮,所以我已经降低了VStack的高度,用户可以滚动时,他们希望查看其他选项。

  • 以下是条件:*
  • 任何中心按钮都不应该有渐变,只有顶部可见和底部可见的按钮应该有渐变,所以用户知道还有更多的滚动。
  • 如果任何时候,顶部或底部按钮被选择,则该按钮不应具有梯度,即对于3个按钮(顶部、中心和底部),如果选择顶部,则顶部不应具有渐变,中心不应具有渐变,按照条件1,并且在这种情况下只有底部将具有渐变。

所选按钮是带有蓝色边框的按钮。总是会有一个可见的按钮被选中,它可以是顶部,中心或底部按钮。
在我的代码中,除了选中的按钮外,所有按钮都有渐变。使用SwiftUI,我并没有找到一种简单的方法来知道哪个按钮目前在显示器上,以及它们在显示器上的位置。我想要达到的是ScrollView吗?

验证码:

import SwiftUI
import Foundation

@main
struct SampleAppApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView().frame(maxHeight: 140.0)
        }
    }
}

struct SimpleTestData {
    let id = UUID()
    let score: Int
}

struct ContentView: View {
    @State private var currentlySelectedData: Int?
    
    let results = [
        SimpleTestData(score: 8),
        SimpleTestData(score: 5),
        SimpleTestData(score: 10),
        SimpleTestData(score: 15),
        SimpleTestData(score: 1)
    ]
    
    
    var body: some View {
        ScrollViewReader { proxy in
            ScrollView(showsIndicators: false) {
                VStack {
                    ForEach(results, id: \.id) { result in
                        makeDataButton(data: result.score).frame(height: 40.0).padding([.bottom, .top], 2.0)
                    }
                }
            }
        }
    }

    @ViewBuilder func makeDataButton(data: Int) -> some View {
        VStack {
            Text("\(data)")
                .frame(maxWidth: .infinity)
                .foregroundColor(Color.black)
                .onTapGesture {
                    self.currentlySelectedData = data
                }
                .background {
                    if currentlySelectedData == data {
                        RoundedRectangle(cornerRadius: 10)
                            .frame(width: 40 - 3, height: 40 - 3)
                            .foregroundColor(Color.white)
                            .border(Color.blue)
                            .shadow(color: Color.gray.opacity(0.1), radius: 3.5, x: 0, y: 1.0)
                    }
                }
                .overlay {
                    if currentlySelectedData != data {
                        LinearGradient(
                            gradient: Gradient(
                                colors: [Color.gray.opacity(0.2), Color.clear]
                            ),
                            startPoint: .top,
                            endPoint: .bottom
                        )
                        .allowsHitTesting(false)
                        .transition(.opacity)
                        .frame(width: 39.0, height: 39.0)
                    }
                }
        }

    }
}
jdzmm42g

jdzmm42g1#

你的代码完全按照你的要求去做。
如果所选的currentlySelectedData不等于传入的值,则告诉它添加覆盖。但是您应该检查的是,该值是否是数组中的第一个或最后一个,并且不等于传入的值。
最快的方法是改变:

if currentlySelectedData != data {

致:

if results.first?.score == data && currentlySelectedData != data || results.last?.score == data && currentlySelectedData != data {

这应该能解决你的简单案子。

相关问题