简体   繁体   English

为什么我的某些锚约束不起作用,而其他锚约束却对同一个项目起作用?

[英]Why dont some of my anchor constraints work while others do for the same item?

I am trying to put anchor constraints on a textField contained within a subView. 我试图将锚约束放到subView中包含的textField上。 For the leading and top anchors the anchors work but for the bottom and trailing anchors they dont. 对于前锚和后锚,它们不起作用。 Im not sure what it could be, I would like some space between the keyboard and the items in my subview as well as some space between the UITextField and the trailing anchor edge of the screen. 我不确定这是什么,我想在键盘和子视图中的项之间留一些空间,以及在UITextField和屏幕的尾随锚之间留一些空间。 Below is the code in question 下面是有问题的代码

Layout Code: 布局代码:

func setUpLayout(){

    //myView
    self.myView.translatesAutoresizingMaskIntoConstraints = false
    self.myView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
  self.myView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
    self.myView.heightAnchor.constraint(equalToConstant: 98).isActive = true
    self.myView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 4).isActive = true


    //CollectionView
    self.collectionView.translatesAutoresizingMaskIntoConstraints = false
    self.collectionView.leadingAnchor.constraint(equalTo: self.myView.leadingAnchor, constant: 0).isActive = true
    self.collectionView.trailingAnchor.constraint(equalTo: self.myView.trailingAnchor, constant: 0).isActive = true
    self.collectionView.bottomAnchor.constraint(equalTo: self.myView.bottomAnchor, constant: 4).isActive = true
    self.collectionView.topAnchor.constraint(equalTo: self.searchBar.bottomAnchor, constant: 4).isActive = true

    //searchbar
    self.searchBar.translatesAutoresizingMaskIntoConstraints = false
    self.searchBar.topAnchor.constraint(equalTo: self.myView.topAnchor, constant: 0).isActive = true
    self.searchBar.leadingAnchor.constraint(equalTo: self.myView.leadingAnchor, constant: 4).isActive = true
    self.searchBar.trailingAnchor.constraint(equalTo: self.myView.trailingAnchor, constant: 4).isActive = true
    self.searchBar.heightAnchor.constraint(equalToConstant: 45).isActive = true
    searchBar.backgroundColor = .white
    searchBar.layer.borderWidth = 2
    searchBar.layer.borderColor = UIColor.black.cgColor
    //PictureView
    self.PictureView.translatesAutoresizingMaskIntoConstraints = false
    self.PictureView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
    self.PictureView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
    self.PictureView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
    self.PictureView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
    self.PictureView.backgroundColor = .green
}

Code in its entirety 完整的代码

import UIKit

class SearchCollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITextFieldDelegate, UICollectionViewDataSource,UIGestureRecognizerDelegate {

    var myView: UIView!
    var searchBar: UITextField!
    var collectionView: UICollectionView!

    var PictureView: UIView!


    var genericArray:[String] = ["A","B","C","D","E","F","G","Ab","Abc","za"]
    var currentGenericArray:[String] = [String]()
    var tagsSelected:[String] = [String]()


    let keyboardSlider = KeyboardSlider()

    override func viewDidLoad() {
        super.viewDidLoad()
        keyboardSlider.subscribeToKeyboardNotifications(view: view)

        myView = UIView(frame: CGRect(x: 0, y: self.view.frame.height, width: self.view.frame.width, height: self.view.frame.height))
        searchBar = UITextField(frame: CGRect(x: 0, y: 0, width: self.myView.frame.width, height: self.myView.frame.height))
        PictureView = UIView(frame: self.view.frame)
         self.view.addSubview(PictureView)

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: (UIScreen.main.bounds.width-1)/2, height: (UIScreen.main.bounds.width-1)/2)
        layout.scrollDirection = .horizontal
        self.collectionView = UICollectionView(frame: CGRect(x: 0, y: self.myView.frame.height, width: self.myView.frame.width, height: 100), collectionViewLayout: layout)
        collectionView.backgroundColor = .clear
        collectionView.contentInset = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
        myView.backgroundColor = .clear
        collectionView.delegate = self
        collectionView.dataSource = self
        self.myView.addSubview(collectionView)
        self.view.addSubview(myView)

        collectionView.register(CollectionCell.self, forCellWithReuseIdentifier: "collectionViewCell")
        currentGenericArray = genericArray




        searchBar.delegate = self
        searchBar.autocorrectionType = .no
        searchBar.keyboardType = .default
        searchBar.addTarget(self, action: #selector(SearchCollectionViewController.textFieldDidChange), for: .editingChanged)



        self.myView.addSubview(searchBar)


        let viewTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(viewTapped(gestureRecognizer:)))
        viewTapGestureRecognizer.cancelsTouchesInView = false
        self.PictureView.addGestureRecognizer(viewTapGestureRecognizer)
        self.PictureView.backgroundColor = .purple
        self.view.backgroundColor = .green
        self.searchBar.becomeFirstResponder()

        self.collectionView.allowsSelection = true
        setUpLayout()
    }

    func setUpLayout(){

        //myView
        self.myView.translatesAutoresizingMaskIntoConstraints = false
        self.myView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
      self.myView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
        self.myView.heightAnchor.constraint(equalToConstant: 98).isActive = true
        self.myView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 4).isActive = true


        //CollectionView
        self.collectionView.translatesAutoresizingMaskIntoConstraints = false
        self.collectionView.leadingAnchor.constraint(equalTo: self.myView.leadingAnchor, constant: 0).isActive = true
        self.collectionView.trailingAnchor.constraint(equalTo: self.myView.trailingAnchor, constant: 0).isActive = true
        self.collectionView.bottomAnchor.constraint(equalTo: self.myView.bottomAnchor, constant: 4).isActive = true
        self.collectionView.topAnchor.constraint(equalTo: self.searchBar.bottomAnchor, constant: 4).isActive = true

        //searchbar
        self.searchBar.translatesAutoresizingMaskIntoConstraints = false
        self.searchBar.topAnchor.constraint(equalTo: self.myView.topAnchor, constant: 0).isActive = true
        self.searchBar.leadingAnchor.constraint(equalTo: self.myView.leadingAnchor, constant: 4).isActive = true
        self.searchBar.trailingAnchor.constraint(equalTo: self.myView.trailingAnchor, constant: 4).isActive = true
        self.searchBar.heightAnchor.constraint(equalToConstant: 45).isActive = true
        searchBar.backgroundColor = .white
        searchBar.layer.borderWidth = 2
        searchBar.layer.borderColor = UIColor.black.cgColor
        //PictureView
        self.PictureView.translatesAutoresizingMaskIntoConstraints = false
        self.PictureView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        self.PictureView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        self.PictureView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
        self.PictureView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
        self.PictureView.backgroundColor = .green
    }



    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

    }



    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        keyboardSlider.unsubscribeFromKeyboardNotifications()

    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()

        collectionView.reloadData()
        return true
    }

    /// Helper to dismiss keyboard
    @objc func didStopEditing() {
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut)
        UIView.animate(withDuration: 0.2) {
            self.view.frame.origin.y = 0
        }
    }

    @objc func textFieldDidChange(){
        guard(!(searchBar.text?.isEmpty)!) else{
            currentGenericArray = genericArray
            collectionView.reloadData()
            return
        }

        currentGenericArray = genericArray.filter({letter -> Bool in
            if searchBar.text!.count > letter.count{
                return false
            }
            let stringRange = letter.index(letter.startIndex, offsetBy: searchBar.text!.count)
            let subword = letter[..<stringRange]
            return subword.lowercased().contains(searchBar.text!.lowercased())
        })

        if currentGenericArray.isEmpty{
            print("text being inserted \(searchBar.text!)")
            currentGenericArray.append(searchBar.text!)
        }

        collectionView.reloadData()
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if (touch.view?.isDescendant(of: self.collectionView))!{
            return false
        }
        return true
    }

    var keyboardIsOpen:Bool = false

    @objc func viewTapped(gestureRecognizer:UIGestureRecognizer){

        if keyboardIsOpen{
            myView.isHidden = true
            keyboardIsOpen = !keyboardIsOpen
            searchBar.resignFirstResponder()
        }

        else{
            myView.isHidden = false
            keyboardIsOpen = !keyboardIsOpen
            searchBar.becomeFirstResponder()
        }


    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if section == 0{
            return tagsSelected.count
        }
        else {
            return currentGenericArray.count
        }
    }

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

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionCell
        if indexPath.section == 0{
            cell.collectionLabel.text = tagsSelected[indexPath.item]
            cell.backgroundColor = .blue
            cell.collectionLabel.textColor = .white
        }
        else if indexPath.section == 1{
            cell.backgroundColor = .white
            cell.collectionLabel.textColor = UIColor.black
            cell.collectionLabel.text = currentGenericArray[indexPath.row]
        }
        cell.layer.masksToBounds = true
        cell.layer.cornerRadius = cell.bounds.width/20
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 6
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        if indexPath.section == 1{\
            if(tagsSelected.contains(currentGenericArray[indexPath.item])){
            }

            tagsSelected.append(currentGenericArray[indexPath.item])
            for i in 0...genericArray.count-1{
                if(currentGenericArray[indexPath.item] == genericArray[i]){
                    genericArray.remove(at: i)
                    break
                }
            }
            currentGenericArray.remove(at: indexPath.item)
            searchBar.text = ""
            collectionView.reloadData()
            if collectionView.numberOfItems(inSection: 1)>0{
            collectionView.scrollToItem(at: IndexPath(item: 0, section: 1), at: .right, animated: true)
            }
        }
        else if indexPath.section == 0{
            currentGenericArray.append(tagsSelected[indexPath.item])
            tagsSelected.remove(at: indexPath.item)
            collectionView.reloadData()
        }
    }

    var offsetY:CGFloat = 0

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(SearchCollectionViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }



    @objc func keyboardFrameChangeNotification(notification: Notification) {
        if let userInfo = notification.userInfo {
            let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
            let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
            let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
            let animationCurve = UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue))
            if let _ = endFrame, endFrame!.intersects(self.myView.frame) {
                self.offsetY = self.myView.frame.maxY - endFrame!.minY
            } else {
                if self.offsetY != 0 {
                    UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
                        self.myView.frame.origin.y = self.myView.frame.origin.y + self.offsetY
                        self.offsetY = 0
                    }, completion: nil)
                }
            }
        }
    }

}


class CollectionCell:UICollectionViewCell{


    var collectionLabel: UILabel!
    var view:UIView!
    override init(frame: CGRect) {
        super.init(frame: frame)
         collectionLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height))
        self.addSubview(collectionLabel)
        collectionLabel.textAlignment = .center
        collectionLabel.translatesAutoresizingMaskIntoConstraints = false
        collectionLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
        collectionLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
        collectionLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
        collectionLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
    }

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

extension UIView {
    func currentFirstResponder() -> UIResponder? {
        if self.isFirstResponder {
            return self
        }

        for view in self.subviews {
            if let responder = view.currentFirstResponder() {
                return responder
            }
        }

        return nil
    }
}

extension Notification.Name{
    static let showKeyboard = Notification.Name("showKeyboard")
}
class KeyboardSlider: NSObject {
    // variables to hold and process information from the view using this class
    weak var view: UIView?

    @objc func keyboardWillShow(notification: NSNotification) {
        // method to move keyboard up
        view?.frame.origin.y = 0 - getKeyboardHeight(notification as Notification)
    }

    func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        // get exact height of keyboard on all devices and convert to float value to return for use
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
        return keyboardSize.cgRectValue.height
    }

    func subscribeToKeyboardNotifications(view: UIView) {
        // assigning view to class' counterpart
        self.view = view
        // when UIKeyboardWillShow do keyboardWillShow function
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
    }

    func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
    }


}

For trailing and bottom anchor constraints, it is common that you have to use negative numbers for the constants to achieve what you want. 对于尾部和底部锚点约束,通常必须对常量使用负数才能实现所需的值。

For example: 例如:

searchBar.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: 4).isActive = true

Becomes: 变为:

searchBar.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: -4).isActive = true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么有些约束嵌套在XCode 6中,而其他约束不在嵌套中? - Why are some constraints nested and others not in XCode 6? 以编程方式进行的约束与情节提要中的约束的工作方式不同 - Constraints programmatically do not work the same way as constraints in storyboard "为什么我抽屉里的按钮不做任何事情?" - Why dont the buttons in my Drawer Do anything? 在iPhone 5和iPhone 6上运行应用程序时,为什么我的约束使布局不同? - why do my constraints make the layout different while running app on iphone 5 and iphone 6? Superview的底部约束不适用于3.5版面 - bottom constraints to superview dont work with 3.5 layout 为什么以编程方式使用“自动布局”约束的居中不起作用? - Why does my centering using Autolayout constraints programmatically not work? 为什么此绘图代码在某些运行iOS 8.1的iPad上有效,而在其他iPad上却不可用? - Why does this drawing code work on some iPads running iOS 8.1, but not others? 为什么一些链接框架看起来像一块乐高,而其他框架就像一个工具箱? - Why are some linked frameworks look like a piece of Lego, while others like a toolbox? 约束如何以编程方式工作? - How do constraints work programmatically? AVAudioPlayer:音量按钮适用于某些设备,而不适用于其他设备 - AVAudioPlayer: volume buttons work on some devices and not others
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM