小屏幕设备上的 UI 损坏 - SwiftUI

Posted

技术标签:

【中文标题】小屏幕设备上的 UI 损坏 - SwiftUI【英文标题】:Broken UI on devices with small screen size - SwiftUI 【发布时间】:2021-11-03 19:37:26 【问题描述】:

所以基本上我已经制作了我的 UI,如果不是因为我的 UI/堆栈似乎不适合屏幕较小的设备,例如 iPod Touch 7th gen 或 iPhone SE 2nd将军我的印象是,如果我避免硬编码帧并使用动态元素,例如堆栈上的间距参数、.padding、Spacer() 等,那么 SwiftUI 将发挥它的布局魔力,并且它可以在多种屏幕尺寸上工作。我什至没有在这里使用复杂的视图,它只是几个堆栈和文本视图。

代码:

struct EntireView: View 
var viewModel: ViewModel
var body: some View 
    VStack 
        HeadView(vm: viewModel)
        Rectangle()
            .frame(width: UIScreen.main.bounds.width - 20, height: 1)
        FieldView(viewModel: viewModel)
        ButtonView()
    

struct HeadView: View 

var body: some View 
    VStack 
        VStack(spacing: 15) 
            Text("some text")
                .font(.custom(FontType.OpenSans.bold, size: 16))
            Text(vm.description)
                .font(.custom(FontType.OpenSans.semibold, size: 14))
        
        .padding()
        
        VStack 
            HStack 
                VStack 
                    Text("some text")
                        .font(.custom(FontType.OpenSans.bold, size: 16))
                    Text("some text")
                        .font(.custom(FontType.OpenSans.regular, size: 12))
                
                Spacer()
                VStack 
                    Text("some text")
                        .font(.custom(FontType.OpenSans.bold, size: 16))
                    Text(""some text")
                        .font(.custom(FontType.OpenSans.regular, size: 12))
                
                Spacer()
                VStack 
                    Text("some text")
                        .font(.custom(FontType.OpenSans.bold, size: 16))
                    Text("some text")
                        .font(.custom(FontType.OpenSans.regular, size: 12))
                
            
        
        .padding()
        HStack 
            Text("some text")
                .font(.custom(FontType.OpenSans.italic, size: 14))
            Spacer()
            Text("some text")
                .font(.custom(FontType.OpenSans.bold, size: 14))
                .foregroundColor(.white)
                .frame(width: 69, height: 25)
                .background(.green)
                .cornerRadius(4)
        
        .padding()
    

struct FieldView: View 
let viewModel: HoldingDetailViewModel

var body: some View 
    VStack(spacing: 20) 
        VStack(spacing: 10) 
            Text("some text")
                .foregroundColor(.blue)
            Text("some text")
                .foregroundColor(.blue)
        
        
        VStack(spacing: 10) 
            Text("some text")
                .foregroundColor(.blue)
            HStack 
                Text("some text")
                Rectangle()
                    .fill(.blue)
                    .frame(width: 1, height: 25)
                Text("some text")
            
            .foregroundColor(.blue)
        
        
        VStack(spacing: 10) 
            Text("some text")
                .foregroundColor(.blue)
            Text("some text")
                .foregroundColor(.blue)
        
        
        VStack(spacing: 10) 
            Text("some text")
                .foregroundColor(.blue)
            Text("some text")
                .foregroundColor(.blue)
        
        
        VStack(spacing: 10) 
            Text("some text")
                .foregroundColor(.blue)
            Text("some text")
                .foregroundColor(.blue)
        
        
    
    .font(.custom(FontType.OpenSans.semibold, size: 14))

在较小的设备上,甚至没有渲染元素,因为它们不适合屏幕,我应该如何解决这个问题?

【问题讨论】:

将您的代码表述为任何人都可以编译的minimal reproducible example 会很有帮助。或者,至少提供屏幕截图。一般来说,SwiftUI 通过响应式设计解决了大量的布局问题。但是,如果您有太多东西无法在屏幕上显示,它无法为您解决这个问题。例如,我在您的代码中看不到任何 ScrollViews,如果它在垂直方向上太大,您必须包含它。 另外,一般来说,我会避免使用UIScreen.main.bounds.width - 20 之类的东西——改用padding 首先,我很抱歉没有提供一个实际可重现的例子,我剥离了部分代码以避免以一个巨大的线程结束。其次,我刚刚测试了一个 ScrollView,这可能是解决方案,因为我猜我试图在屏幕上显示的内容实际上不适合较小的屏幕,即使在 UIKit 中也不可行,对吧?我以为我错过了一些与 SwiftUI 相关的东西,但可能只是这些元素确实不适合屏幕,并且滚动视图是强制性的。最后,注意避免使用 UIScreen,我认为填充是一种更好的方法。谢谢! 你是对的,它“即使在 UIKit 中也不可行”——在某个方向上有太多内容是无法避免的(除非你继续缩小字体、图像等)。另请记住,您应该适应用户的可访问性设置,例如字体大小(SwiftUI 免费为您提供,但您使用显式字体大小覆盖)这将使内容增长得更多。 您是否有关于它如何在较小的屏幕尺寸上“破坏”视图的屏幕截图?那会很有帮助 【参考方案1】:

目前,您已经堆叠了如此多的垂直堆栈,以至于 UI 构建器只是用尽了物理屏幕空间来渲染您的所有 UI 元素。

我认为你想要使用的是这样的ScrollView

struct EntireView: View 
    var viewModel: ViewModel
    var body: some View 
        ScrollView(.vertical, showsIndicators: false) 
            HeadView(vm: viewModel)
            Rectangle()
                .frame(width: UIScreen.main.bounds.width - 20, height: 1)
            FieldView(viewModel: viewModel)
            ButtonView()
        
    

这样,所有 UI 元素都呈现在一个大的 VStack 中,可以说,您可以滚动浏览。因此,不限于物理屏幕尺寸。这是你想要的吗?

如果您希望视图的某些部分是可滚动的,而有些则不是,例如,您可以执行以下操作:

struct EntireView: View 
    var viewModel: ViewModel
    var body: some View 
        VStack 
            HeadView(vm: viewModel)
            ScrollView(.vertical, showsIndicators: false) 
            
                 Rectangle()
                     .frame(width: UIScreen.main.bounds.width - 20, height: 1)
                 FieldView(viewModel: viewModel)
                 ButtonView()
             
        
        
    

这样,HeadView 将保持在屏幕顶部的位置,其他内容将可滚动。

【讨论】:

是的!这正是正在发生的事情,无论出于何种原因,我认为我的布局有问题并且我在 SwiftUI 中遗漏了一些东西,但它最终实际上没有足够的物理空间来渲染所有的堆栈,哈哈,新手错误!所以滚动视图就可以了。也非常感谢第二部分,我实际上使用了那个案例并且只让我的 UI 的几个部分可滚动!谢谢!! 嗨@stompy,如果 Björn 解决了您的问题,请将其标记为正确答案,以便其他遇到相同问题的人可以轻松找到解决方案 :) 很高兴它有帮助。祝你的 Swift 之旅好运 :) 谢谢!从外观上看,我肯定会需要它哈哈。

以上是关于小屏幕设备上的 UI 损坏 - SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

Twitter Bootstrap 响应式导航栏在小屏幕上损坏

微信小程序 不同设备下的屏幕适配处理 (px和rpx换算)

分页:如何限制小屏幕设备上的页面数量

基于屏幕尺寸的 UI 元素间距

Unity3d UGUI基于屏幕尺寸的自适应

iPadOS 13 上的屏幕旋转故障