SwiftUI 将列表中的行间距减少为空
SwiftUI reduce spacing of rows in a list to null
我想将列表中的行距缩小为空。
我尝试减少填充没有奏效。
设置“.environment(.defaultMinListRowHeight, 0)”帮助很大。
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
List {
ForEach(data, id: \.self)
{ item in
Text("\(item)")
.padding(0)
//.frame(height: 60)
.background(Color.yellow)
}
//.frame(height: 60)
.padding(0)
.background(Color.blue)
}
.environment(\.defaultMinListRowHeight, 0)
.onAppear { UITableView.appearance().separatorStyle = .none }
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
}
}
}
将“separatorStyle”更改为“.none”仅删除了该行,但留下了 space.
列表行或行之间的分隔符是否有额外的“隐藏”视图?
如何控制?
使用 ScrollView
而不是 List
会是一个好的解决方案吗?
ScrollView(.horizontal, showsIndicators: true)
{
//List {
ForEach(data, id: \.self)
{ item in
HStack{
Text("\(item)")
Spacer()
}
它也适用于大型数据集吗?
嗯,实际上并不奇怪 - .separatorStyle = .none
工作正常。我想你混淆了文本背景和单元格背景——它们被不同的修饰符改变了。请在下面找到经过测试和工作的代码 (Xcode 11.2 / iOS 13.2)
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
List {
ForEach(data, id: \.self)
{ item in
Text("\(item)")
.background(Color.yellow) // text background
.listRowBackground(Color.blue) // cell background
}
}
.onAppear { UITableView.appearance().separatorStyle = .none }
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
}
}
}
更新:
it's not possible to avoid the blue space between the yellow Texts?
从技术上讲是的,这是可能的,但是对于演示来说,它使用硬编码值并且不难适应一些,而动态计算这个可能具有挑战性......无论如何,它是
它需要组合堆栈进行压缩,内容填充进行抵抗,环境进行限制:
List {
ForEach(data, id: \.self)
{ item in
HStack { // << A
Text("\(item)")
.padding(.vertical, 2) // << B
}
.listRowBackground(Color.blue)
.background(Color.yellow)
.frame(height: 12) // << C
}
}
.environment(\.defaultMinListRowHeight, 12) // << D
减少行间距真的很棘手,试试
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)").font(.largeTitle)
.background(Color.yellow)
}.background(Color.green)
.padding(.leading, 10)
.padding(.bottom, -25)
.frame(maxWidth: .infinity)
}
}
}
}
}
它使用 ScrollView 而不是 List 和负填充。
没有找到基于List的解决方案,只好求苹果出xxxxStyle协议和底层结构
更新
这个负填充值怎么样?当然,这取决于我们行内容的高度,不幸的是取决于 SwiftUI 布局策略。让我们尝试一些更动态的内容! (我们使用零填充来演示要解决的问题)
struct ContentView: View {
@State var data : [CGFloat] = [20, 30, 40, 25, 15]
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)").font(.system(size: item))
.background(Color.yellow)
}.background(Color.green)
.padding(.leading, 10)
//.padding(.bottom, -25)
.frame(maxWidth: .infinity)
}
}
}
}
}
很明显行距不是固定值!我们必须分别计算每一行。
下一个代码片段演示了基本思想。我使用全局字典(存储每行的高度和位置)并尽量避免任何高阶函数和/或一些高级 SwiftUI 技术,因此很容易看出策略。所需的填充仅在 .onAppear 闭包中计算一次
import SwiftUI
var _p:[Int:(CGFloat, CGFloat)] = [:]
struct ContentView: View {
@State var data : [CGFloat] = [20, 30, 40, 25, 15]
@State var space: [CGFloat] = []
func spc(item: CGFloat)->CGFloat {
if let d = data.firstIndex(of: item) {
return d < space.count ? space[d] : 0
} else {
return 0
}
}
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)")
.font(.system(size: item))
.background(Color.yellow)
}
.background(
GeometryReader { proxy->Color in
if let i = self.data.firstIndex(of: item) {
_p[i] = (proxy.size.height, proxy.frame(in: .global).minY)
}
return Color.green
}
)
.padding(.leading, 5)
.padding(.bottom, -self.spc(item: item))
.frame(maxWidth: .infinity)
}.onAppear {
var arr:[CGFloat] = []
_p.keys.sorted(by: <).forEach { (i) in
let diff = (_p[i + 1]?.1 ?? 0) - (_p[i]?.1 ?? 0) - (_p[i]?.0 ?? 0)
if diff < 0 {
arr.append(0)
} else {
arr.append(diff)
}
}
self.space = arr
}
}
}
}
}
运行 我得到的代码
我用简单的 SwiftUI 方式来做:
struct ContentView: View {
init() {
UITableView.appearance().separatorStyle = .none
}
var body: some View {
List {
ForEach(0..<10){ item in
Color.green
}
.listRowInsets( EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) )
}
}
}
我想将列表中的行距缩小为空。
我尝试减少填充没有奏效。 设置“.environment(.defaultMinListRowHeight, 0)”帮助很大。
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
List {
ForEach(data, id: \.self)
{ item in
Text("\(item)")
.padding(0)
//.frame(height: 60)
.background(Color.yellow)
}
//.frame(height: 60)
.padding(0)
.background(Color.blue)
}
.environment(\.defaultMinListRowHeight, 0)
.onAppear { UITableView.appearance().separatorStyle = .none }
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
}
}
}
将“separatorStyle”更改为“.none”仅删除了该行,但留下了 space.
列表行或行之间的分隔符是否有额外的“隐藏”视图?
如何控制?
使用 ScrollView
而不是 List
会是一个好的解决方案吗?
ScrollView(.horizontal, showsIndicators: true)
{
//List {
ForEach(data, id: \.self)
{ item in
HStack{
Text("\(item)")
Spacer()
}
它也适用于大型数据集吗?
嗯,实际上并不奇怪 - .separatorStyle = .none
工作正常。我想你混淆了文本背景和单元格背景——它们被不同的修饰符改变了。请在下面找到经过测试和工作的代码 (Xcode 11.2 / iOS 13.2)
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
List {
ForEach(data, id: \.self)
{ item in
Text("\(item)")
.background(Color.yellow) // text background
.listRowBackground(Color.blue) // cell background
}
}
.onAppear { UITableView.appearance().separatorStyle = .none }
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
}
}
}
更新:
it's not possible to avoid the blue space between the yellow Texts?
从技术上讲是的,这是可能的,但是对于演示来说,它使用硬编码值并且不难适应一些,而动态计算这个可能具有挑战性......无论如何,它是
它需要组合堆栈进行压缩,内容填充进行抵抗,环境进行限制:
List {
ForEach(data, id: \.self)
{ item in
HStack { // << A
Text("\(item)")
.padding(.vertical, 2) // << B
}
.listRowBackground(Color.blue)
.background(Color.yellow)
.frame(height: 12) // << C
}
}
.environment(\.defaultMinListRowHeight, 12) // << D
减少行间距真的很棘手,试试
struct ContentView: View {
@State var data : [String] = ["first","second","3rd","4th","5th","6th"]
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)").font(.largeTitle)
.background(Color.yellow)
}.background(Color.green)
.padding(.leading, 10)
.padding(.bottom, -25)
.frame(maxWidth: .infinity)
}
}
}
}
}
它使用 ScrollView 而不是 List 和负填充。
没有找到基于List的解决方案,只好求苹果出xxxxStyle协议和底层结构
更新
这个负填充值怎么样?当然,这取决于我们行内容的高度,不幸的是取决于 SwiftUI 布局策略。让我们尝试一些更动态的内容! (我们使用零填充来演示要解决的问题)
struct ContentView: View {
@State var data : [CGFloat] = [20, 30, 40, 25, 15]
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)").font(.system(size: item))
.background(Color.yellow)
}.background(Color.green)
.padding(.leading, 10)
//.padding(.bottom, -25)
.frame(maxWidth: .infinity)
}
}
}
}
}
很明显行距不是固定值!我们必须分别计算每一行。
下一个代码片段演示了基本思想。我使用全局字典(存储每行的高度和位置)并尽量避免任何高阶函数和/或一些高级 SwiftUI 技术,因此很容易看出策略。所需的填充仅在 .onAppear 闭包中计算一次
import SwiftUI
var _p:[Int:(CGFloat, CGFloat)] = [:]
struct ContentView: View {
@State var data : [CGFloat] = [20, 30, 40, 25, 15]
@State var space: [CGFloat] = []
func spc(item: CGFloat)->CGFloat {
if let d = data.firstIndex(of: item) {
return d < space.count ? space[d] : 0
} else {
return 0
}
}
var body: some View {
VStack {
ScrollView {
ForEach(data, id: \.self) { item in
VStack(alignment: .leading, spacing: 0) {
Color.red.frame(height: 1)
Text("\(item)")
.font(.system(size: item))
.background(Color.yellow)
}
.background(
GeometryReader { proxy->Color in
if let i = self.data.firstIndex(of: item) {
_p[i] = (proxy.size.height, proxy.frame(in: .global).minY)
}
return Color.green
}
)
.padding(.leading, 5)
.padding(.bottom, -self.spc(item: item))
.frame(maxWidth: .infinity)
}.onAppear {
var arr:[CGFloat] = []
_p.keys.sorted(by: <).forEach { (i) in
let diff = (_p[i + 1]?.1 ?? 0) - (_p[i]?.1 ?? 0) - (_p[i]?.0 ?? 0)
if diff < 0 {
arr.append(0)
} else {
arr.append(diff)
}
}
self.space = arr
}
}
}
}
}
运行 我得到的代码
我用简单的 SwiftUI 方式来做:
struct ContentView: View {
init() {
UITableView.appearance().separatorStyle = .none
}
var body: some View {
List {
ForEach(0..<10){ item in
Color.green
}
.listRowInsets( EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) )
}
}
}