Виджеты перекрывают друг друга в ячейках табличного представления swift ios - PullRequest
0 голосов
/ 10 мая 2018

Я получаю виджеты либо textField, либо textView в ячейках табличного представления на основе предоставленных элементов в массиве widgetInstockArray. И получение заполнителя для виджетов от labelInstcokArray

Проблема: Ячейка появляется с перекрытием обоих виджетов, textField заключен в textView на каждую ячейку.

Что я хочу: в каждой ячейке должен быть textField или textView, но не оба должны быть одновременно вложенными и перекрытыми.

Вот что я сделал до сих пор:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {

var widgetInstockArray = [String]()
var labelInstockArray = [String]()
var idInstockArray = [IntegerLiteralType]()
var newLabel = UITextField()
var newTextView = UITextView()
let wTextField = "textField"
let wTextView = "textView"

@IBOutlet weak var firstTableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
    widgetInstockArray = [wTextView, wTextField, wTextView, wTextField, wTextField, wTextView, wTextField]
    idInstockArray = [1,2,3,4,5,6,7]
    labelInstockArray = ["1ok","2ok","3ok","4ok","5ok","6ok","7ok"]
    firstTableView.delegate = self
    firstTableView.dataSource = self
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return widgetInstockArray.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 60
}

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var Cell : UITableViewCell?

        var instockTag : Int = 1
        Cell = firstTableView.dequeueReusableCell(withIdentifier: "firstCell")! as UITableViewCell
        if widgetInstockArray.count == 0 && labelInstockArray.isEmpty {
            print("no textFields in instock")
        }
        else {
            print("widget process i in winstock loop")
            for i in widgetInstockArray {
                print("widget process i in winstock loopok so here is \(i)")
                let indexOfA = widgetInstockArray.index(of: i)
                print("her is the index of i of widgets \(String(describing: indexOfA))")
                if i.contains(wTextField)  {
                    print("textField was placed")
                    newLabel = UITextField(frame: CGRect(x: 10, y: 10, width: 200, height: 30))
                    newLabel.textColor = UIColor.gray
                    newLabel.tag = instockTag
                    print("You have a instock textLabel with tag \(newLabel.tag)")
                    if labelInstockArray.isEmpty || idInstockArray.count != labelInstockArray.count {
                        newLabel.text = " "
                    } else {
                        newLabel.placeholder = labelInstockArray[indexPath.row]
                        newLabel.layer.cornerRadius = 3
                        newLabel.layer.borderColor = UIColor.gray.cgColor
                        newLabel.layer.borderWidth = 1
                        instockTag += 1
                        print("\(widgetInstockArray.count)")
                        Cell?.contentView.addSubview(newLabel)
                    }
                }

                if i.contains(wTextView) {
                    print("textView was placed")
                    newTextView = UITextView(frame: CGRect(x:10, y: 10, width: 200, height: 60))
                    newTextView.textAlignment = NSTextAlignment.justified
                    newTextView.textColor = UIColor.black
                    newTextView.backgroundColor = UIColor.white
                    newTextView.font = UIFont.systemFont(ofSize: 15)
                    newTextView.tag = instockTag
                    print("You have a instock textView with tag \(newTextView.tag)")
                    if labelInstockArray.isEmpty || idInstockArray.count != labelInstockArray.count {
                    } else {
                        //newTextView.text = labelInstockArray[indexPath.row]
                        newTextView.layer.cornerRadius = 3
                        newTextView.layer.borderColor = UIColor.gray.cgColor
                        newTextView.layer.borderWidth = 1
                        instockTag += 1
                        print("\(widgetInstockArray.count)")
                        Cell?.contentView.addSubview(newTextView)
                    }
                }
            }
            print("could not add widgets")
        }
    return Cell!
    }

func textViewDidBeginEditing(_ textView: UITextView) {
    if newTextView.textColor == UIColor.lightGray {
        newTextView.text = nil
        newTextView.textColor = UIColor.black
    }
}

func textViewDidEndEditing(_ textView: UITextView) {
    if newTextView.text.isEmpty {
        for i in labelInstockArray {
        newTextView.text = i
        }
        newTextView.textColor = UIColor.lightGray
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

Выход перекрывается :(
TextFiled находится внутри textview, оба появляются в одной ячейке. Но я хочу, чтобы они не перекрывались, и в каждой ячейке должен быть только один виджет.

enter image description here


ОБНОВЛЕНИЕ согласно ЭТОТ ОТВЕТ

Что, если я хочу добавить виджеты по нажатию кнопки, чтобы вживую виджеты добавлялись при каждом нажатии.

вот что я сделал

var idWidgetIs = IntegerLiteralType()
var labelWidget = String()
var widgetName = String()

let stockArray: [StockItem] = [ StockItem(id: idWidgetIs, label: labelWidget, widget: widgetName)]

    @IBAction func textViewAct(_ sender: Any) {
    idWidgetIs += 1
    labelWidget = "placeholder"
    StockItem.init(id: idWidgetIs, label: labelWidget, widget: .textView)
    }

    @IBAction func textFieldAct(_ sender: Any) {
    idWidgetIs += 1
    labelWidget = "placeholder"
    StockItem.init(id: idWidgetIs, label: labelWidget, widget: .textField)
   }

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Если я правильно понимаю ваш код / ​​необходимость, добавление подпредставления является проблемой , а не для перекрытия. Добавление подпредставлений несколько раз - это проблема

for i in widgetInstockArray { в методе cellForRowAt проблема. В основном для каждой ячейки вы просматриваете (7 times = 3 for wTextView and 4 for wTextField), что означает, что вы добавляете представление поверх представления.

Предложение: удалить for i in widgetInstockArray { и

 let i = widgetInstockArray[indexPath.row]

и сравните, используя

 if i == wTextField {

и аналогично для wTextView.

0 голосов
/ 20 мая 2018

Как указано в этот ответ :

  • каждый раз, когда табличное представление запрашивает ячейку, создается новое текстовое поле / текстовое представление
  • цикл по widgetInStockArray при создании ячейки приведет к добавлению нескольких текстовых полей и текстовых представлений в эту ячейку

Пример кода из вопроса может быть изменен и улучшен следующим образом для достижения желаемого результата.


Информация о реструктуризации

Определите два типа для более удобного доступа к идентификатору, метке и виджету одного элемента товара.

enum StockWidget: String {
    case textField
    case textView
}

struct StockItem {
    let id: IntegerLiteralType
    let label: String
    let widget: StockWidget
}

Обновите данные образца соответствующим образом.

let stockArray: [StockItem] = [
    StockItem(id: 1, label: "1ok", widget: .textView),
    StockItem(id: 2, label: "2ok", widget: .textField),
    StockItem(id: 3, label: "3ok", widget: .textView),
    StockItem(id: 4, label: "4ok", widget: .textField),
    StockItem(id: 5, label: "5ok", widget: .textField),
    StockItem(id: 6, label: "6ok", widget: .textView),
    StockItem(id: 7, label: "7ok", widget: .textField)
]

Определить конкретные ячейки

Один с UITextField:

class TextFieldWidgetCell: UITableViewCell {

    let textField: UITextField

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        let field = UITextField(frame: CGRect(x: 10, y: 10, width: 200, height: 30))
        field.layer.borderColor = UIColor.gray.cgColor
        field.layer.borderWidth = 1.0
        field.layer.cornerRadius = 3.0
        field.textColor = UIColor.gray
        textField = field

        super.init(style: style, reuseIdentifier: reuseIdentifier)

        contentView.addSubview(textField)
    }

    override func prepareForReuse() {
        super.prepareForReuse()

        textField.placeholder = nil
        textField.text = nil
    }

}

и один с UITextView:

class TextViewWidgetCell: UITableViewCell {

    let textView: UITextView

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        let view = UITextView(frame: CGRect(x:10, y: 10, width: 200, height: 60))
        view.backgroundColor = UIColor.white
        view.font = UIFont.systemFont(ofSize: 15)
        view.layer.borderColor = UIColor.gray.cgColor
        view.layer.borderWidth = 1.0
        view.layer.cornerRadius = 3.0
        view.textAlignment = NSTextAlignment.justified
        view.textColor = UIColor.black
        textView = view

        super.init(style: style, reuseIdentifier: reuseIdentifier)

        contentView.addSubview(textView)
    }

    override func prepareForReuse() {
        super.prepareForReuse()

        textView.text = nil
    }

}

Зарегистрируйте ячейки виджета в табличном представлении.

override func viewDidLoad() {
    super.viewDidLoad()

    firstTableView.dataSource = self
    firstTableView.delegate = self

    firstTableView.register(TextFieldWidgetCell.self, forCellReuseIdentifier: StockWidget.textField.rawValue)
    firstTableView.register(TextViewWidgetCell.self, forCellReuseIdentifier: StockWidget.textView.rawValue)
}

Адаптировать UITableViewDataSource Реализация

Теперь, когда конфигурация ячейки разделена на два UITableViewCell подкласса, реализация tableView(_, cellForRowAt:) может быть значительно уменьшена.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return stockArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let stockItem = stockArray[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: stockItem.widget.rawValue)

    switch stockItem.widget {
    case .textField:
        if let cell = cell as TextFieldWidgetCell {
            cell.textField.placeholder = stockItem.label
        }
    case .textView:
        if let cell = cell as TextViewWidgetCell {
            cell.textView.text = stockItem.label
        }
    }

    return cell
}
0 голосов
/ 14 мая 2018

Проблемы

1) Вы программно добавляете подпредставление.как ячейка используется повторно, так что вы создаете TextField и TextView Каждый раз

2) Еще одна проблема, которую я вижу в вашем коде, это i.contains(wTextField)
и i.contains(wTextView), которые будутвсегда true, поскольку оба значения wTextField и wTextView находятся в массиве widgetInstockArray, а оба кадра - CGRect(x: 10, y: 10, width: 200, height: 30), поэтому вы получаете перекрытие


Лучшее решение - использовать UIStackView

Создание пользовательской ячейки с UIStackview

Теперь добавьте Один UITextField и один UITextView к UIStackview.

Теперь следующий шаг в cellForRow Метод.Просто скройте другой элемент, например

if i == wTextField  { 
  cell.wTextView.isHidden = true
   cell.wTextField.isHidden = false

} else {
  cell.wTextField.isHidden = true
  cell.wTextView.isHidden = false

}

Когда вы скрываете один из видов в UIStackView, автоматически устанавливается соответствующий другой элемент

Надеюсь, что это полезно, пожалуйста, дайте мне знать в случае запросов

ОБНОВЛЕНИЕ

Не связано, но не рекомендуется хранить два массива для заполнения таблицы, это может быть проблематично для будущего обновления кода.

Лучшее решениебыло бы создать struct или class

Как

enum Widget {
    case TextField
    case TextView
}
struct StockArray {
    var type : Widget
    var labelInstockArray = [String]()
    var idInstockArray = [IntegerLiteralType]()
}

Теперь Вы можете создать массив StockArray, и его очень легко поддерживать

Бинго!!!

...