SwiftUI ScrollView не центрирует контент, когда контент соответствует границам прокрутки - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь сделать так, чтобы содержимое внутри ScrollView было центрировано, когда это содержимое достаточно мало, чтобы не требовать прокрутки, но вместо этого оно выравнивается по верху. Это ошибка или я не добавляю что-то? Используя Xcode 11.4 (11E146)

    @State private var count : Int = 100

    var body : some View {
//        VStack {
            ScrollView {
                VStack {
                    Button(action: {
                        if self.count > 99 {
                            self.count = 5
                        } else {
                            self.count = 100
                        }
                    }) {
                        Text("CLICK")
                    }
                    ForEach(0...count, id: \.self) { no in
                        Text("entry: \(no)")
                    }
                }
                .padding(8)
                .border(Color.red)
                .frame(alignment: .center)
            }
            .border(Color.blue)
            .padding(8)
//        }
    }

enter image description here

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Модификатор frame(alignment: .center), который вы добавили, не работает, поскольку он оборачивает ваше представление в новое представление точно такого же размера. Из-за этого выравнивание ничего не делает, так как нет никакого дополнительного места для представления, которое нужно переместить.

Одним из возможных решений вашей проблемы было бы завершение целого ScrollView в GeometryReader для прочитайте доступную высоту. Затем используйте эту высоту, чтобы указать, что дети не должны быть меньше ее. Это сделает ваш взгляд центрированным внутри ScrollView.

struct ContentView: View {
    @State private var count : Int = 100

    var body : some View {
        GeometryReader { geometry in
            ScrollView {
                VStack {
                    Button(action: {
                        if self.count > 99 {
                            self.count = 5
                        } else {
                            self.count = 100
                        }
                    }) {
                        Text("CLICK")
                    }
                    ForEach(0...self.count, id: \.self) { no in
                        Text("entry: \(no)")
                    }
                }
                .padding(8)
                .border(Color.red)
                .frame(minHeight: geometry.size.height) // Here we are setting minimum height for the content
            }
            .border(Color.blue)
        }
    }
}
1 голос
/ 13 апреля 2020

Вы наблюдаете просто нормальное поведение ScrollView. Вот демонстрация возможного подхода к достижению вашей цели.

demo

// view pref to detect internal content height
struct ViewHeightKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}

// extension for modifier to detect view height
extension ViewHeightKey: ViewModifier {
    func body(content: Content) -> some View {
        return content.background(GeometryReader { proxy in
            Color.clear.preference(key: Self.self, value: proxy.size.height)
        })
    }
}

// Modified your view for demo
struct TestAdjustedScrollView: View {
    @State private var count : Int = 100

    @State private var myHeight: CGFloat? = nil
    var body : some View {
        GeometryReader { gp in
            ScrollView {
                VStack {
                    Button(action: {
                        if self.count > 99 {
                            self.count = 5
                        } else {
                            self.count = 100
                        }
                    }) {
                        Text("CLICK")
                    }
                    ForEach(0...self.count, id: \.self) { no in
                        Text("entry: \(no)")
                    }
                }
                .padding(8)
                .border(Color.red)
                .frame(alignment: .center)
                .modifier(ViewHeightKey())   // read content view height !!
            }
            .onPreferenceChange(ViewHeightKey.self) {
                // handle content view height
                self.myHeight = $0 < gp.size.height ? $0 : gp.size.height
            }
            .frame(height: self.myHeight) // align own height with content
            .border(Color.blue)
            .padding(8)
        }
    }
}
...