SwiftUI, как создать список с пользовательскими UIViews внутри него - PullRequest
0 голосов
/ 24 марта 2020

Я рассматриваю, как создать список 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)")
        }
    }
}

Кажется, что оба работают неправильно, так как строки исчезают. У меня также были проблемы с представлениями, не сохраняющими отступы и выходящими за пределы экрана, если было больше контента. Только несколько первых строк (видны изначально на макетах экрана правильно), другие исчезают или куда-то прыгают.

enter image description hereenter image description here

ОБНОВЛЕНИЕ 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)
        ])
    }

}

1 Ответ

1 голос
/ 24 марта 2020

ОБНОВЛЕННЫЙ ОТВЕТ попробуйте это:

struct TestView : UIViewRepresentable {

    let text : String

    var label : UILabel = UILabel()

    func makeUIView(context: Context) -> UILabel {

        return label
    }

    func updateUIView(_ uiView: UILabel, context: Context) {
        uiView.text = text
    }
}



struct ContentView : View {

    var body: some View {

        List (0..<30, id: \.self) { i in
            TestView(text: "\(i)").id(i)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
...