MDCTextField()未正确显示

时间:2018-04-18 06:18:35

标签: ios material-design swift4 textfield mdc-components

我有一个简单的UIViewController,我正在尝试学习如何配置MDCTextField。

我有两个错误

  1. 文字字段不可编辑
  2. 帮助文本显示在文本字段的顶部而不是在其下面。
  3. 如何解决这两个错误?或者有一个更好的库用于这种文本字段。

    这里是我们在点击它之前的文本字段。您可以看到帮助文本位于文本字段的顶部。

    enter image description here

    这是单击后的文本字段。您可以看到占位符文本确实浮动,占位符文本和下划线确实改变颜色,但我仍然无法输入文本和帮助器文字仍然在顶部而不是在下面。

    enter image description here

    以下是示例代码

    let leftpad: CGFloat = 16
    
    import UIKit
    import MaterialComponents.MaterialTextFields
    
    class ViewController: UIViewController, UIScrollViewDelegate {  // ,   UITextFieldDelegate
    
    var containerHeight : CGFloat = 1000
    let scrollView = UIScrollView()
    var textFieldFloating : MDCTextField!
    var textFieldControllerFloating = MDCTextInputControllerUnderline()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
        // Container
        containerView.delegate = self
        view.addSubview(containerView)
        containerView.contentSize = CGSize(width: view.frame.width, height: containerHeight)
        containerView.autoresizingMask = UIViewAutoresizing.flexibleBottomMargin
        containerView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        containerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
        containerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: 0).isActive = true
        containerView.heightAnchor.constraint(equalTo: view.heightAnchor, constant: 0).isActive = true
    
        // Text
        textFieldFloating = MDCTextField()
        textFieldFloating.translatesAutoresizingMaskIntoConstraints = false
        // textFieldFloating.delegate = self
        textFieldFloating.placeholder = "Name"
        textFieldFloating.isEnabled = true
        textFieldFloating.isUserInteractionEnabled = true
        textFieldFloating.clearButtonMode = .whileEditing
        textFieldControllerFloating = MDCTextInputControllerUnderline(textInput: textFieldFloating)
        textFieldControllerFloating.helperText = "Enter a name"
        textFieldControllerFloating.leadingUnderlineLabelTextColor = UIColor.darkGray       // The helper text
        textFieldControllerFloating.trailingUnderlineLabelTextColor = UIColor.green
        textFieldControllerFloating.inlinePlaceholderColor = UIColor.lightGray              // inline label
        textFieldControllerFloating.borderFillColor = UIColor.white
        textFieldControllerFloating.isFloatingEnabled = true
    
        textFieldControllerFloating.activeColor = UIColor.orange                            // active label & underline
        textFieldControllerFloating.normalColor = UIColor.lightGray                         // default underline
        textFieldControllerFloating.errorColor = UIColor.red
        // textFieldControllerFloating.floatingPlaceholderNormalColor = UIColor.magenta
    
        containerView.addSubview(textFieldFloating)
    
    }
    
    override func viewDidLayoutSubviews() {
    
        // containerView.view.layout( textFieldFloating).center().left(leftpad).right(leftpad)
        textFieldFloating.topAnchor.constraint(equalTo: containerView.topAnchor, constant : 40 ).isActive = true
        textFieldFloating.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant : leftpad ).isActive = true
        textFieldFloating.widthAnchor.constraint(equalTo: containerView.widthAnchor, constant : -leftpad * 2).isActive = true
        textFieldFloating.heightAnchor.constraint(equalToConstant: 40).isActive = true
    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    // The container
    let containerView: UIScrollView = {
        let view = UIScrollView()
        view.backgroundColor = UIColor.white
        view.translatesAutoresizingMaskIntoConstraints = false
        view.layer.masksToBounds = true                          // This makes the rounded corners visible
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleContainerTap))
        view.isUserInteractionEnabled = true
        view.addGestureRecognizer(tapGestureRecognizer)
        return view
    }()
    @objc func handleContainerTap() {
        resignFirstResponderListOnContainerTap()
    }
    func resignFirstResponderListOnContainerTap() {
        // tfName.resignFirstResponder()
    }
    
    
    
    }
    

2 个答案:

答案 0 :(得分:1)

尝试 删除MDCTextfield的高度约束 。我也遇到了同样的问题,并在删除高度约束后得到了解决,因为MDCTexfield将其自身的高度作为适当的高度运行。

答案 1 :(得分:0)

在花了太多时间试图为一个简单的textField设置MDCTextField之后,我决定开发自己的子类,其中包括:i)上边缘的动画占位符,ii)信息标签,iii)动画行底部。

它是UITextField的子类,因此一切都可以通过UITextFieldDelegate方法按预期工作

使用textField.placehoderText = "Placeholder"并     textfield.infolabel.text = "Warning"来设置辅助文本。动画是自动的。

passwordTextField = AGTextField()
passwordTextField.delegate = self
passwordTextField.autocapitalizationType = .none
passwordTextField.keyboardType = UIKeyboardType.default
passwordTextField.isSecureTextEntry = true
passwordTextField.placehoderText = "Password"
self.view.addSubview(passwordTextField)
passwordTextField.addAnchorsAndCenter(centerX: true, centerY: nil, width: width, height: 30, left: nil, top: 30, right: nil, bottom: nil, withAnchor: .top, relativeToView: emailTextField)

附加了子类和自动布局助手

import UIKit
class AGTextField: UITextField {
    var animationDuration: TimeInterval = 0.3
    var placehoderText: String = "" {
        didSet {
            placeholderLabel.text = placehoderText
        }
    }
    var placeholderLabel: UILabel!
    var infoLabel: UILabel!
    var activeColor: UIColor = .gray {
        didSet {
            line.backgroundColor = activeColor
        }
    }
    private let placeholderColor = UIColor.gray
    private let infoColor = UIColor.red
    private var line: UIView!
    convenience init() {
        self.init(frame: CGRect.zero)
        self.tintColor = activeColor
        self.font = UIFont(name: Fonts.regular, size: 16)
        line = UIView()
        line.backgroundColor = activeColor
        self.addSubview(line)
        line.addAnchorsAndSize(width: nil, height: 1.5, left: 0, top: nil, right: 0, bottom: 0)
        placeholderLabel = UILabel()
        placeholderLabel.font = UIFont(name: Fonts.regular, size: 16)
        placeholderLabel.textColor = .lightGray
        self.addSubview(placeholderLabel)
        Timer.scheduledTimer(withTimeInterval: 0.01, repeats: false) { (nil) in
            self.placeholderLabel.frame = self.bounds
        }
        infoLabel = UILabel()
        infoLabel.font = UIFont(name: Fonts.regular, size: 12)
        infoLabel.textColor = .red
        infoLabel.isHidden = true
        self.addSubview(infoLabel)
        infoLabel.addAnchors(left: 0, top: 8, right: nil, bottom: nil, withAnchor: .top, relativeToView: line)
        NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidBeginEditing(notification:)), name: NSNotification.Name.UITextFieldTextDidBeginEditing, object: self)
        NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidEndEditing(notification:)), name: NSNotification.Name.UITextFieldTextDidEndEditing, object: self)
    }
    @objc func textFieldDidBeginEditing(notification: Notification) {
        UIView.animate(withDuration: animationDuration) {
            self.placeholderLabel.frame.origin.y = self.line.frame.origin.y - 50.0
            self.placeholderLabel.font = UIFont(name: Fonts.regular, size: 12)
            self.line.backgroundColor = .gray
        }
        line.backgroundColor = Colors.accent
        infoLabel.isHidden = true
    }
    @objc func textFieldDidEndEditing(notification: Notification) {
        if self.text?.count == 0 {
            UIView.animate(withDuration: animationDuration) {
                self.placeholderLabel.frame = self.bounds
                self.placeholderLabel.font = UIFont(name: Fonts.regular, size: 16)
            }
        }
        self.line.backgroundColor = .gray
    }
    func showInfo(_ text: String) {
        infoLabel.text = text
        infoLabel.isHidden = false
    }
    func hideInfo() {
        infoLabel.isHidden = true
    }
}

我还要添加自动布局UIView扩展

import UIKit
enum Anchor { case left, top, right, bottom }
extension UIView {
    /**
    Description: Centers the view in the superview, using the superview's **size** and **XYAxis** position, not the left, top, right, bottom anchors to avoid issues with the *UISCrollViews*
    Parameters: None
    */
    func addAnchorsCenterAndFillContainer() {
        self.translatesAutoresizingMaskIntoConstraints = false
        self.widthAnchor.constraint(equalTo: self.superview!.widthAnchor).isActive = true
        self.heightAnchor.constraint(equalTo: self.superview!.heightAnchor).isActive = true
        self.centerXAnchor.constraint(equalTo: self.superview!.centerXAnchor).isActive = true
        self.centerYAnchor.constraint(equalTo: self.superview!.centerYAnchor).isActive = true
    }

    /**
    Adds 2 optional alignment parameterts (**centerX**, **centerY**), 2 optional size dimensions (**width** and **height**) and up to 4 border anchors **.left**, **.top**, **.right** and **.bottom**. One of them (defined in **withAnchor** can be relative to another view

    - Parameter centerX: **Bool** value (or *nil*) to define if the view should be centered **horizontally** to the superview. (optional)
    - Parameter centerY: **Bool** value (or *nil*) to define if the view should be centered **vertically** to the superview. (optional)
    - Parameter width: The **width** of the view (optional)
    - Parameter width: The **width** of the view (optional)
    - Parameter height: The **height** of the view (optional)
    - Parameter left: The **left** margin to the superview
    - Parameter top: The **top** margin to the superview
    - Parameter right: The **right** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter bottom: The **bottom** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter withAnchor: The **Anchor** type that is relative to the **relativeToView** view. *This parameter can be omited*
    - Parameter relativeToView: The **UIView** object that is the reference for the **withAnchor** anchor. *This parameter can be omited*

    - Returns: None
    */
    func addAnchorsAndCenter(centerX: Bool?, centerY: Bool?, width: CGFloat?, height: CGFloat?, left: CGFloat?, top: CGFloat?, right: CGFloat?, bottom: CGFloat?, withAnchor: Anchor? = nil, relativeToView: UIView? = nil) {

        self.translatesAutoresizingMaskIntoConstraints = false
        if centerX != nil {
            if centerX! == true {
                self.centerXAnchor.constraint(equalTo: self.superview!.centerXAnchor).isActive = true
            }
        }
        if centerY != nil {
            if centerY! == true {
                self.centerYAnchor.constraint(equalTo: self.superview!.centerYAnchor).isActive = true
            }
        }

        self.addAnchorsAndSize(width: width, height: height, left: left, top: top, right: right, bottom: bottom, withAnchor: withAnchor, relativeToView: relativeToView)
    }

    /**
    Adds 2 optional size dimensions (**width** and **height**) and up to 4 border anchors **.left**, **.top**, **.right** and **.bottom**. One of them (defined in **withAnchor** can be relative to another view

    - Parameter width: The **width** of the view (optional)
    - Parameter height: The **height** of the view (optional)
    - Parameter left: The **left** margin to the superview
    - Parameter top: The **top** margin to the superview
    - Parameter right: The **right** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter bottom: The **bottom** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter withAnchor: The **Anchor** type that is relative to the **relativeToView** view. *This parameter can be omited*
    - Parameter relativeToView: The **UIView** object that is the reference for the **withAnchor** anchor. *This parameter can be omited*

    - Returns: None
    */
    func addAnchorsAndSize(width: CGFloat?, height: CGFloat?, left: CGFloat?, top: CGFloat?, right: CGFloat?, bottom: CGFloat?, withAnchor: Anchor? = nil, relativeToView: UIView? = nil) {

        self.translatesAutoresizingMaskIntoConstraints = false
        if width != nil {
            self.widthAnchor.constraint(equalToConstant: width!).isActive = true
        }
        if height != nil {
            self.heightAnchor.constraint(equalToConstant: height!).isActive = true
        }
        self.addAnchors(left: left, top: top, right: right, bottom: bottom, withAnchor: withAnchor, relativeToView: relativeToView)
    }

    /**
    Adds up to 4 border anchors **.left**, **.top**, **.right** and **.bottom**. One of them (defined in **withAnchor** can be relative to another view

    - Parameter left: The **left** margin to the superview
    - Parameter top: The **top** margin to the superview
    - Parameter right: The **right** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter bottom: The **bottom** margin to the superview. *Magniture adjusted to be positive for margins inside the view*
    - Parameter withAnchor: The **Anchor** type that is relative to the **relativeToView** view. *This parameter can be omited*
    - Parameter relativeToView: The **UIView** object that is the reference for the **withAnchor** anchor. *This parameter can be omited*

    - Returns: None
    */
    func addAnchors(left: CGFloat?, top: CGFloat?, right: CGFloat?, bottom: CGFloat?, withAnchor: Anchor? = nil, relativeToView: UIView? = nil) {

        self.translatesAutoresizingMaskIntoConstraints = false
        let superView = self.superview!
        if withAnchor != nil && relativeToView != nil {
            /**
            * Anchors relative to oposite anchors of reference view
            **/
            switch withAnchor! {
            case .left:
                if left != nil {
                    self.leftAnchor.constraint(equalTo: relativeToView!.rightAnchor, constant: left!).isActive = true
                }
            case .top:
                if top != nil {
                    self.topAnchor.constraint(equalTo: relativeToView!.bottomAnchor, constant: top!).isActive = true
                }
            case .right:
                if right != nil {
                    self.rightAnchor.constraint(equalTo: relativeToView!.leftAnchor, constant: -right!).isActive = true
                }
            case .bottom:
                if bottom != nil {
                    self.bottomAnchor.constraint(equalTo: relativeToView!.topAnchor, constant: -bottom!).isActive = true
                }
            }
        }

        /**
        * Anchors relative to same anchors of superview
        **/
        if let _anchor = withAnchor {
            if _anchor == .left {
                if top != nil {
                    self.topAnchor.constraint(equalTo: superView.topAnchor, constant: top!).isActive = true
                }
                if right != nil {
                    self.rightAnchor.constraint(equalTo: superView.rightAnchor, constant: -right!).isActive = true
                }
                if bottom != nil {
                    self.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: -bottom!).isActive = true
                }
            }
            if _anchor == .top {
                if left != nil {
                    self.leftAnchor.constraint(equalTo: superView.leftAnchor, constant: left!).isActive = true
                }
                if right != nil {
                    self.rightAnchor.constraint(equalTo: superView.rightAnchor, constant: -right!).isActive = true
                }
                if bottom != nil {
                    self.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: -bottom!).isActive = true
                }
            }
            if _anchor == .right {
                if left != nil {
                    self.leftAnchor.constraint(equalTo: superView.leftAnchor, constant: left!).isActive = true
                }
                if top != nil {
                    self.topAnchor.constraint(equalTo: superView.topAnchor, constant: top!).isActive = true
                }
                if bottom != nil {
                    self.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: -bottom!).isActive = true
                }
            }
            if _anchor == .bottom {
                if left != nil {
                    self.leftAnchor.constraint(equalTo: superView.leftAnchor, constant: (left!)).isActive = true
                }
                if top != nil {
                    self.topAnchor.constraint(equalTo: superView.topAnchor, constant: top!).isActive = true
                }
                if right != nil {
                    self.rightAnchor.constraint(equalTo: superView.rightAnchor, constant: -right!).isActive = true
                }
            }
        } else {
            if left != nil {
                self.leftAnchor.constraint(equalTo: superView.leftAnchor, constant: left!).isActive = true
            }
            if top != nil {
                self.topAnchor.constraint(equalTo: superView.topAnchor, constant: top!).isActive = true
            }
            if right != nil {
                self.rightAnchor.constraint(equalTo: superView.rightAnchor, constant: -right!).isActive = true
            }
            if bottom != nil {
                self.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: -bottom!).isActive = true
            }
        }
    }
}