Я рассматриваю, как создать список SwitUI, в качестве строки которого используются пользовательские UIViews.
Я создаю список:
List {
RowView()
}
RowView - это UIViewRepresentable для UIRowView
struct RowView : UIViewRepresentable {
func makeUIView() -> UIRowView { ... }
}
UIRowView - это настраиваемое представление
UIRowView: UIView { ... }
В настоящее время первые строки являются отображаются, но обычно они не имеют правильного расположения, и при прокрутке эти представления исчезают, а не перерабатываются
ОБНОВЛЕНИЕ
Пример 1
struct NoteView: UIViewRepresentable {
// MARK: - Properties
let note: Note
let date = Date()
func makeUIView(context: Context) -> UINoteView {
let view = UINoteView()
view.note = note
return view
}
func updateUIView(_ uiView: UINoteView, context: Context) {
uiView.note = note
print("View bounds: \(uiView.bounds)")
}
}
var body: some View {
List {
ForEach(Array(notes.enumerated()), id: \.1) { (i, note) in
NoteView(note: note)
.background(Color.green)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}.background(Color.red)
}
Пример 2 - Упрощенный
struct TestView : UIViewRepresentable {
let text : String
func makeUIView(context: Context) -> UILabel {
UILabel()
}
func updateUIView(_ uiView: UILabel, context: Context) {
uiView.text = text
}
}
var body: some View {
List {
ForEach(0..<30, id: \.self) { i in
TestView(text: "\(i)")
}
}
}
Кажется, что оба работают неправильно, так как строки исчезают. У меня также были проблемы с представлениями, не сохраняющими отступы и выходящими за пределы экрана, если было больше контента. Только несколько первых строк (видны изначально на макетах экрана правильно), другие исчезают или куда-то прыгают.
ОБНОВЛЕНИЕ 2
Вот Autosizable UINoteView
class UINoteView: UIView {
// MARK: - Init
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupViews()
}
// MARK: - Properties
var note: Note? {
didSet {
textView.attributedText = note?.content?.parsedHtmlAttributedString(textStyle: .html)
noteFooterViewModel.note = note
}
}
// MARK: - Views
lazy var textView: UITextView = {
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.backgroundColor = UIColor.yellow
textView.textContainer.lineBreakMode = .byWordWrapping
textView.textContainerInset = .zero
textView.textContainer.lineFragmentPadding = 0
textView.isScrollEnabled = false
textView.isSelectable = true
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.textContainer.maximumNumberOfLines = 0
return textView
}()
lazy var label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "TEST ROW \(note?.id ?? "")"
return label
}()
lazy var vStack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [
textView,
noteFooter
])
stack.axis = .vertical
stack.alignment = .fill
stack.distribution = .fill
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
var noteFooterViewModel = NoteFooterViewModel()
var noteFooter: UIView {
let footer = NoteFooter(viewModel: noteFooterViewModel)
let hosting = UIHostingController(rootView: footer)
hosting.view.translatesAutoresizingMaskIntoConstraints = false
return hosting.view
}
private func setupViews() {
self.backgroundColor = UIColor.green
self.addSubview(vStack)
NSLayoutConstraint.activate([
vStack.leadingAnchor.constraint(equalTo: self.leadingAnchor),
vStack.trailingAnchor.constraint(equalTo: self.trailingAnchor),
vStack.topAnchor.constraint(equalTo: self.topAnchor),
vStack.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
}