小部件在表视图swift ios的单元格中彼此重叠

时间:2018-05-10 10:23:34

标签: ios swift uitableview nsindexpath

我根据数组textField中提供的元素在表视图的单元格中获取小部件textViewwidgetInstockArray。 并从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


根据THIS ANSWER

更新

如果我想在点击按钮上添加小部件,那么每次点击都应该添加小部件。

这就是我所做的

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 :(得分:4)

问题

1)您正在以编程方式添加子视图。因为单元格被重用,所以每次都要创建TextField和TextView

2)我在代码中看到的另一个问题是i.contains(wTextField)
 由于i.contains(wTextView)wTextField都在数组wTextView中且两个框架都是widgetInstockArray,所以CGRect(x: 10, y: 10, width: 200, height: 30)始终为真,因此您将重叠< / strong>

更好的解决方案是使用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时,其他元素会自动相应地设置

希望它有用,请在查询的情况下告诉我

<强>更新

不相关但是保留两个数组以填充tableview不是一个好习惯,这可能会对将来的更新代码造成问题。

更好的解决方案是创建structclass

喜欢

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

现在您可以创建StockArray数组,并且很容易维护

宾果!

答案 1 :(得分:2)

this answer中所述:

  • 每次表格视图请求单元格时,都会创建一个新的文本字段/文本视图
  • 在创建单元格时循环 widgetInStockArray 将导致多个文本字段和文本视图添加到该单元格

可以按照以下方式重新构建和改进问题中的示例代码,以获得所需的结果。

重组股票信息

定义两种类型,以便更方便地访问单个库存项目的ID,标签和小部件。

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
}

答案 2 :(得分:1)

如果我理解您的代码/需要正确,添加子视图是重叠的问题。 多次添加子视图是问题

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类似。