2016-07-04 57 views
2

我非常新的斯威夫特动画,并有如何去这样的想法,但想看看别人会怎么做 -在Swift中实现UILabel动画效果的最佳方法?

我想创建的效果,即在搜索栏的占位符文本缩小并在搜索栏上移动并在用户进入搜索栏时变为不同的颜色。像这样:

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

如果我把在搜索栏一个UILabel并且在进入搜索林不知道输入搜索栏会注册,因为一个UILabel将超过其缩放这个标签..

一般我试图复制这些一般textfields。我将如何去创建这个动画?或者甚至添加一个底部边框到我的搜索栏?

布里杰:

// 
// 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

+1

我觉得这些都是你的后效应(星,我相信它叫)。 https://github.com/raulriera/TextFieldEffects/tree/master/TextFieldEffects/TextFieldEffects – Paulo

回答

4

这大约是一个很好的项目,实现源正是你的搜索:

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._%+-][email protected][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) 

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

enter image description here

+0

无法实现此目的 - 即使我在我的pod文件中写入了所需的行,也无法通过导入PureLayout获取此类模块。我应该在一个单独的脚本中添加所有这些吗?当我这样做,它不认识什么EG文本域是 – skyguy

+0

Looke在这里:https://github.com/PureLayout/PureLayout也有如何导入它的指令 –

+0

好吧,我看透了,但它是一个有点模糊 - 当我将它导入到一个单独的文件中时,我没有收到错误,只是当我将它导入到我的视图控制器文件中时。我是否将上述代码放在单独的文件中? – skyguy

1

你可以试试这样说:

要创建动画:

  1. 发生在文本框的标签,并添加自来水gestureRecogniser标注。将标签缩放到其位置,并在点击标签时将文本字段作为第一响应者。

要创建底部边框:

  1. 添加一个UIView/UIImageView的文本字段下面的根据您的要求1或2个像素的高度。并为textfield设置无边框样式。

要使用颜色更改图标,请尝试使用font-awesome-icons。通过这种方式,您只需传递字符串名称即可将图标更改为彩色图标。

+0

关于如何在标签中设置动画比例的任何想法?我试过CGAffineTransform,但它跳帧/不像上面的答案GIF光滑。 – skyguy

+0

我远离键盘,我将通过EOD发布简单解决方案 –

相关问题