Swift-子视图框架。不正确地阅读限制阅读

发布于 2025-01-25 21:02:37 字数 9051 浏览 2 评论 0原文

我有一个基本的注册屏幕以编程方式设置,其中的UI元素本身就是滚动视图中的视图。

屏幕中的最后一个UI元素是寄存器按钮。我设置了带有遗嘱显示的键盘通知观察者,并将隐藏通知。

我正在iPod Touch 7th Gen Simulator上运行此代码。

我的问题是尝试读取注册按钮的最大值并将其与键盘Miny进行比较时,它打印了错误的数字。

键盘显然是阻止寄存器按钮,这意味着按钮的最大值将更大,键盘小值。

但是,打印的值表明读取寄存器按钮框架有问题。

这是我的代码:

import UIKit

class RegisterVC: UIViewController {
    
    
    private let scrollView: UIScrollView = {
        let scroll = UIScrollView()
        scroll.clipsToBounds = true
        scroll.isScrollEnabled = true
        scroll.translatesAutoresizingMaskIntoConstraints = false
        scroll.showsVerticalScrollIndicator = false
        
        return scroll
    }()
    
    private let scrollInnerView: UIView = {
        let innerView = UIView()
        innerView.translatesAutoresizingMaskIntoConstraints = false
        
        return innerView
    }()
    
    private let profilePic: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(systemName: "person.circle")
        imageView.contentMode = .scaleAspectFit
        imageView.tintColor = .gray
        imageView.translatesAutoresizingMaskIntoConstraints = false
        
        return imageView
    }()
    
    
    private let usernameField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .next
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Username..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.keyboardType = .default
        field.isHighlighted = false
        field.textAlignment = .left
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let emailField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .next
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Email Address..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.keyboardType = .default
        field.textAlignment = .left
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let passwordField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .done
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Password..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.isSecureTextEntry = true
        field.textAlignment = .left
        field.keyboardType = .default
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let registerButton: UIButton = {
        let button = UIButton()
        button.setTitle("Create Account", for: .normal)
        button.backgroundColor = .systemGreen
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 12
        button.layer.masksToBounds = true
        button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
        button.translatesAutoresizingMaskIntoConstraints = false
        
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Create Account"
        view.backgroundColor = .white
        
        view.addSubview(scrollView)
        scrollView.addSubview(scrollInnerView)
        scrollInnerView.addSubview(profilePic)
        scrollInnerView.addSubview(usernameField)
        scrollInnerView.addSubview(emailField)
        scrollInnerView.addSubview(passwordField)
        scrollInnerView.addSubview(registerButton)
        usernameField.delegate = self
        emailField.delegate = self
        passwordField.delegate = self
        profilePic.isUserInteractionEnabled = true
        registerButton.addTarget(self,
                                 action: #selector(registerButtonTapped),
                                 for: .touchUpInside)

        setUpKeyboard()
        setUpConstraints()
        
    }
    
    private func setUpConstraints() {
        
        // Scroll View Constraints
        
        scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        
        // Scroll Inner View Constraints
        
        scrollInnerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        scrollInnerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        scrollInnerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        scrollInnerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        scrollInnerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
        scrollInnerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, constant: 1).isActive = true
        
        // Profile Picture Constraints
        
        profilePic.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
        profilePic.heightAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
        profilePic.centerXAnchor.constraint(equalTo: scrollInnerView.centerXAnchor).isActive = true
        profilePic.topAnchor.constraint(equalTo: scrollInnerView.topAnchor, constant: 10).isActive = true
        
        // User Name Field Constraints
        
        usernameField.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, constant: -60).isActive = true
        usernameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
        usernameField.topAnchor.constraint(equalTo: profilePic.bottomAnchor, constant: 10).isActive = true
        usernameField.centerXAnchor.constraint(equalTo: profilePic.centerXAnchor).isActive = true
        
        // Email Field Constraints
        
        emailField.widthAnchor.constraint(equalTo: usernameField.widthAnchor).isActive = true
        emailField.heightAnchor.constraint(equalTo: usernameField.heightAnchor).isActive = true
        emailField.topAnchor.constraint(equalTo: usernameField.bottomAnchor, constant: 10).isActive = true
        emailField.centerXAnchor.constraint(equalTo: usernameField.centerXAnchor).isActive = true
        
        // Password Field Constraints
        
        passwordField.widthAnchor.constraint(equalTo: emailField.widthAnchor).isActive = true
        passwordField.heightAnchor.constraint(equalTo: emailField.heightAnchor).isActive = true
        passwordField.topAnchor.constraint(equalTo: emailField.bottomAnchor, constant: 10).isActive = true
        passwordField.centerXAnchor.constraint(equalTo: emailField.centerXAnchor).isActive = true
        
        // Register Button Constraints
        
        registerButton.widthAnchor.constraint(equalTo: passwordField.widthAnchor).isActive = true
        registerButton.heightAnchor.constraint(equalTo: passwordField.heightAnchor).isActive = true
        registerButton.topAnchor.constraint(equalTo: passwordField.bottomAnchor, constant: 20).isActive = true
        registerButton.centerXAnchor.constraint(equalTo: passwordField.centerXAnchor).isActive = true
    }
    
    private func setUpKeyboard() {
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc private func keyboardWillShowNotification(_ notification: NSNotification) {
        
        guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        else {
            
            return
        }
        
        print(keyboardSize.minY)
        print(registerButton.frame.maxY)
        
    }
}

I have a basic sign up screen set up programmatically with the UI elements inside a view that is itself inside a scroll view.

The last UI element in the screen is a register button. I set up a keyboard notification observer with the Will Show and Will Hide notifications.

I am running this code on iPod touch 7th gen simulator.

My problem is when trying to read the maxY value of the sign up button and compare it to the keyboard minY it prints wrong numbers.

The keyboard is clearly blocking the register button which mean the button's maxY value will be greater the the keyboard minY value.

However the values printed shows that there is something wrong with the reading of the register button frame.

Here is my code:

import UIKit

class RegisterVC: UIViewController {
    
    
    private let scrollView: UIScrollView = {
        let scroll = UIScrollView()
        scroll.clipsToBounds = true
        scroll.isScrollEnabled = true
        scroll.translatesAutoresizingMaskIntoConstraints = false
        scroll.showsVerticalScrollIndicator = false
        
        return scroll
    }()
    
    private let scrollInnerView: UIView = {
        let innerView = UIView()
        innerView.translatesAutoresizingMaskIntoConstraints = false
        
        return innerView
    }()
    
    private let profilePic: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(systemName: "person.circle")
        imageView.contentMode = .scaleAspectFit
        imageView.tintColor = .gray
        imageView.translatesAutoresizingMaskIntoConstraints = false
        
        return imageView
    }()
    
    
    private let usernameField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .next
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Username..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.keyboardType = .default
        field.isHighlighted = false
        field.textAlignment = .left
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let emailField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .next
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Email Address..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.keyboardType = .default
        field.textAlignment = .left
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let passwordField: UITextField = {
        let field = UITextField()
        field.autocapitalizationType = .none
        field.autocorrectionType = .no
        field.returnKeyType = .done
        field.layer.cornerRadius = 12
        field.layer.borderWidth = 1
        field.layer.borderColor = UIColor.lightGray.cgColor
        field.placeholder = "Password..."
        field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
        field.leftViewMode = .always
        field.backgroundColor = .white
        field.isSecureTextEntry = true
        field.textAlignment = .left
        field.keyboardType = .default
        field.translatesAutoresizingMaskIntoConstraints = false
        
        return field
    }()
    
    private let registerButton: UIButton = {
        let button = UIButton()
        button.setTitle("Create Account", for: .normal)
        button.backgroundColor = .systemGreen
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 12
        button.layer.masksToBounds = true
        button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
        button.translatesAutoresizingMaskIntoConstraints = false
        
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Create Account"
        view.backgroundColor = .white
        
        view.addSubview(scrollView)
        scrollView.addSubview(scrollInnerView)
        scrollInnerView.addSubview(profilePic)
        scrollInnerView.addSubview(usernameField)
        scrollInnerView.addSubview(emailField)
        scrollInnerView.addSubview(passwordField)
        scrollInnerView.addSubview(registerButton)
        usernameField.delegate = self
        emailField.delegate = self
        passwordField.delegate = self
        profilePic.isUserInteractionEnabled = true
        registerButton.addTarget(self,
                                 action: #selector(registerButtonTapped),
                                 for: .touchUpInside)

        setUpKeyboard()
        setUpConstraints()
        
    }
    
    private func setUpConstraints() {
        
        // Scroll View Constraints
        
        scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        
        // Scroll Inner View Constraints
        
        scrollInnerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        scrollInnerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        scrollInnerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        scrollInnerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        scrollInnerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
        scrollInnerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, constant: 1).isActive = true
        
        // Profile Picture Constraints
        
        profilePic.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
        profilePic.heightAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
        profilePic.centerXAnchor.constraint(equalTo: scrollInnerView.centerXAnchor).isActive = true
        profilePic.topAnchor.constraint(equalTo: scrollInnerView.topAnchor, constant: 10).isActive = true
        
        // User Name Field Constraints
        
        usernameField.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, constant: -60).isActive = true
        usernameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
        usernameField.topAnchor.constraint(equalTo: profilePic.bottomAnchor, constant: 10).isActive = true
        usernameField.centerXAnchor.constraint(equalTo: profilePic.centerXAnchor).isActive = true
        
        // Email Field Constraints
        
        emailField.widthAnchor.constraint(equalTo: usernameField.widthAnchor).isActive = true
        emailField.heightAnchor.constraint(equalTo: usernameField.heightAnchor).isActive = true
        emailField.topAnchor.constraint(equalTo: usernameField.bottomAnchor, constant: 10).isActive = true
        emailField.centerXAnchor.constraint(equalTo: usernameField.centerXAnchor).isActive = true
        
        // Password Field Constraints
        
        passwordField.widthAnchor.constraint(equalTo: emailField.widthAnchor).isActive = true
        passwordField.heightAnchor.constraint(equalTo: emailField.heightAnchor).isActive = true
        passwordField.topAnchor.constraint(equalTo: emailField.bottomAnchor, constant: 10).isActive = true
        passwordField.centerXAnchor.constraint(equalTo: emailField.centerXAnchor).isActive = true
        
        // Register Button Constraints
        
        registerButton.widthAnchor.constraint(equalTo: passwordField.widthAnchor).isActive = true
        registerButton.heightAnchor.constraint(equalTo: passwordField.heightAnchor).isActive = true
        registerButton.topAnchor.constraint(equalTo: passwordField.bottomAnchor, constant: 20).isActive = true
        registerButton.centerXAnchor.constraint(equalTo: passwordField.centerXAnchor).isActive = true
    }
    
    private func setUpKeyboard() {
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc private func keyboardWillShowNotification(_ notification: NSNotification) {
        
        guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        else {
            
            return
        }
        
        print(keyboardSize.minY)
        print(registerButton.frame.maxY)
        
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬心 2025-02-01 21:02:37

这是因为键盘框架和按钮框架位于两个不同的坐标系中。您无法直接比较它们。在比较之前,您需要将按钮框架转换为窗口坐标。否则,将键盘框架转换为按钮框架坐标(按钮的超级图)。

实际上,我通常要做的是将键盘框架转换为目标视图的内部坐标,并将其与目标视图的 bends进行比较。例如:

// n is the notification
let d = n.userInfo!
var r = d[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
r = self.slidingView.convert(r, from:nil) // <- this is the key move!
let h = self.slidingView.bounds.intersection(r).height

这告诉我键盘是否涵盖了滑动视图,如果是的,则可以覆盖多少。

It's because the keyboard frame and the button frame are in two different coordinate systems. You cannot compare them directly. You need to convert the button frame to window coordinates before comparing them. Or else convert the keyboard frame to the button frame coordinates (the button's superview).

Actually what I typically do is convert the keyboard frame to the internal coordinates of the target view and compare that to the target view's bounds. For example:

// n is the notification
let d = n.userInfo!
var r = d[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
r = self.slidingView.convert(r, from:nil) // <- this is the key move!
let h = self.slidingView.bounds.intersection(r).height

That tells me whether the keyboard would cover the sliding view, and if so, by how much.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文