我有一个简单的UIViewController,我正在尝试学习如何配置MDCTextField。
我有两个错误
如何解决这两个错误?或者有一个更好的库用于这种文本字段。
这里是我们在点击它之前的文本字段。您可以看到帮助文本位于文本字段的顶部。
这是单击后的文本字段。您可以看到占位符文本确实浮动,占位符文本和下划线确实改变颜色,但我仍然无法输入文本和帮助器文字仍然在顶部而不是在下面。
以下是示例代码
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()
}
}
答案 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
}
}
}
}