当前位置:网站首页>Xcode如何利用预览(Preview)让SwiftUI视图快速适配不同尺寸的设备
Xcode如何利用预览(Preview)让SwiftUI视图快速适配不同尺寸的设备
2022-07-29 19:03:00 【大熊猫侯佩】

概览
有时候,我们需要根据不同尺寸的设备适配最合适的视图布局。
这在SwiftUI项目中如何操作呢?

如上图所示,我们在SwiftUI中自定义了一个多项列表视图,不过它在不同尺寸的设备中显示的并不完美。在大屏设备尾部留出了太多空间,而在小屏设备中最后一列又显示不全,真是让人伤脑筋啊!
不过别急!
在本篇博文中,我们将介绍一些在不同设备中适配SwiftUI视图的小技巧,相信小伙伴们看完之后一定能妥妥的搞定适配问题了。
那还等什么呢?
Let’s go!
所见即所得
要想适配不同尺寸的设备,首先我们要做的第一件是就是能够快速预览不同设备的界面。
我们可以通过为SwiftUI视图添加特定的修改器,在Xcode预览界面中快速浏览其在对应设备中的外观:
struct TestView_Previews: PreviewProvider {
static var body: some View {
NavigationView {
// 实际测试视图的布局描述
}
}
static var previews: some View {
Group {
body
.previewDevice(.init(rawValue: "iPhone 13 Pro Max"))
body
.previewDevice(.init(rawValue: "iPhone 13 Pro"))
body
.previewDevice(.init(rawValue: "iPhone 12 mini"))
body
.previewDevice(.init(rawValue: "iPod touch (7th generation)"))
}
}
}
在以上预览视图代码中,我们分别将测试视图放到 iPhone 13 Pro Max、iPhone 13 Pro、iPhone 12 mini以及iPod touch等四种不同尺寸设备中去预览显示。
获取设备尺寸
在不同设备中预览我们的视图只是第一步,接着我们需要在运行中确定到底当前在何种设备中运行。
或者换句话说:当前运行的设备屏幕尺寸是多少?
为了获取当前运行设备的名称,我们只需一行代码:
UIDevice.current.name
同样,为了获取当前运行设备屏幕的尺寸,即逻辑分辨率,同样只需一行代码:
UIScreen.main.bounds
这里,我们只需要设备屏幕的尺寸。
动如脱兔,静若处子
能够在运行中确定设备的尺寸之后,我们就可以根据不同设备的尺寸大小,来动态调整我们视图的界面了。
首先,写一个对应的布局尺寸结构:
fileprivate enum LayoutSize {
case tiny, small, middle, large
// 根据当前设备计算实际的布局尺寸
static func calc() -> Self {
let width = UIScreen.main.bounds.width
if width <= 320 {
return .tiny
}else if width <= 360 {
return .small
}else if width <= 390 {
return .middle
}else{
return .large
}
}
// 列表中单个列的宽度
var unitWidth: CGFloat {
let w: CGFloat
switch self {
case .tiny, .small, .middle:
w = 30
case .large:
w = 38
}
return w
}
}
在以上代码中,我们根据前面4种典型iPhone设备的宽度,创建了4种对应的尺寸枚举类型。
我们希望在 large 和 middle 尺寸类型的设备中,最大化每列的宽度;而在较小尺寸 small 和 tiny 等设备中,紧凑的显示每列,并按需合并若干列,达到最优利用空间的目的:
if layoutSize == .large || layoutSize == .middle {
Text("\(trace.totalGainedScore)")
.fontWeight(.heavy)
.font(.body)
.foregroundColor(scoreColor)
.opacity(1.0)
.frame(minWidth: layoutSize.unitWidth)
baseScoreView
.underline(true, color: stateColor)
.fontWeight(.bold)
.font(.callout)
.foregroundColor(stateColor)
.frame(minWidth: layoutSize.unitWidth)
}else{
HStack(alignment: .top, spacing: 5) {
Text("\(trace.totalGainedScore)")
.fontWeight(.heavy)
.font(.body)
.foregroundColor(scoreColor)
.opacity(1.0)
baseScoreView
.underline(true, color: stateColor)
.fontWeight(.bold)
.font(.callout)
.foregroundColor(stateColor)
}.frame(minWidth: 50)
}
不过,即使采用上面的优化方法,在最小的 tiny 设备界面中,最后一列的显示仍然捉襟见肘。
这时,我们需要更进一步,大幅度更改列表的布局,将第二列的内容放到第一列最底部显示,继续压榨显示空间:
if layoutSize == .tiny {
VStack(spacing: 2) {
Text(Model.shortDateFt.string(from: trace.date ?? Date.distantPast))
.fontWeight(.light)
.font(.footnote)
.foregroundColor(.slateGray)
CommonUI.hiveScoringTracesView(trace, model: model)
// tiny设备中,需要将第二列显示的状态内容放到第一列的底部
stateView
.foregroundColor(stateColor)
.frame(minWidth: layoutSize.unitWidth)
}.frame(minWidth: 65.0)
}else{
VStack {
Text(Model.shortDateFt.string(from: trace.date ?? Date.distantPast))
.fontWeight(.light)
.font(.footnote)
.foregroundColor(.slateGray)
CommonUI.hiveScoringTracesView(trace, model: model)
}.frame(minWidth: 65.0)
stateView
.foregroundColor(stateColor)
.frame(minWidth: layoutSize.unitWidth)
}
现在,运行代码看一下布局适配的效果:

如上图所示,现在不同设备中的显示效果是不是比一开始要好很多呢?
我们最大化的利用了空间,做到了视图适配的收放自如,棒棒哒!
总结
在本篇博文中,我们利用SwiftUI代码,在Xcode预览中快速查看了不同设备的界面,并据此动态调整视图的布局,达到了最优空间之利用的目的。
最后,感谢各位观赏,我们下次再会!
边栏推荐
- yarn的安装和使用(yarn安装mysql)
- What should I do if the Win11 network is unstable?The solution to frequent disconnection of wifi connection in Win11
- centos8安装redis
- C# CLI(公共语言基础结构)
- C pitfalls and pitfalls
- Typescript类功能混合(mixin)使用,将多个类中功能合并到一个对象
- TDengine 落地协鑫能科,数百亿数据压缩至 600GB
- 会议OA项目之待开会议&&所有会议功能
- 第01章 Linux下MySQL的安装与使用【1.MySQL架构篇】【MySQL高级】
- 手机银行体验性测试:如何获取用户真实感受
猜你喜欢
随机推荐
[数学]必备基本知识
函数指针与block[通俗易懂]
Custom Components -behaviors
UE4选不中半透明物体(半透明显示快捷键是啥)
效率技巧│十分钟学会 xmind 思维导图的使用
洪九果品、百果园抢滩港股,卖水果是门好生意吗?
2022暑假 动态规划总结
Neo4j开源NoSQL数据库
Postgresql-xl全局快照代码走读与GTM原理(支线1)
要卖课、要带货,知识付费系统帮你一步搞定!
不堆概念、换个角度聊多线程并发编程
关于高考选志愿
基于STM32的RFID-RC522门禁系统
秋招之路-经典面试题之手写字符串函数
How to read excel test data in Go language, easy to learn
7 lines of code crashed station B for 3 hours, but because of "a tricky 0"
线程池 ThreadPoolExecutor 详解
嵌入式开发:嵌入式基础——软件错误分类
在宇宙中心五道口上班,是怎样一种体验
MySQL 中的反斜杠 \\,我上当了








