Swift CollectionViewCell具有与其CollectionView不同的框架

时间:2019-10-04 10:19:39

标签: ios swift uicollectionview uicollectionviewflowlayout

我有一个CollectionView,它已填满整个屏幕,具有水平scrollDirection并启用了分页。它位于带有隐藏的NavigationController的{​​{1}}内部。 navigationBar也具有屏幕的高度。

我期望发生的事情:
每个单元格将填满整个屏幕,当我向左/向右滑动时,将出现另一个单元格并填满整个屏幕。

实际发生的情况:
单元格未填满整个屏幕。单元格的顶部和屏幕的顶部边框之间有一个很小的空间(大约20像素)。单元格的底部(也大约20像素)位于屏幕底部边框的下方。
我也收到警告:

  

由于以下原因,未定义UICollectionViewFlowLayout的行为:
  项目高度必须小于UICollectionView的高度减去该部分可插入的顶部和底部值,再减去内容可插入的顶部和底部值。

因此,像元高度看起来正确,但是y值错误。

我已经尝试过的方法: CollectionViewCells返回true。

您会看到here,蓝色边框是collectionView的边框,红色边框是单元格的边框。正如我所期望的那样,蓝色边框是,但我希望红色边框像蓝色边框一样。

代码如下:

override shouldInvalidateLayoutForBoundsChange

PageCell:

class LoginController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, LoginControllerDelegate, UIGestureRecognizerDelegate {

    lazy var loginCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal 
        layout.minimumLineSpacing = 0
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.dataSource = self
        cv.delegate = self
        cv.isPagingEnabled = true
        cv.layer.borderWidth = 1.0
        cv.layer.borderColor = UIColor.blue.cgColor
        return cv
    }()

    let introCellId = "IntroCellId"
    let loginCellId = "LoginCellId"

    let pages: [Page] = {
        let firstPage = Page(title: String,
                             message: String,
                             imageName: String)

        let secondPage = Page(title: String,
                             message: String,
                             imageName: String)

        let thirdPage = Page(title: String,
                             message: String,
                             imageName: String)

        return [firstPage, secondPage, thirdPage]
    }()

    override func viewDidLoad() {        
        super.viewDidLoad()

        navigationController?.navigationBar.isHidden = true

        view.addSubview(loginCollectionView)

        registerCells()
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return pages.count + 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        if indexPath.item == pages.count {
            let loginCell = collectionView.dequeueReusableCell(withReuseIdentifier: loginCellId, for: indexPath) as! LoginCell
            loginCell.loginControllerDelegate = self
            loginCell.layer.borderColor = UIColor.red.cgColor
            loginCell.layer.borderWidth = 2.0
            return loginCell
        }

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: introCellId, for: indexPath) as! PageCell
        let page = pages[indexPath.item]
        cell.page = page
        cell.layer.borderColor = UIColor.red.cgColor
        cell.layer.borderWidth = 2.0
        return cell
    }

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

LoginCell:

class PageCell: UICollectionViewCell {

    var page: Page? {
        didSet {
            guard let page = page
            else {
                return
            }

            imageView.image = UIImage(named: page.imageName)

            let color = UIColor(white: 0.2, alpha: 1)

            let attributedText = NSMutableAttributedString(string: page.title, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.medium), NSAttributedString.Key.foregroundColor: color])

            attributedText.append(NSMutableAttributedString(string: "\n\n\(page.message)", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.medium), NSAttributedString.Key.foregroundColor: color]))

            let paragraphStyle = NSMutableParagraphStyle()

            paragraphStyle.alignment = .center

            let length = attributedText.string.count

            attributedText.addAttributes([NSAttributedString.Key.paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: length))

            textView.attributedText = attributedText
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupViews()
    }

    let imageView: UIImageView = {
        let iv = UIImageView()
        iv.contentMode = .scaleAspectFill
        iv.backgroundColor = UIColor(displayP3Red: 139/255, green: 221/255, blue: 116/255, alpha: 1)
        iv.clipsToBounds = true
        return iv
    }()

    let textView: UITextView = {
        let tv = UITextView()
        tv.isEditable = false
        tv.contentInset = UIEdgeInsets(top: 24, left: 0, bottom: 0, right: 0)
        tv.textColor = UIColor(displayP3Red: 51/255, green: 51/255, blue: 51/255, alpha: 1)
        return tv
    }()

    func setupViews() {

        addSubview(imageView)
        addSubview(textView)

        _ = imageView.anchor(topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: screenWidth, heightConstant: (screenHeight) / 2)

        _ = textView.anchor(imageView.bottomAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: screenWidth, heightConstant: (screenHeight) / 2)

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been impremented")
    }
}

Anchor方法:

class LoginCell: UICollectionViewCell {

    let logoImageView: UIImageView = {
        let image = UIImage(named: "logo green")
        let imageView = UIImageView(image: image)
        return imageView
    }()

    let emailTextField: UITextField = {
        let textField = UITextField()
        textField.placeholder = "E-Mail"
        textField.layer.borderColor = UIColor.lightGray.cgColor
        let border = CALayer()
        border.frame = CGRect(x: 0, y: 40, width: UIScreen.main.bounds.width - 64, height: 2.0)
        border.backgroundColor = UIColor(displayP3Red: 51/255, green: 51/255, blue: 51/255, alpha: 1).cgColor
        textField.layer.addSublayer(border)
        textField.keyboardType = .emailAddress
        return textField
    }()

    let emailAlertLabel: UILabel = {
        let label = UILabel()
        label.text = "E-Mail-Adresse nicht gefunden"
        label.textColor = .red
        label.isHidden = true
        return label
    }()

    let passwordTextField: UITextField = {
        let textField = UITextField()
        textField.placeholder = "Passwort"
        textField.layer.borderColor = UIColor.lightGray.cgColor
        let border = CALayer()
        border.frame = CGRect(x: 0, y: 40, width: UIScreen.main.bounds.width - 64, height: 2.0)
        border.backgroundColor = UIColor(displayP3Red: 51/255, green: 51/255, blue: 51/255, alpha: 1).cgColor
        textField.layer.addSublayer(border)
        textField.isSecureTextEntry = true
        return textField
    }()

    let passwordAlertLabel: UILabel = {
        let label = UILabel()
        label.text = "Ungültiges Passwort"
        label.textColor = .red
        label.isHidden = true
        return label
    }()

    lazy var forgotPasswordButton: UIButton = {
        let button = UIButton(type: .system)
        button.backgroundColor = .white
        button.setTitle("Passwort vergessen?", for: .normal)
        button.setTitleColor(UIColor(displayP3Red: 139/255, green: 221/255, blue: 116/255, alpha: 1), for: .normal)
        button.addTarget(self, action: #selector(handleForgotPassword), for: .touchUpInside)
        button.contentHorizontalAlignment = .left
        return button
    }()

    lazy var loginButton: UIButton = {
        let button = UIButton(type: .system)
        button.backgroundColor = UIColor(displayP3Red: 139/255, green: 221/255, blue: 116/255, alpha: 1)
        button.setTitle("Login", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.addTarget(self, action: #selector(checkUserData), for: .touchUpInside)
        button.layer.cornerRadius = 25.0
        return button
    }()

    weak var loginControllerDelegate: LoginControllerDelegate?

    lazy var stayLoggedInSwitch: UISwitch = {
        let loginSwitch = UISwitch(frame: CGRect(x: 150, y: 150, width: 0, height: 0))
        loginSwitch.addTarget(self, action: #selector(LoginCell.handleStayLoggedInState(_:)), for: .valueChanged)
        loginSwitch.setOn(false, animated: true)
        return loginSwitch
    }()

    let stayLoggedInTextField: UITextField = {
        let textField = UITextField()
        textField.text = "Angemeldet bleiben"
        textField.textColor = UIColor(displayP3Red: 51/255, green: 51/255, blue: 51/255, alpha: 1)
        textField.isUserInteractionEnabled = false
        return textField
    }()

    let registerLabel: UILabel = {
        let label = UILabel()
        label.text = "Sie haben noch keinen Account?"
        label.textColor = .lightGray
        label.backgroundColor = .white
        label.font = label.font.withSize(13)
        return label
    }()

    lazy var registerButton: UIButton = {
        let button = UIButton(type: .system)
        button.backgroundColor = .white
        button.setTitle("Registrieren", for: .normal)
        button.setTitleColor(UIColor(displayP3Red: 139/255, green: 221/255, blue: 116/255, alpha: 1), for: .normal)
        button.addTarget(self, action: #selector(handleRegister), for: .touchUpInside)
        button.contentHorizontalAlignment = .left
        button.titleLabel?.font = button.titleLabel?.font.withSize(13)
        return button
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupViews()
    }

    func setupViews() {

        addSubview(logoImageView)
        addSubview(emailTextField)
        addSubview(emailAlertLabel)
        addSubview(passwordTextField)
        addSubview(passwordAlertLabel)
        addSubview(forgotPasswordButton)
        addSubview(loginButton)
        addSubview(stayLoggedInSwitch)
        addSubview(stayLoggedInTextField)
        addSubview(registerLabel)
        addSubview(registerButton)

        _ = logoImageView.anchor(centerYAnchor, left: nil, bottom: nil, right: nil, topConstant: -230, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 160, heightConstant: 160)
        logoImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true

        _ = emailTextField.anchor(logoImageView.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 35, leftConstant: 32, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 50)

        _ = emailAlertLabel.anchor(emailTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 32, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 20)

        _ = passwordTextField.anchor(emailAlertLabel.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 32, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 50)

        _ = passwordAlertLabel.anchor(passwordTextField.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 32, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 20)

        _ = forgotPasswordButton.anchor(passwordAlertLabel.bottomAnchor, left: leftAnchor, bottom: nil, right: nil, topConstant: 0, leftConstant: 32, bottomConstant: 0, rightConstant: 0, widthConstant: 200, heightConstant: 25)

        _ = loginButton.anchor(forgotPasswordButton.bottomAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, topConstant: 4, leftConstant: 32, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 50)

        _ = stayLoggedInSwitch.anchor(loginButton.bottomAnchor, left: leftAnchor, bottom: nil, right: nil, topConstant: 16, leftConstant: 32, bottomConstant: 0, rightConstant: 0, widthConstant: 60, heightConstant: 50)

        _ = stayLoggedInTextField.anchor(loginButton.bottomAnchor, left: stayLoggedInSwitch.rightAnchor, bottom: nil, right: rightAnchor, topConstant: 16, leftConstant: 0, bottomConstant: 0, rightConstant: 32, widthConstant: 0, heightConstant: 32)

        _ = registerLabel.anchor(nil, left: leftAnchor, bottom: bottomAnchor, right: nil, topConstant: 0, leftConstant: 32, bottomConstant: 32, rightConstant: 0, widthConstant: 200, heightConstant: 25)

        _ = registerButton.anchor(nil, left: registerLabel.rightAnchor, bottom: bottomAnchor, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 32, rightConstant: 32, widthConstant: 0, heightConstant: 25)

        emailTextField.addTarget(self, action: #selector(underlineTextFieldColor(sender:)), for: .editingDidBegin)
        emailTextField.addTarget(self, action: #selector(underlineTextFieldDark(sender:)), for: .editingDidEnd)
        passwordTextField.addTarget(self, action: #selector(underlineTextFieldColor(sender:)), for: .editingDidBegin)
        passwordTextField.addTarget(self, action: #selector(underlineTextFieldDark(sender:)), for: .editingDidEnd)
    }

    @objc func underlineTextFieldDark(sender: UITextField) {
        sender.layer.sublayers![0].backgroundColor = UIColor(displayP3Red: 51/255, green: 51/255, blue: 51/255, alpha: 1).cgColor
    }

    @objc func underlineTextFieldColor(sender: UITextField) {
        sender.layer.sublayers![0].backgroundColor = UIColor(displayP3Red: 139/255, green: 221/255, blue: 116/255, alpha: 1).cgColor
    }

    @objc func handleLogin() {
        loginControllerDelegate?.finishLoggingIn()
    }

    @objc func handleStayLoggedInState(_ sender: UISwitch) {
        if (sender.isOn == true) {
            UserDefaults.standard.setIsLoggedIn(value: true)
        }
        else {
            UserDefaults.standard.setIsLoggedIn(value: false)
        }
    }

    @objc func handleForgotPassword() {
        loginControllerDelegate?.finishLoggingIn()
    }

    @objc func handleRegister() {
        loginControllerDelegate?.finishLoggingIn()
    }

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

1 个答案:

答案 0 :(得分:0)

集合视图自动设置为整个视图。如果您未设置任何行为,collectionView的内容将能够自动调整昆虫。在这种情况下,将自动调整设置为false以获得全屏视图。屏幕的顶部和底部有一个安全区域,用于调整带有缺口的视图。

尝试一下

collectionView?.contentInsetAdjustmentBehavior = .never

希望这可以解决此问题。