У меня есть этот код для отображения списка пользовательских строк.
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
List(1...10) {_ in
CustomRow()
}
}
}
}
Однако я хочу удалить строку в каждой строке. Я пытался не использовать List
и вместо этого использовать ForEach
внутри ScrollView
, но это полностью удаляет все стили, включая отступы и поля. Я просто хочу удалить линии и ничего больше.
Пожалуйста, помогите, спасибо.
Привет, вопрос в ссылке относится к удалить лишние строки для пустых строк, это к удалить все строки для всех строк (пустых или непустых), спасибо.
Да, немного другие вопросы, но, к сожалению, тот же вывод (пока): не представляется возможным. См. также ответы на этот вопрос: stackoverflow.com/questions/56517904/…
LazyVStack
внутри ScrollView
глючит и не имеет всех функций List
Просто добавьте .listRowSeparator(.hidden)
в качестве модификатора к представлению, содержащемуся в List
. https://developer.apple.com/documentation/swiftui/texteditor/listrowseparator(_:edges:)
List {
ForEach(garage.cars) { car in
Text(car.model)
.listRowSeparator(.hidden)
}
}
Добавление UITableView.appearance().separatorColor = .clear
в любом месте вашего кода до появления List
должно работать. Хотя это решение удаляет разделители, обратите внимание, что все экземпляры List
будут привязаны к этому стилю, поскольку в настоящее время нет официального способа удалить только разделители определенных экземпляров. Вы можете запустить этот код в onAppear
и отменить его в onDisappear
, чтобы сохранить разные стили.
Также обратите внимание, что этот код предполагает, что Apple использует UITableView
для возврата List
, что неверно в iOS 14 SDK. Надеюсь, в будущем они добавят официальный API. Кредит на https://twitter.com/singy/status/1169269782400647168.
Хотя этот код может ответить на вопрос, было бы лучше объяснить, как он решает проблему, не вводя других, и зачем его использовать. Ответы, содержащие только код, в долгосрочной перспективе бесполезны.
Наконец, спасибо! Все просто и работает (по крайней мере, на данный момент), Ура!
Спасибо! Просто обратите внимание, что вместо этого я бы изменил стиль разделителя, так как его легче восстановить в исходное состояние .onAppear { UITableView.appearance().separatorStyle = .none } .onDisappear { UITableView.appearance().separatorStyle = .singleLine }
Использование этого API по какой-то причине приводит к сбою приложения, нужно найти другой обходной путь.
Apple, скорее всего, откажется от использования List
под капотом. Когда это произойдет, эта реализация сломается. Вместо этого вы можете использовать UITableView
в подвидах вашего списка.
Одна из проблем с использованием этого в .onAppear
и .onDisappear
заключается в том, что последний не вызывается, когда вы представляете модальный лист, поэтому все списки и формы внутри модального окна по-прежнему обрабатываются .onAppear
.
Может быть, использовать сетку с одним столбцом в iOS 14?
@EverUribe можно было даже использовать простой VStack
, чтобы избежать разделителей, но вы не получаете преимуществ от использования List
. Не уверен, насколько это важно для 14, особенно с введением LazyVStack
, который откладывает инициализацию будущих строк до тех пор, пока они не понадобятся для отображения пользователю. Кроме того, улучшения анимации могут сделать обновления строк более естественными. Использование LazyVGrid
, конечно, возможно и в 14 с дополнительными преимуществами.
В этом году Apple представила новый модификатор .listRowSeparator
, который можно использовать для стилизации разделителей. вы можете передать .hidden
, чтобы скрыть это:
List {
ForEach(items, id:\.self) {
Text("Row \($0)")
.listRowSeparator(.hidden)
}
}
вместо этого вы можете рассмотреть возможность использования LazyVStack
внутри ScrollView
(поскольку iOS НЕТ больше не поддерживает UIAppearance
для списков SwiftUI).
⚠️ This method is deprecated and it's not working from iOS 14
За SwiftUI стоит UITableView
для iOS 13. Поэтому, чтобы удалить
вам нужен List
и удалить
вам нужно tableFooterView
быть separatorStyle
init() {
if #available(iOS 14.0, *) {
// iOS 14 doesn't have extra separators below the list by default.
} else {
// To remove only extra separators below the list:
UITableView.appearance().tableFooterView = UIView()
}
// To remove all separators including the actual ones:
UITableView.appearance().separatorStyle = .none
}
var body: some View {
List {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
}
Обратите внимание, что в статическом списке по умолчанию не отображаются дополнительные разделители под списком.
спасибо, это работает, и вы также можете добавить это в .onAppear
UITableView.appearance().separatorStyle = .none
странным образом у меня не работает, тоже не .introspectTableView { tableView in tableView.separatorStyle = .none }
(с SwiftUI-Introspect
...)
Какая версия iOS?
Разработчики iOS 14, использующие формы, которые хотят, чтобы в одном разделе не было разделителей между определенными элементами, но сохранялись разделители в других областях одного и того же представления: просто используйте LazyVStack вокруг представлений, в которых вы хотите, чтобы не было разделительных линий.
Просто отметим, что очень важно убедиться, что .listRowSeparator(.hidden)
является внутриList
.
Спасибо. Это сработало.
Не могли бы вы обновить описание в разделе «iOS 14» здесь? > вместо этого вы можете рассмотреть возможность использования LazyVStack внутри ScrollView (поскольку iOS больше НЕ поддерживает внешний вид для списков SwiftUI). // Раздел «iOS 15» выше, кажется, противоречит этому. Судя по всему, iOS продолжит поддерживать внешний вид списков SwiftUI?
Проверьте SwiftUI-Интроспект. Он предоставляет базовые представления UIKit/AppKit.
В этом случае вы можете напрямую манипулировать UITableView (без необходимости изменять все представления таблицы через прокси-сервер внешнего вида):
import Introspect
:
:
List {
...
}.introspectTableView { tableView in
tableView.separatorStyle = .none
}
Да, это больше не работает в сборках iOS 14. В зависимости от вашего варианта использования вы можете попробовать SidebarListStyle
скрыть разделители: .listStyle(SidebarListStyle())
Делать что-то вроде:
UITableView.appearance().separatorColor = .clear
работает, но во многих случаях это не то, что я бы рекомендовал. Это глобальные изменения, т.е. они затронут экземпляры все UITableView. Это проблема, если у вас есть несколько UITableView, которым нужны разные стили. Или, если вы разрабатываете фреймворк, клиенты, использующие ваш фреймворк, также наследуют эти изменения!
Более безопасное решение состоит в том, чтобы нацеливаться только на UITableView, которые находятся внутри указанного контейнера. К счастью, appearance
API дает нам возможность быть конкретным:
UITableView.appearance(whenContainedInInstancesOf: [UIHostingController<YourSwiftUiViewHere>.self]).separatorColor = .clear
Во-первых, ваш код даже не скомпилируется, так как правильное имя appearance(whenContainedInInstancesOf:)
. В целом, однако, это звучит как лучший подход, действительно. К сожалению, это не сработало для меня. Я заменил глобальную перезапись внешнего вида (сработало, как и ожидалось) на целевую, и это не дало никакого эффекта...
@NeverwinterMoon, спасибо, что сообщили мне об опечатке! Я обновлю его сейчас. Я написал это прямо в переполнении стека, так что это плохо. У меня он работал для цвета разделителя, цвета фона ячейки и других свойств. не уверен, почему это не работает правильно для вас. Я могу только проверить иерархию представлений и проверить, что для вас перекрывает неправильный цвет. проверьте это для инспектора иерархии представлений developer.apple.com/library/archive/documentation/…
Использовать ScrollView?
Некоторое состояние, которое представляет ваш список
@State var menuItems: [String] = ["One", "Two", "Three"]
Петля SwiftUI
ForEach
внутри ScrollView
ScrollView {
ForEach(self.menuItems, id: \.self) { item in
Text(item)
}
}
Это правильное предложение, но ответ @Mojtaba Hosseini более полный, когда он также предлагает LazyVStack
внутри ScrollView
. Можно было бы пояснить здесь, в чем заключаются компромиссы при замене List на ScrollView — один из них исправлен с помощью LazyVStack
(iOS 14+), так что хотя бы не все ячейки инициализируются сразу, но вы все равно не получаете полное поведение повторного использования, которое List/UITableView даст вам, ни какой-либо другой стиль, когда первоначальный вопрос касался только сокрытия разделителя и явного упоминания ScrollView
была предпринята попытка.
Хотя эти ответы технически правильны, по моему опыту, они повлияют на List
или Form
глобально (во всем приложении).
Хакерский способ, который я нашел для решения этой проблемы, по крайней мере, в моем приложении, состоит в том, чтобы добавить следующий код в «основное» представление содержимого приложения:
.onAppear(perform: {
UITableView.appearance().separatorStyle = .none
})
Затем в любом другом представлении, которое вы хотите добавить в разделительные линии, добавьте это в конец представления List
или Form
.
.onAppear(perform: {
UITableView.appearance().separatorStyle = .singleLine
})
Это, кажется, добавляет разделитель одной строки к любому листу просмотра, который находится над основным видом контента. Опять же, все это не соответствует моему недавнему опыту работы со SwiftUI.
По моему опыту, мне нужно было только добавить метод .onAppear(... = .singleLine)
к одному из моих «подробных» представлений, и разделительная линия появлялась на всех последующих представленных представлениях.
Редактировать: Еще одно замечание, поскольку этот ответ продолжает привлекать внимание. Это решение, которое я опубликовал, не решает все случаи, оно, конечно, не решило это для меня, опять же, в некоторых случаях. В итоге я использовал Самоанализ для SwiftUI для решения этой проблемы во всем приложении.
Я надеюсь, что это прояснит некоторую путаницу и разочарование, когда люди наткнутся на этот пост.
iOS 14
В настоящее время нет решения скрыть разделители в бета-версии iOS 14.
Если вам не нужен редактируемый List
, вы должны использовать LazyVStack
внутри ScrollView
.
Но если вы хотите остаться на List
. Я нашел решение на форуме Apple от samwarner. https://developer.apple.com/forums/thread/651028
Это временное решение. В некоторых случаях вам может понадобиться настроить вставки. Вот его реализация:
struct HideRowSeparatorModifier: ViewModifier {
static let defaultListRowHeight: CGFloat = 44
var insets: EdgeInsets
var background: Color
init(insets: EdgeInsets, background: Color) {
self.insets = insets
var alpha: CGFloat = 0
UIColor(background).getWhite(nil, alpha: &alpha)
assert(alpha == 1, "Setting background to a non-opaque color will result in separators remaining visible.")
self.background = background
}
func body(content: Content) -> some View {
content
.padding(insets)
.frame(
minWidth: 0, maxWidth: .infinity,
minHeight: Self.defaultListRowHeight,
alignment: .leading
)
.listRowInsets(EdgeInsets())
.background(background)
}
}
extension EdgeInsets {
static let defaultListRowInsets = Self(top: 0, leading: 16, bottom: 0, trailing: 16)
}
extension View {
func hideRowSeparator(insets: EdgeInsets = .defaultListRowInsets, background: Color = .white) -> some View {
modifier(HideRowSeparatorModifier(insets: insets, background: background))
}
}
Наконец, вот реализация в списке. Вы должны добавить .hideRowSeparator()
в ячейку списка.
struct CustomRow: View {
let text: String
var body: some View {
HStack {
Text(self.text)
Image(systemName: "star")
}
}
}
struct ContentView : View {
@State private var fruits = ["Apple", "Orange", "Pear", "Lemon"]
var body: some View {
VStack(alignment: .leading) {
List {
ForEach(self.fruits, id: \.self) { str in
CustomRow(text: str)
.hideRowSeparator()
}
}
}
.padding(.top)
}
}
используя этот обходной путь, первая строка показывает разделитель сверху
...отличный модификатор, большое спасибо. Если вы делаете пользовательскую ячейку смахивания, вы можете установить .listRowBackground(background)
в дополнение к существующему .background(background)
в теле HideRowSeparatorModifiers...
@JAHelia да, у меня такая же проблема
Я начал проект, чтобы решить эту проблему в iOS14, так как обходные пути iOS 13 больше не работают. Он позволяет установить стиль разделителя, цвет разделителя и вставку разделителя.
Скрыть разделители в списке
List { <content> }
.listSeparatorStyle(.none)
Показать одну разделительную линию с настраиваемым цветом и вставками
List { <content> }
.listSeparatorStyle(.singleLine, color: .red, inset: EdgeInsets(top: 0, leading: 50, bottom: 0, trailing: 20)
https://github.com/SchmidtyApps/SwiftUIListSeparator
если вы примените фон, все разделители снова появятся
Все ответы говорят вам использовать ScrollView (что я тоже рекомендую)
Но если вы хотите использовать список и хотите удалить разделительные строки..
Установите SwiftPM: https://github.com/siteline/SwiftUI-Интроспект
ОБРАЗЕЦ:
List {
Text("Item 1")
Text("Item 2")
}
.introspectTableView { tableView in
tableView.separatorStyle = .none
}
Это мое расширение ListRowExtensions для разделителя строк списка Спрятать и обычай для этого.
import SwiftUI
// MARK: List row extensions
extension View {
func hideListRowSeparator() -> some View {
return customListRowSeparator(insets: .init(), insetsColor: .clear)
}
func customListRowSeparator(
insets: EdgeInsets,
insetsColor: Color) -> some View {
modifier(HideRowSeparatorModifier(insets: insets,
background: insetsColor
)) .onAppear {
UITableView.appearance().separatorStyle = .none
UITableView.appearance().separatorColor = .clear
}
}
}
// MARK: ViewModifier
private struct HideRowSeparatorModifier: ViewModifier {
var insets: EdgeInsets
var background: Color
func body(content: Content) -> some View {
content
.padding(insets)
.frame(
minWidth: 0,
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .leading
)
.listRowInsets(EdgeInsets())
.background(background)
}
}
Использовать :
// Without list row separator
List {
ForEach(self.viewModel.data, id: \.id) { item in
Text("Text")
}
.hideRowSeparatorItemList()
}
// With list row separator with color and size
List {
ForEach(self.viewModel.data, id: \.id) { item in
Text("Text")
}
.customListRowSeparator(insets: EdgeInsets(top: 0,
leading: 0,
bottom: 5,
trailing: 0),
insetsColor: Color.red)
}
Я не уверен, нужны ли вам все функции «UITableView» в SwiftUI, но если вы просто хотите просто отобразить список представлений в iOS 13 или более поздней версии, не могли бы вы просто сделать:
ScrollView {
VStack(alignment: .leading) {
ForEach(1...10) { _ in
CustomRow()
}
}
}
А затем добавьте .padding()
для любых полей, которые вы хотите?
Удалить отступы и разделитель
iOS 14.2, Xcode 12.2
ScrollView {
LazyVStack {
ForEach(viewModel.portfolios) { portfolio in
PortfolioRow(item: portfolio)
}
}
}
Это дает вам полный контроль над списком. Текущая реализация List не обеспечивает полного контроля и содержит некоторые проблемы.
Хороший! Работает как шарм.
Это работает, но не позволяет вам иметь плавающие заголовки Section
, как если бы вы использовали List
или UITableView
.
Для iOS 14 у вас есть это:
.listStyle(SidebarListStyle()) # IOS 14
Спасибо, что указали на это. Он удалил разделитель и стрелку раскрытия, но теперь добавляет серый фон, который я не могу удалить. Есть ли способ изменить фон? Зачем Apple все так усложняет?...
@Эмиль, я не знаю :)
Вы можете удалить разделители, установив для listStyle значение InsetListStyle()
, например:
.listStyle(InsetListStyle())
Добавьте это в конец вашего кода
Кажется, это единственное, что работает для меня.
List() {
}
.listStyle(SidebarListStyle())
Отличный ответ для тех, кто делает боковое меню из List
Простое решение, которое будет работать как на iOS 13, так и на 14.
extension List {
func removeSeparator() -> some View {
if #available(iOS 14.0, *) {
return self.listStyle(SidebarListStyle()).erasedToAnyView()
} else {
return self.onAppear {
UITableView.appearance().separatorStyle = .none
}.erasedToAnyView()
}
}
Можно просто использовать негативные вставки и сплошной цвет, чтобы замаскировать разделитель.
У меня та же проблема. Но я знаю самодельное решение для этого. Итак, если вы установите параметры строки списка, например:
.listRowInsets(EdgeInsets(top: -5, leading: 0, bottom: 0, trailing: 0))
и заполнение тела представления строки, например
.padding(EdgeInsets(top: Statics.adjustValue(v: 10), leading: Statics.adjustValue(v: 10), bottom: Statics.adjustValue(v: 10), trailing: Statics.adjustValue(v: 10)))
тогда разделители будут скрыты.
ДЛЯ ВСЕХ ВЕРСИЙ iOS
Что такое Statics.adjustValue?
Метод Statics.adjustValue() является регулятором размера по плотности экрана.
extension View {
func hideRowSeparator(insets: EdgeInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0),
background: Color = .white) -> some View {
modifier(HideRowSeparatorModifier(insets: insets, background: background))
}
}
struct HideRowSeparatorModifier: ViewModifier {
static let defaultListRowHeight: CGFloat = 44
var insets: EdgeInsets
var background: Color
init(insets: EdgeInsets, background: Color) {
self.insets = insets
var alpha: CGFloat = 0
if #available(iOS 14.0, *) {
UIColor(background).getWhite(nil, alpha: &alpha)
assert(alpha == 1, "Setting background to a non-opaque color will result in separators remaining visible.")
}
self.background = background
}
func body(content: Content) -> some View {
content
.padding(insets)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: Self.defaultListRowHeight)
.listRowInsets(EdgeInsets())
.overlay(
VStack {
HStack {}
.frame(maxWidth: .infinity)
.frame(height: 1)
.background(background)
Spacer()
HStack {}
.frame(maxWidth: .infinity)
.frame(height: 1)
.background(background)
}
.padding(.top, -1)
)
}
}
struct ContentView: View {
var body: some View {
List {
ForEach(0 ..< 30) { item in
HStack(alignment: .center, spacing: 30) {
Text("Hello, world!:\(item)").padding()
}
.hideRowSeparator(background: .white)
}
}
.listStyle(PlainListStyle())
}
}
Для iOS 14:
Поскольку .listRowSeparator(.hidden)
доступен только для iOS 15, вы можете скрыть разделитель в более ранних версиях, явно установив значение edgeinsets равным 0.
Просмотр содержимого:
List {
ForEach(viewModel.items, id: \.id) { item in
YourListItem(item)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}
Сопровождайте вышеуказанное изменение, сделав фон элемента строки белым (или цветом корневой страницы).
Элемент строки:
var body: some View {
VStack {
..... your content
}
.background(Colors.white)
}
VStack — это просто пример. Это может быть любой компонент.
Это мое решение, которое содержит все соображения:
let style: UITableViewCell.SeparatorStyle
public func body(content: Content) -> some View {
content
.introspectTableView { tableView in
tableView.separatorStyle = .none
}
}
}
public extension View {
func listSeparator(style: UITableViewCell.SeparatorStyle) -> some View {
ModifiedContent(content: self, modifier: ListSeparatorStyle(style: style))
}
}
Реализовано:
List {
// code...
}
.listSeparator(style: .none)
Можете ли вы завершить начало кода?
Чтобы удалить разделитель строк в SwiftUI, вы можете настроить представление List
, присоединив модификатор onAppear
и вызвать API внешнего вида UITableView
, чтобы отключить разделитель строк:
.onAppear {
UITableView.appearance().separatorStyle = .none
}
С помощью этого кода все разделители строк списка должны быть удалены.
Возможный дубликат Удалите лишние разделители под списком в SwiftUI