SwiftUI当总内容宽度小于屏幕宽度时,如何在动态水平滚动视图中居中内容

Posted

技术标签:

【中文标题】SwiftUI当总内容宽度小于屏幕宽度时,如何在动态水平滚动视图中居中内容【英文标题】:SwiftUI How can I center content in a dynamic horizontal scroll view when the total content width is less than screen width 【发布时间】:2021-08-12 06:07:11 【问题描述】:

我有一个水平滚动视图,它显示了来自动态图像数组的一堆图像。当总内容宽度大于屏幕宽度时,一切都很好。但是,如果说数组中只有一个图像,它将前导对齐,这是默认行为。

当总内容宽度小于屏幕宽度并且不知道如何实现时,我希望内容居中:

ScrollView(.horizontal) 
    HStack 
        ForEach(images.indices, id: \.self)  index in
            let image = images[index] 
                Image(uiImage(uiImage: image))
            
        
    
    .frame(height: 200)

所以在这种情况下,如果只有一个图像它是对齐的,但我希望它居中,直到内容填满屏幕然后滚动。在填满屏幕之前,我不介意弹跳或不弹跳。

【问题讨论】:

这里的高度是相同的***.com/a/62878812/12299030 - 你只需要复制它的宽度。 其他可能的方法是在 ScrollView 小于屏幕时使其适合内容,例如 ***.com/a/61185571/12299030。 【参考方案1】:

您可以使用GeometryReader 并在ScrollView内容 上设置minWidth

示例(出于测试目的将图像换成颜色):

struct ContentView: View 
    @State private var width: CGFloat?
    private let total = 10//0

    var body: some View 
        ScrollView(.horizontal) 
            HStack 
                ForEach(0 ..< total)  index in
                    Color.red.opacity(Double(index) / Double(total) + 0.05)
                        .frame(width: 20)
                
//                ForEach(images.indices, id: \.self)  index in
//                    let image = images[index] 
//                        Image(uiImage(uiImage: image))
//                    
//                
            
            .frame(height: 200)
            .frame(minWidth: width)
        
        .widthReader  width in
            self.width = width
        
    

自定义widthReader(_:)修饰符:

extension View 
    func widthReader(_ width: @escaping (CGFloat?) -> Void) -> some View 
        modifier(WidthReaderModifier(width: width))
    


fileprivate struct WidthReaderModifier: ViewModifier 
    private struct WidthPreferenceKey: PreferenceKey 
        static func reduce(value: inout CGFloat?, nextValue: () -> CGFloat?) 
            value = nextValue()
        
    

    let width: (CGFloat?) -> Void

    func body(content: Content) -> some View 
        content
            .background(
                GeometryReader  geo in
                    Color.clear
                        .preference(key: WidthPreferenceKey.self, value: geo.size.width)
                        .onAppear 
                            width(geo.size.width)
                        
                
            )
            .onPreferenceChange(WidthPreferenceKey.self)  width in
                self.width(width)
            
    

【讨论】:

以上是关于SwiftUI当总内容宽度小于屏幕宽度时,如何在动态水平滚动视图中居中内容的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI如何对齐大于屏幕宽度的视图

如何在溢出屏幕的 SwiftUI 中制作无限宽度的视图?

SwiftUI - ScrollView 的宽度为 0,我的内容不可见

如何使视图最大。 SwiftUI 中带填充的宽度

如果屏幕小于某个宽度,则隐藏 div

在我的页脚中,当我的屏幕宽度小于 700 像素时,如何将社交图标分成 2 行?