ios - 在Swift中实现UILabel动画效果的最佳方法?

标签 ios swift

我对 Swift 动画还很陌生,并且知道如何去做,但想看看其他人会如何做 -

我正在尝试创建这样的效果:当用户进入搜索栏时,搜索栏的占位符文本会缩小并向上移动到搜索字段上方,并更改为不同的颜色。像这样:

http://magicus.xyz当您点击用户名时。

如果我在搜索栏上放置一个 uilabel 并在输入搜索器时缩放此标签,我不确定输入搜索栏是否会注册,因为 uilabel 将位于其上方。

我通常会尝试复制这些文本字段。我将如何创作这个动画?或者甚至为我的搜索栏添加底部边框?

桥梁:

//
//  Makestagram-Bridging-Header.h
//  round
//
//  Created by Skylar Thomas on 6/24/16.
//  Copyright © 2016 Make School. All rights reserved.
//

#ifndef Makestagram_Bridging_Header_h
#define Makestagram_Bridging_Header_h

#import "PureLayout.h"

#endif /* Makestagram_Bridging_Header_h */

enter image description here

错误:

enter image description here

我的项目:

enter image description here

最佳答案

这是一个很好的项目的来源,它完全实现了您的搜索:

    public enum EGFloatingTextFieldValidationType {
        case Email
        case Number
    }

    public class EGFloatingTextField: UITextField {


        private typealias EGFloatingTextFieldValidationBlock = ((text:String,inout message:String)-> Bool)!

        public var validationType : EGFloatingTextFieldValidationType!


        private var emailValidationBlock  : EGFloatingTextFieldValidationBlock
        private var numberValidationBlock : EGFloatingTextFieldValidationBlock


        let kDefaultInactiveColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54))
        let kDefaultActiveColor = UIColor.blueColor()
        let kDefaultErrorColor = UIColor.redColor()
        let kDefaultLineHeight = CGFloat(22)
        let kDefaultLabelTextColor = UIColor(white: CGFloat(0), alpha: CGFloat(0.54))


        public var floatingLabel : Bool!
        var label : UILabel!
        var labelFont : UIFont!
        var labelTextColor : UIColor!
        var activeBorder : UIView!
        var floating : Bool!
        var active : Bool!
        var hasError : Bool!
        var errorMessage : String!



        required public init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            self.commonInit()
        }


        override public init(frame: CGRect) {
            super.init(frame: frame)
            self.commonInit()
        }

        func commonInit(){

            self.emailValidationBlock = ({(text:String, inout message: String) -> Bool in
                var emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"

                var emailTest = NSPredicate(format:"SELF MATCHES %@" , emailRegex)

                var  isValid = emailTest.evaluateWithObject(text)
                if !isValid {
                    message = "Invalid Email Address"
                }
                return isValid;
            })
            self.numberValidationBlock = ({(text:String,inout message: String) -> Bool in
                var numRegex = "[0-9.+-]+";
                var numTest = NSPredicate(format:"SELF MATCHES %@" , numRegex)

                var isValid =  numTest.evaluateWithObject(text)
                if !isValid {
                    message = "Invalid Number"
                }
                return isValid;

            })
            self.floating = false
            self.hasError = false

            self.labelTextColor = kDefaultLabelTextColor
            self.label = UILabel(frame: CGRectZero)
            self.label.font = self.labelFont
            self.label.textColor = self.labelTextColor
            self.label.textAlignment = NSTextAlignment.Left
            self.label.numberOfLines = 1
            self.label.layer.masksToBounds = false
            self.addSubview(self.label)


            self.activeBorder = UIView(frame: CGRectZero)
            self.activeBorder.backgroundColor = kDefaultActiveColor
            self.activeBorder.layer.opacity = 0
            self.addSubview(self.activeBorder)

            self.label.autoAlignAxis(ALAxis.Horizontal, toSameAxisOfView: self)
            self.label.autoPinEdge(ALEdge.Left, toEdge: ALEdge.Left, ofView: self)
            self.label.autoMatchDimension(ALDimension.Width, toDimension: ALDimension.Width, ofView: self)
            self.label.autoMatchDimension(ALDimension.Height, toDimension: ALDimension.Height, ofView: self)

            self.activeBorder.autoPinEdge(ALEdge.Bottom, toEdge: ALEdge.Bottom, ofView: self)
            self.activeBorder.autoPinEdge(ALEdge.Left, toEdge: ALEdge.Left, ofView: self)
            self.activeBorder.autoPinEdge(ALEdge.Right, toEdge: ALEdge.Right, ofView: self)
            self.activeBorder.autoSetDimension(ALDimension.Height, toSize: 2)

            NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("textDidChange:"), name: "UITextFieldTextDidChangeNotification", object: self)
        }
        public func setPlaceHolder(placeholder:String){
            self.label.text = placeholder
        }

        override public func becomeFirstResponder() -> Bool {

            var flag:Bool = super.becomeFirstResponder()

            if flag {

                if self.floatingLabel! {

                    if !self.floating! || self.text!.isEmpty {
                        self.floatLabelToTop()
                        self.floating = true
                    }
                } else {
                    self.label.textColor = kDefaultActiveColor
                    self.label.layer.opacity = 0
                }
                self.showActiveBorder()
            }

            self.active=flag
            return flag
        }
        override public func resignFirstResponder() -> Bool {

            var flag:Bool = super.becomeFirstResponder()

            if flag {

                if self.floatingLabel! {

                    if self.floating! && self.text!.isEmpty {
                        self.animateLabelBack()
                        self.floating = false
                    }
                } else {
                    if self.text!.isEmpty {
                        self.label.layer.opacity = 1
                    }
                }
                self.label.textColor = kDefaultInactiveColor
                self.showInactiveBorder()
                self.validate()
            }
            self.active = flag
            return flag

        }

        override public func drawRect(rect: CGRect){
            super.drawRect(rect)

            var borderColor = self.hasError! ? kDefaultErrorColor : kDefaultInactiveColor

            var textRect = self.textRectForBounds(rect)
            var context = UIGraphicsGetCurrentContext()
            var borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1),
                CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)]

            if  self.enabled  {

                CGContextBeginPath(context);
                CGContextAddLines(context, borderlines, 2);
                CGContextSetLineWidth(context, 1.0);
                CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
                CGContextStrokePath(context);

            } else {

                CGContextBeginPath(context);
                CGContextAddLines(context, borderlines, 2);
                CGContextSetLineWidth(context, 1.0);
                var  dashPattern : [CGFloat]  = [2, 4]
                CGContextSetLineDash(context, 0, dashPattern, 2);
                CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
                CGContextStrokePath(context);

            }
        }

        func textDidChange(notif: NSNotification){
            self.validate()
        }

        func floatLabelToTop() {

            CATransaction.begin()
            CATransaction.setCompletionBlock { () -> Void in
                self.label.textColor = self.kDefaultActiveColor
            }

            var anim2 = CABasicAnimation(keyPath: "transform")
            var fromTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), CGFloat(1))
            var toTransform = CATransform3DMakeScale(CGFloat(0.5), CGFloat(0.5), CGFloat(1))
            toTransform = CATransform3DTranslate(toTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0)
            anim2.fromValue = NSValue(CATransform3D: fromTransform)
            anim2.toValue = NSValue(CATransform3D: toTransform)
            anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
            var animGroup = CAAnimationGroup()
            animGroup.animations = [anim2]
            animGroup.duration = 0.3
            animGroup.fillMode = kCAFillModeForwards;
            animGroup.removedOnCompletion = false;
            self.label.layer.addAnimation(animGroup, forKey: "_floatingLabel")
            self.clipsToBounds = false
            CATransaction.commit()
        }
        func showActiveBorder() {

            self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1)
            self.activeBorder.layer.opacity = 1
            CATransaction.begin()
            self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1)
            var anim2 = CABasicAnimation(keyPath: "transform")
            var fromTransform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1)
            var toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1)
            anim2.fromValue = NSValue(CATransform3D: fromTransform)
            anim2.toValue = NSValue(CATransform3D: toTransform)
            anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
            anim2.fillMode = kCAFillModeForwards
            anim2.removedOnCompletion = false
            self.activeBorder.layer.addAnimation(anim2, forKey: "_activeBorder")
            CATransaction.commit()
        }

        func animateLabelBack() {
            CATransaction.begin()
            CATransaction.setCompletionBlock { () -> Void in
                self.label.textColor = self.kDefaultInactiveColor
            }

            var anim2 = CABasicAnimation(keyPath: "transform")
            var fromTransform = CATransform3DMakeScale(0.5, 0.5, 1)
            fromTransform = CATransform3DTranslate(fromTransform, -CGRectGetWidth(self.label.frame)/2, -CGRectGetHeight(self.label.frame), 0);
            var toTransform = CATransform3DMakeScale(1.0, 1.0, 1)
            anim2.fromValue = NSValue(CATransform3D: fromTransform)
            anim2.toValue = NSValue(CATransform3D: toTransform)
            anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

            var animGroup = CAAnimationGroup()
            animGroup.animations = [anim2]
            animGroup.duration = 0.3
            animGroup.fillMode = kCAFillModeForwards;
            animGroup.removedOnCompletion = false;

            self.label.layer.addAnimation(animGroup, forKey: "_animateLabelBack")
            CATransaction.commit()
        }
        func showInactiveBorder() {

            CATransaction.begin()
            CATransaction.setCompletionBlock { () -> Void in
                self.activeBorder.layer.opacity = 0
            }
            var anim2 = CABasicAnimation(keyPath: "transform")
            var fromTransform = CATransform3DMakeScale(1.0, 1.0, 1)
            var toTransform = CATransform3DMakeScale(0.01, 1.0, 1)
            anim2.fromValue = NSValue(CATransform3D: fromTransform)
            anim2.toValue = NSValue(CATransform3D: toTransform)
            anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
            anim2.fillMode = kCAFillModeForwards
            anim2.removedOnCompletion = false
            self.activeBorder.layer.addAnimation(anim2, forKey: "_activeBorder")
            CATransaction.commit()
        }

        func performValidation(isValid:Bool,message:String){
            if !isValid {
                self.hasError = true
                self.errorMessage = message
                self.labelTextColor = kDefaultErrorColor
                self.activeBorder.backgroundColor = kDefaultErrorColor
                self.setNeedsDisplay()
            } else {
                self.hasError = false
                self.errorMessage = nil
                self.labelTextColor = kDefaultActiveColor
                self.activeBorder.backgroundColor = kDefaultActiveColor
                self.setNeedsDisplay()
            }
        }

        func validate(){

            if self.validationType != nil {
                var message : String = ""

                if self.validationType! == .Email {

                    var isValid = self.emailValidationBlock(text: self.text, message: &message)

                    performValidation(isValid,message: message)

                } else {
                    var isValid = self.numberValidationBlock(text: self.text, message: &message)

                    performValidation(isValid,message: message)
                }
            }
        }


    }

    extension EGFloatingTextField {

    }

他的名字是EGFloatingTextField,您可以找到更多详细信息 here

用法:

let emailLabel = EGFloatingTextField(frame: CGRectMake(8, 64, CGRectGetWidth(self.view.bounds) - 16, 48))
emailLabel.floatingLabel = true
emailLabel.setPlaceHolder("Email")
emailLabel.validationType = .Email
emailLabel.keyboardType = .EmailAddress
self.view.addSubview(emailLabel)

附注您需要导入PureLayout库,here您可以找到完整的源代码和如何导入它的说明。

enter image description here

关于ios - 在Swift中实现UILabel动画效果的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38189672/

相关文章:

ios - 如何用SKLightNode获取正午阳光的影子

Swift:初始化具有大量属性的模型类的正确方法

ios - Alamofire 图像模糊 Swift

iphone - 设备上的 UISlider setMinimumTrackTintColor 崩溃

ios - 如何使用 Xcode 6.3 Beta2 在 Swift 中覆盖 SuperClass 的 setter?

ios - 尝试使用 Firebase 动态链接,无法在 iOS 上打开应用

objective-c - 如何检测 UIBezierPath 是否与自身相交?

Swift Vapor Postgres Xcode 构建错误 : Could not build Objective-C module 'CPostgreSQLMac'

ios - Swift - 在 CollectionView 中显示检索到的 Firestore 数据

ios - 无法将数据转换为字符周围的字符串