UICollectionViewCell 的 UiTextField,在 UICollectionViewController 中重叠

Posted

技术标签:

【中文标题】UICollectionViewCell 的 UiTextField,在 UICollectionViewController 中重叠【英文标题】:UICollectionViewCell's UiTextField, overlapping in UICollectionViewController 【发布时间】:2017-12-24 14:48:46 【问题描述】:

我正在尝试设计一个多步骤注册菜单。为此,我将 UICollectionViewController 与屏幕大小的单元格一起使用。在这些单元格中,我有一个 UITextView 来提问和一个 UITextField 来收集答案。我还有一个 Page 对象,用于在设置时从 uicollectionviewcontroller 传递信息。 我现在遇到的问题是,在每 3 页之后,我从 3 页之前的 textField 输入重复,而不是显示占位符。我注意到另一个问题,单元格似乎只实例化了 3 次,而不是我有多少页的 6 次。实例化顺序也很奇怪。起初它会执行一次,然后单击按钮,再执行两次,然后再也不执行了。 如何解决这个问题,我真的很挣扎,我不知道出了什么问题。

这是我的代码:

import UIKit

class OnboardingPageViewCell: UICollectionViewCell

    override init(frame: CGRect) 
        super.init(frame: frame)
        print("made a page")
        setupView()
    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    var oboardingPage = NewOnboardingPage() 
        didSet
            reload()
        
    

    private var questionTextField: UITextView = 
        var q = UITextView()
        q.textColor = UIColor.white
        q.textAlignment = .left
        q.font = UIFont(name: "Avenir-Black", size: 25)
        q.isEditable = true
        q.isScrollEnabled = false
        q.backgroundColor = UIColor.black
        q.translatesAutoresizingMaskIntoConstraints = false
        print("made aquestion field")
        return q
    ()

    private var answerField : CustomTextField = 
        let tf = CustomTextField.nameField
        print("made an answer field")
        return tf
    ()

    private func setupView()
        backgroundColor = UIColor.white

        addSubview(questionTextField)
        questionTextField.topAnchor.constraint(equalTo: topAnchor, constant: 120).isActive = true
        questionTextField.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        questionTextField.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.90).isActive = true
        questionTextField.heightAnchor.constraint(equalToConstant: 90).isActive = true

        addSubview(answerField)
        answerField.topAnchor.constraint(equalTo: questionTextField.bottomAnchor, constant: 20).isActive = true
        answerField.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        answerField.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.90).isActive = true
        answerField.heightAnchor.constraint(equalToConstant: 90).isActive = true
    

    private func reload()
        questionTextField.text = oboardingPage.question
        answerField.placeholder = oboardingPage.answerField
    


class NewOnboardingPage 
    var question : String?
    var answerField : String?



import UIKit

class SignUpController: UICollectionViewController, UICollectionViewDelegateFlowLayout 

    private let cellId = "cellId"
    private var pages = [NewOnboardingPage]()

    override func viewDidLoad() 
        super .viewDidLoad()
        setupSignUpControllerView()
        addPages()
    

    private  func addPages()
        let namePage = NewOnboardingPage()
        namePage.question = "What's your name?"
        namePage.answerField = "What's your name?"
        pages.append(namePage)

        let birthDayPage = NewOnboardingPage()
        birthDayPage.question = "When's your birthdate?"
        birthDayPage.answerField = "When's your birthdate?"
        pages.append(birthDayPage)

        let userNamePage = NewOnboardingPage()
        userNamePage.question = "Choose a user name."
        userNamePage.answerField = "Choose a user name."
        pages.append(userNamePage)

        let passWordPage = NewOnboardingPage()
        passWordPage.question = "Set a password"
        passWordPage.answerField = "Set a password"
        pages.append(passWordPage)

        let emailAuthPage = NewOnboardingPage()
        emailAuthPage.question = "What's your email?"
        emailAuthPage.answerField = "What's your email?"
        pages.append(emailAuthPage)

        let phoneNumberPage = NewOnboardingPage()
        phoneNumberPage.question = "What's your phone number?"
        phoneNumberPage.answerField = "What's your phone number?"
        pages.append(phoneNumberPage)
    

    private func setupSignUpControllerView()
        collectionView?.backgroundColor = .white
        collectionView?.register(OnboardingPageViewCell.self, forCellWithReuseIdentifier: cellId)
        collectionView?.isPagingEnabled = true
        collectionView?.isScrollEnabled = true

        if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout 
            layout.scrollDirection = .horizontal
            layout.minimumLineSpacing = 0
        

        view.addSubview(nextButton)
        nextButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 400).isActive = true
        nextButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        nextButton.widthAnchor.constraint(equalToConstant: 250).isActive = true
        nextButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
    

    private let nextButton: UIButton = 
        let button = UIButton(type: .system)
        button.backgroundColor = UIColor.RED
        button.setTitle("next", for: .normal)
        button.setTitleColor(UIColor.white, for: .normal)
        button.titleLabel?.font = UIFont(name: "Avenir-Black", size: 25)
        button.layer.cornerRadius = 30
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(turnNextPage), for: .touchUpInside)
        return button
    ()

    @objc private func turnNextPage() 
        let visibleItems: NSArray = collectionView?.indexPathsForVisibleItems as! NSArray
        let currentItem: IndexPath = visibleItems.object(at: 0) as! IndexPath
        let nextItem: IndexPath = IndexPath(item: currentItem.item + 1, section: 0)
        if nextItem.row < pages.count 
            collectionView?.scrollToItem(at: nextItem, at: .left, animated: true)
        
    

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return pages.count
    

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! OnboardingPageViewCell
        cell.oboardingPage = pages[indexPath.item]
        return cell
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        return CGSize(width: view.frame.width, height: view.frame.height)
    




import UIKit

class CustomTextField: UITextField, UITextFieldDelegate 
convenience init() 
        self.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

        self.allowsEditingTextAttributes = false
        self.autocorrectionType = .no

        self.tintColor = UIColor.RED
        self.translatesAutoresizingMaskIntoConstraints = false
    


    override func willMove(toSuperview newSuperview: UIView?) 
        addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        editingChanged(self)
    

    @objc func editingChanged(_ textField: UITextField) 
        guard let text = textField.text else  return 
        textField.text = String(text.prefix(30))
    

    override func selectionRects(for range: UITextRange) -> [Any] 
        return []
    

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
        if action == #selector(paste(_:)) ||
            action == #selector(cut(_:)) ||
            action == #selector(copy(_:)) ||
            action == #selector(select(_:)) ||
            action == #selector(selectAll(_:))
            return false
        
        return super.canPerformAction(action, withSender: sender)
    




override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! OnboardingPageViewCell
        cell.answerField.text = nil
        cell.oboardingPage = pages[indexPath.item]
        return cell
    

【问题讨论】:

【参考方案1】:

1- textFeild 显示相同的数据而不是 placeholder 因为单元格出队所以你必须挂钩这些属性并清除它们在 cellForRowAt 中的内容/p>

2- 实例化是 3 而不是 6 aslo cell dequeuing

解决:

将两个属性添加到您的模型 NewOnboardingPage 将它们命名为 currentQuestion 和 currentAnswer,并在用户输入并滚动到下一页时将它们保存在模型数组中,您应该将它们设为全局,以便在单元格内部和外部集合中访问当您在 cellForRowAt 中滚动时,将这些值添加到 textfeildtextView

【讨论】:

你的意思是 cellForItemAt?所以像这样吧,(最后编辑)?这有帮助,谢谢。我不知道出队。但问题是,现在我以前的数据被删除了,所以如果用户决定向后滑动并查看输入的内容,那一切都消失了。如何让它再次显示? 当用户点击下一页时获取textfeild和textview的当前内容并存储在模型数组的相应索引中,当他点击返回时重新加载表格 顺便说一句,为什么其他所有东西都出队了,但是 textField 呢?毕竟,我使用的是 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) 作为! OnboardingPageViewCell 您可能会在 cellForRowAt 中刷新它的占位符

以上是关于UICollectionViewCell 的 UiTextField,在 UICollectionViewController 中重叠的主要内容,如果未能解决你的问题,请参考以下文章

向 UICollectionViewCell 添加圆角和阴影

XCTest 与自定义 UICollectionViewCell

将 UIViewController 添加到 UICollectionViewCell

动画后 UICollectionViewCell 位置错误

在情节提要中设计 UICollectionViewCell

滚动时大型 UICollectionViewCell 停止显示