2016-07-04 150 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發佈簡單解決方案 –