【问题标题】:SwitUI - VStack - Jumping when text enteredSwiftUI - VStack - 输入文本时跳转
【发布时间】:2021-08-24 02:04:40
【问题描述】:

我正在开发一个基本的密码输入屏幕,由一个顶部堆栈组成以显示当前输入,然后一些 HStack 显示数字

    VStack(){
        HStack(spacing: 20){
            ForEach(codes,id: \.self){i in
                Text("*")
            }
        }
        
        HStack(){
            <Number 1 - 3>
        }
        HStack(){
            <Number 4 - 6>
        }
        HStack(){
            <Number 7 - 9>
        }
        HStack(){
            <Number 0>
        }
    }

我面临的这个问题是当没有输入密码时 HStack 不会占用任何空间,因此垂直高度为 0,当我输入密码时,它会迫使整个视图随着视图调整大小而稍微跳跃.

我怎样才能阻止它呢

【问题讨论】:

    标签: swiftui vstack


    【解决方案1】:

    老实说,建造起来很有趣! ? 如果它解决了您的问题,请不要忘记将此答案标记为正确答案。 ✅

    问题

    跳跃效果是由于 SwiftUI 根据您的内容(密码数字)计算的可用空间更新所有视图位置。字体、字体粗细、文本大小等……都会影响其他视图的可用空间。

    解决方案

    为避免这种情况,您需要一个预定义的框架,让父视图知道您的数字永远不会占用更多空间。这样做,每次更新都不会影响任何其他视图的位置,因为分配的顶部空间将始终是您指定的大小,而不是数字大小(或不存在)。

    代码

    import SwiftUI
    import Combine
    
    
    // Using Combine to manage digits and future network calls…
    class PasscodeManager: ObservableObject {
        let codesQuantity = 4
        @Published var codes = [Int]()
    }
    
    
    struct PasscodeView: View {
    
        @StateObject private var manager = PasscodeManager()
    
        var body: some View {
            VStack {
                Spacer()
                // Dots placeholders and passcode digits
                selectedCodes
                Spacer()
                // Numberpad
                PasscodeLine(numbers: 1...3) { add(number: $0) }
                PasscodeLine(numbers: 4...6) { add(number: $0) }
                PasscodeLine(numbers: 7...9) { add(number: $0) }
                PasscodeLine(numbers: 0...0) { add(number: $0) }
                Spacer()
            }
            .padding()
        }
    
        var selectedCodes: some View {
            let minDots = manager.codes.count == manager.codesQuantity ? 0:1
            let maxDots = manager.codesQuantity - manager.codes.count
            return HStack(spacing: 32) {
                ForEach(manager.codes, id: \.self) { Text("\($0)") }
                if maxDots != 0 {
                    ForEach(minDots...maxDots, id: \.self) { _ in
                        Circle().frame(width: 12)
                    }
                }
            }
            .font(.title.bold())
            // Setting a default height should fix your problem. ? 
            .frame(height: 70)
        }
    
        func add(number: Int) {
            guard manager.codes.count < manager.codesQuantity else { return }
            manager.codes.append(number)
        }
    
    }
    
    struct PasscodeLine: View {
        let numbers: ClosedRange<Int>
        var select: (Int) -> Void
        var body: some View {
            HStack {
                ForEach(numbers, id: \.self) { number in
                    Spacer()
                    Button(action: { select(number) },
                           label: {
                            Text("\(number)")
                                .font(.title)
                                .fontWeight(.medium)
                                .foregroundColor(Color(.label))
                                .padding(32)
                                .background(Color(.quaternarySystemFill))
                                .clipShape(Circle())
                           })
                }
                Spacer()
            }
        }
    }
    

    结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 2020-10-29
      相关资源
      最近更新 更多