layout - 在 TVOS 上的 SwiftUI 布局中苦苦挣扎
问题描述
我在 TVOS 中使用 SwiftUI 有一个可行的 UI,但我不知道如何让它正确布局。
目标:
- 屏幕为全屏,未插入安全区域
- 相册图像为正方形,保留纵横比,从上到下填充
- 专辑和艺术家文本布局舒适,靠近专辑封面
import SwiftUI
struct ContentView: View {
@ObservedObject var ds = DataStore()
var body: some View {
HStack(alignment: .top) {
if (ds.currentRoom.albumImage != nil) {
Image(uiImage: ds.currentRoom.albumImage!)
.resizable()
.aspectRatio(contentMode: ContentMode.fit)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(Color.black)
}
VStack(alignment: .leading, spacing: 8) {
Text(ds.currentRoom.artist ?? "?")
.font(.system(.title, design: .default))
.bold()
.foregroundColor(Color.gray)
.padding(.top, 100)
Text(ds.currentRoom.title ?? "?")
.font(.system(.headline, design: .default))
.foregroundColor(Color.gray)
.padding(.bottom, 100)
Button(action: { print ("pressed!" )} ) {
Image(systemName: "playpause")
.font(.system(.title, design: .default))
.foregroundColor(Color.gray)
.padding(30)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(Color.green, lineWidth: 4)
)
}
}
}
.padding(20)
.background(Color.black)
.edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
如果它有帮助,这里是相关的 helper 和 DataSource 方法:
DataStore() 类有这个方法:
import SwiftUI
import Combine
class CurrentRoom {
var artist: String?
var title: String?
var album: String?
var albumArtURI: String?
var absoluteAlbumArtURI: String?
var albumImage: UIImage?
}
class DataStore: ObservableObject {
@Published var currentRoom: CurrentRoom = CurrentRoom()
init() {
getCurrentRoom()
}
func getCurrentRoom() {
currentRoom.artist = "Eilen Jewell"
currentRoom.album = "Sundown over Ghost Town"
currentRoom.title = "Half-Broke Horse"
currentRoom.absoluteAlbumArtURI = "https://images-na.ssl-images-amazon.com/images/I/71mkKfTQD0L._SX425_.jpg"
currentRoom.albumImage = Api().getImageDataFromURI(UrlAsString: currentRoom.absoluteAlbumArtURI)
}
}
struct DataStore_Previews: PreviewProvider {
static var previews: some View {
/*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
}
}
最后:
class Api {
func getImageDataFromURI(UrlAsString: String?) -> UIImage? {
if let URI = UrlAsString {
if URI.starts(with: "http") {
if let url = URL(string: URI) {
let data = try? Data(contentsOf: url)
if let imageData = data {
return UIImage(data: imageData)
}
}
}
}
return nil
}
}
解决方案
您可以使用 Asperis 答案,或者,如果 ContentMode.Fit 对您很重要(因为您不想剪辑图像),只需删除图像上框架修饰符的宽度部分,然后在后面添加一个 Spacer VStack,它将消耗其余部分:
struct ContentView: View {
@ObservedObject var ds = DataStore()
var body: some View {
HStack(alignment: .top) {
if (ds.currentRoom.albumImage != nil) {
Image(uiImage: ds.currentRoom.albumImage!)
.resizable()
.aspectRatio(contentMode: ContentMode.fit)
.frame(minHeight: 0, maxHeight: .infinity)
.background(Color.black)
}
VStack(alignment: .leading, spacing: 8) {
Text(ds.currentRoom.artist ?? "?")
.font(.system(.title, design: .default))
.bold()
.foregroundColor(Color.gray)
.padding(.top, 100)
Text(ds.currentRoom.title ?? "?")
.font(.system(.headline, design: .default))
.foregroundColor(Color.gray)
.padding(.bottom, 100)
Button(action: { print ("pressed!" )} ) {
Image(systemName: "playpause")
.font(.system(.title, design: .default))
.foregroundColor(Color.gray)
.padding(30)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(Color.green, lineWidth: 4)
)
}
}
.padding(.leading, 10)
Spacer()
}
.padding(20)
.background(Color.black)
.edgesIgnoringSafeArea(.all)
}
}
这将产生这个图像: 正确的布局
推荐阅读
- android - APK 限制安装在虚拟设备中
- azure - 切换到 Azure.Storage.Queues 后 Azure 函数中的模型绑定问题
- sql - 具有行数的新表
- java - 如何在 JPA(Java、Spring、Hibernate 和 Postgres)中正确删除作为外来键引用的行
- python - 在 Windows 中查找 database.ini 文件
- python - 如何获得数组中某物的最短重复?
- java - 它不调用的工人的构造函数?
- c++ - 来自可变参数模板的 C++ 结构字段名称和类型
- javascript - 在突出显示行和列时冻结第一行
- url - 获取物理类别中所有 Wikipedia 文章的 URL 列表