在 TVOS 上的 SwiftUI 布局中苦苦挣扎
Posted
技术标签:
【中文标题】在 TVOS 上的 SwiftUI 布局中苦苦挣扎【英文标题】:Struggling with layout in SwiftUI on TVOS 【发布时间】:2020-07-10 23:39:13 【问题描述】:我在 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()
如果有帮助,这里是相关的帮助器和 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
目标:
【问题讨论】:
你肯定需要ContentMode.fill,否则即使图像的框架可以按照你的意愿对齐,由于不适当的纵横比,图像本身在框架内可能会在水平或垂直方向上留下空白。跨度> 【参考方案1】:您可以使用 Asperis 答案,或者,如果 ContentMode.Fit 对您很重要(因为您不想剪辑图像),只需删除图像上框架修饰符的宽度部分,然后添加VStack 后面的 Spacer,它将消耗其余部分:
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)
这将产生以下图像: Correct layout
【讨论】:
以上是关于在 TVOS 上的 SwiftUI 布局中苦苦挣扎的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - tvOS 上的 AVPlayerViewController 全屏
我正在为使用 ConstraintLayout 和 Barrier 的 Android 布局而苦苦挣扎
多次使用 Android TouchDelegate 苦苦挣扎