在SwiftUI中是否有可能只在一行中显示尽可能多的(固定大小的)视图而不裁剪,例如裁剪视图的部分。
示例布局
-----------------------------------------
| |
| ------- ------- ------- ------- -------
| | VIEW1 | | VIEW2 | | VIEW3 | | VIEW4 | | VIEW5 |
| ------- ------- ------- ------- -------
| |
-----------------------------------------
在本例中,应该隐藏VIEW5
,因为它完全超出了父视图的范围。这可以用.clipped()
来完成。
VIEW4
也应该是完全隐藏的!因为如果要展示它,就必须切断它。所有其他视图都应正常呈现。
SwiftUI布局
此初始尝试存在以下问题:
itemView
的宽度比外部VStack
大得多,前缘没有对齐=>☑️最后的视图可能是可见的,即使它不是完全在屏幕上。应该避免这种情况。struct DemoView: View {
let items: [String]
@State private var totalHeight = CGFloat.zero
var body: some View {
VStack(alignment: .leading) {
Text("Demo View:")
itemView
.padding()
.background(Color.green)
}
}
private var itemView: some View {
HStack {
ForEach(items, id: \.self) { item in
Text(item)
.lineLimit(1)
.fixedSize()
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
}
}
.frame(maxWidth: 350)
}
}
#if DEBUG
struct DemoView_Previews: PreviewProvider {
static var items: [String] = (2000..<2020).map(String.init)
// .map { item in
// Bool.random() ? item : item + item
// }
static var previews: some View {
DemoView(items: items)
// .previewLayout(.sizeThatFits)
}
}
#endif
发布于 2020-12-15 15:30:45
在HStack
框架上使用对齐剪裁(用Xcode 12.1 / iOS 14.1测试)
private var itemView: some View {
HStack {
ForEach(items, id: \.self) { item in
Text(item)
.lineLimit(1)
.fixedSize()
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
}
}
.frame(maxWidth: 350, alignment: .leading)
.clipped()
}
发布于 2020-12-16 18:05:24
以下是基于您的评论的解决方案。VStack与前导对齐,然后我添加了一个ScrollView来保存项的HStack。此外,我在每个项目中添加了一个白色.overlay,当项目完全移动到屏幕上时,透明度将从1.0 (完全覆盖项)更改为0.0 (显示项)。
还请注意,我将前面的填充移到了VStack中,这样当您向左滚动时,项目就会移动到屏幕的边缘,而不是在填充的地方被切断。
struct DemoView: View {
let items: [String]
var body: some View {
VStack(alignment: .leading) {
Text("Demo View:")
.padding(.leading)
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(items, id: \.self) { item in
Text(item)
.lineLimit(1)
.fixedSize()
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
.overlay(
GeometryReader { geometry in
Color.white
.opacity(
geometry.frame(in: .global).maxX < UIScreen.main.bounds.width ? 0.0 : 1.0
)
}
)
}
}
.background(Color.orange) // Starting HStack
.padding(.leading)
.background(Color.green) // Scrollable area
}
}
}
}
struct DemoView_Previews: PreviewProvider {
static var previews: some View {
DemoView(items: [
"ONE",
"TWO",
"THREE",
"FOUR",
"FIVE",
"SIX",
"SEVEN",
"EIGHT",
"NINE",
"TEN",
])
}
}
发布于 2020-12-17 07:32:09
这是nicksamo提供的通用内容ViewBuilder
的答案。谢谢你的解决方案!:)
import SwiftUI
struct NonClippingView<Item: Hashable, Content: View>: View {
let items: [Item]
let isScrollingDisabled: Bool
let backgroundColor: Color
let content: (Item) -> Content
init(items: [Item], isScrollingDisabled: Bool = false, backgroundColor: Color = .white, @ViewBuilder content: @escaping (Item) -> Content) {
self.items = items
self.isScrollingDisabled = isScrollingDisabled
self.backgroundColor = backgroundColor
self.content = content
}
var body: some View {
GeometryReader { proxy in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(items, id: \.self) { item in
content(item)
.overlay(
GeometryReader { geometry in
backgroundColor
.opacity(
geometry.frame(in: .global).maxX < proxy.size.width ? 0.0 : 1.0
)
}
)
}
}
// .background(Color.orange) // Starting HStack
.padding(.leading)
// .background(Color.green) // Scrollable area
}
.disabled(isScrollingDisabled)
}
}
}
struct NonClippingView_Previews: PreviewProvider {
static var previews: some View {
NonClippingView(items: [
"ONE",
"TWO",
"THREE",
"FOUR",
"FIVE",
"SIX",
"SEVEN",
"EIGHT",
"NINE",
"TEN",
], content: { item in
VStack {
Image(systemName: "tag")
Text(item)
.lineLimit(1)
.fixedSize()
}
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
})
}
}
https://stackoverflow.com/questions/65308828
复制相似问题