草庐IT

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

coder 2023-09-12 原文

我对使用 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 */

错误:

我的项目:

最佳答案

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

    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您可以找到完整的源代码和如何导入它的说明。

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

有关ios - 在 Swift 中实现 UILabel 动画效果的最佳方式?的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  6. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  7. ruby-on-rails - 如何在 Ruby on Rails 中实现无向图? - 2

    我需要在RubyonRails中实现无向图G=(V,E)并考虑构建一个Vertex和一个Edge模型,其中Vertex有_多条边。由于边恰好连接两个顶点,您将如何在Rails中执行此操作?您是否知道任何有助于实现此类图表的gem或库(对重新发明轮子不感兴趣;-))? 最佳答案 不知道有任何现有库在ActiveRecord之上提供图形逻辑。您可能必须实现自己的Vertex、EdgeActiveRecord支持的模型(请参阅Rails安装的rails/activerecord中的vertex.rb和edge.rb/test/fixtur

  8. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  9. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  10. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

随机推荐