当前位置: > > > Swift - 一个纯代码实现的登录界面(带猫头鹰动画效果)

Swift - 一个纯代码实现的登录界面(带猫头鹰动画效果)

这个是一个可爱的登录框页面,动画效果仿自国外网站readme.io。在GitHub上有人写了个objective-C版本,这里我翻译成Swift版的分享给大家。

效果图如下:
(1)当输入用户名时,猫头鹰的手是搭在登录框上
(2)当输入密码时,猫头鹰的手会遮住眼睛。这个是有动画效果的。实现方式其实就是图片移动动画。
(3)离开密码框时,猫头鹰手又会放下。
    

动态效果如下:


代码如下:
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    //用户密码输入框
    var txtUser:UITextField!
    var txtPwd:UITextField!
    
    //左手离脑袋的距离
    var offsetLeftHand:CGFloat = 60
    
    //左手图片,右手图片(遮眼睛的)
    var imgLeftHand:UIImageView!
    var imgRightHand:UIImageView!
    
    //左手图片,右手图片(圆形的)
    var imgLeftHandGone:UIImageView!
    var imgRightHandGone:UIImageView!
    
    //登录框状态
    var showType:LoginShowType = LoginShowType.NONE

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //获取屏幕尺寸
        let mainSize = UIScreen.mainScreen().bounds.size
        
        //猫头鹰头部
        let imgLogin =  UIImageView(frame:CGRectMake(mainSize.width/2-211/2, 100, 211, 109))
        imgLogin.image = UIImage(named:"owl-login")
        imgLogin.layer.masksToBounds = true
        self.view.addSubview(imgLogin)
        
        //猫头鹰左手(遮眼睛的)
        let rectLeftHand = CGRectMake(61 - offsetLeftHand, 90, 40, 65)
        imgLeftHand = UIImageView(frame:rectLeftHand)
        imgLeftHand.image = UIImage(named:"owl-login-arm-left")
        imgLogin.addSubview(imgLeftHand)
        
        //猫头鹰右手(遮眼睛的)
        let rectRightHand = CGRectMake(imgLogin.frame.size.width / 2 + 60, 90, 40, 65)
        imgRightHand = UIImageView(frame:rectRightHand)
        imgRightHand.image = UIImage(named:"owl-login-arm-right")
        imgLogin.addSubview(imgRightHand)
        
        //登录框背景
        let vLogin =  UIView(frame:CGRectMake(15, 200, mainSize.width - 30, 160))
        vLogin.layer.borderWidth = 0.5
        vLogin.layer.borderColor = UIColor.lightGrayColor().CGColor
        vLogin.backgroundColor = UIColor.whiteColor()
        self.view.addSubview(vLogin)
        
        //猫头鹰左手(圆形的)
        let rectLeftHandGone = CGRectMake(mainSize.width / 2 - 100,
            vLogin.frame.origin.y - 22, 40, 40)
        imgLeftHandGone = UIImageView(frame:rectLeftHandGone)
        imgLeftHandGone.image = UIImage(named:"icon_hand")
        self.view.addSubview(imgLeftHandGone)
        
        //猫头鹰右手(圆形的)
        let rectRightHandGone = CGRectMake(mainSize.width / 2 + 62,
            vLogin.frame.origin.y - 22, 40, 40)
        imgRightHandGone = UIImageView(frame:rectRightHandGone)
        imgRightHandGone.image = UIImage(named:"icon_hand")
        self.view.addSubview(imgRightHandGone)
        
        //用户名输入框
        txtUser = UITextField(frame:CGRectMake(30, 30, vLogin.frame.size.width - 60, 44))
        txtUser.delegate = self
        txtUser.layer.cornerRadius = 5
        txtUser.layer.borderColor = UIColor.lightGrayColor().CGColor
        txtUser.layer.borderWidth = 0.5
        txtUser.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
        txtUser.leftViewMode = UITextFieldViewMode.Always
        
        //用户名输入框左侧图标
        let imgUser =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
        imgUser.image = UIImage(named:"iconfont-user")
        txtUser.leftView!.addSubview(imgUser)
        vLogin.addSubview(txtUser)
        
        //密码输入框
        txtPwd = UITextField(frame:CGRectMake(30, 90, vLogin.frame.size.width - 60, 44))
        txtPwd.delegate = self
        txtPwd.layer.cornerRadius = 5
        txtPwd.layer.borderColor = UIColor.lightGrayColor().CGColor
        txtPwd.layer.borderWidth = 0.5
        txtPwd.secureTextEntry = true
        txtPwd.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
        txtPwd.leftViewMode = UITextFieldViewMode.Always
        
        //密码输入框左侧图标
        let imgPwd =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
        imgPwd.image = UIImage(named:"iconfont-password")
        txtPwd.leftView!.addSubview(imgPwd)
        vLogin.addSubview(txtPwd)
    }
    
    //输入框获取焦点开始编辑
    func textFieldDidBeginEditing(textField:UITextField)
    {
        //如果当前是用户名输入
        if textField.isEqual(txtUser){
            if (showType != LoginShowType.PASS)
            {
                showType = LoginShowType.USER
                return
            }
            showType = LoginShowType.USER
            
            //播放不遮眼动画
            UIView.animateWithDuration(0.5, animations: { () -> Void in
                self.imgLeftHand.frame = CGRectMake(
                    self.imgLeftHand.frame.origin.x - self.offsetLeftHand,
                    self.imgLeftHand.frame.origin.y + 30,
                    self.imgLeftHand.frame.size.width, self.imgLeftHand.frame.size.height)
                self.imgRightHand.frame = CGRectMake(
                    self.imgRightHand.frame.origin.x + 48,
                    self.imgRightHand.frame.origin.y + 30,
                    self.imgRightHand.frame.size.width, self.imgRightHand.frame.size.height)
                self.imgLeftHandGone.frame = CGRectMake(
                    self.imgLeftHandGone.frame.origin.x - 70,
                    self.imgLeftHandGone.frame.origin.y, 40, 40)
                self.imgRightHandGone.frame = CGRectMake(
                    self.imgRightHandGone.frame.origin.x + 30,
                    self.imgRightHandGone.frame.origin.y, 40, 40)
            })
        }
        //如果当前是密码名输入
        else if textField.isEqual(txtPwd){
            if (showType == LoginShowType.PASS)
            {
                showType = LoginShowType.PASS
                return
            }
            showType = LoginShowType.PASS
            
            //播放遮眼动画
            UIView.animateWithDuration(0.5, animations: { () -> Void in
                self.imgLeftHand.frame = CGRectMake(
                    self.imgLeftHand.frame.origin.x + self.offsetLeftHand,
                    self.imgLeftHand.frame.origin.y - 30,
                    self.imgLeftHand.frame.size.width, self.imgLeftHand.frame.size.height)
                self.imgRightHand.frame = CGRectMake(
                    self.imgRightHand.frame.origin.x - 48,
                    self.imgRightHand.frame.origin.y - 30,
                    self.imgRightHand.frame.size.width, self.imgRightHand.frame.size.height)
                self.imgLeftHandGone.frame = CGRectMake(
                    self.imgLeftHandGone.frame.origin.x + 70,
                    self.imgLeftHandGone.frame.origin.y, 0, 0)
                self.imgRightHandGone.frame = CGRectMake(
                    self.imgRightHandGone.frame.origin.x - 30,
                    self.imgRightHandGone.frame.origin.y, 0, 0)
            })
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

//登录框状态枚举
enum LoginShowType {
    case NONE
    case USER
    case PASS
}
源码下载:hangge_926.zip
评论11
  • 11楼
    2016-06-29 08:53
    SkyGrass

    航哥,我不是这个意思,我是说,这个自适应的原理是 什么?怎么做到自适应的。

    站长回复

    程序一开始先获取整个屏幕的尺寸。猫头鹰根据屏幕宽度计算中点,实现水平居中。对于输入框,其宽度就是:屏幕宽度 - 60,即左右各留30边距撑满整个屏幕。

  • 10楼
    2016-06-28 16:43
    SkyGrass

    航哥,哪里看出来是 自适应的啊?

    站长回复

    你用不同的设备或模拟器测试下不就可以看出来了。(比如我文章里静态截图是4s,动态图用的是6)

  • 9楼
    2016-06-23 17:38
    SkyGrass

    航哥,这个登录效果 适配了其他尺寸的屏幕了么?

    站长回复

    是自适应的,可以适配各种屏幕尺寸。

  • 8楼
    2016-05-01 17:01

    怎么登录

    站长回复

    这篇文章是演示如何实现界面布局和动画效果的,登录要自己实现了。

  • 7楼
    2016-04-19 16:09

    站长,您好, 有android 版的吗

    站长回复

    这个目前没有android版的。

  • 6楼
    2016-03-25 20:34
    newblash

    站长你好,最近我写了个纯代码方式的app,但是不知道纯代码转场和传值的方法。。 在AppDelegate.swift里边设置了 rootviewController的初始界面。但是每次都判断登录不成功,就一直在 登录和登录之后的页面跳转

    站长回复

    纯代码页面切换与传值可以参考我原来写的这篇文章:Swift - 使用导航条和导航条控制器来进行页面切换(http://www.hangge.com/blog/cache/detail_586.html)

  • 5楼
    2016-01-09 11:51
    wbstc

    能请教站长一个问题吗.. 比如应用打开的时候,是先进入登录界面。然后登录完成。下次用户再进入的时候,就不用再自动登录了。我写在viewDidLoad 这个事件中.
    let vc = configurationRootViewController();
    self.presentViewController(vc, animated: true, completion: nil)

    ,这个事件是我写的有问题吗.(跳转的代码我已经测试过了的。可以跳转的。).感觉不能像Android一样简单。可以随意跳转了...

    站长回复

    这样写没什么问题。或者你也可以在AppDelegate.swift中的
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    return true
    }
    这个方法里动态调整初始页面

  • 4楼
    2015-11-16 14:49
    young

    good

    站长回复

    ^_^

  • 3楼
    2015-11-06 22:32
    Panda

    纯代码……好牛逼的样子……

    站长回复

    storyboard很好用,有人喜欢,但有人还是更倾向于在代码中创建界面元素,制定布局。两种方式没有哪种更好,只有哪种更适合自己的。

  • 2楼
    2015-11-06 10:56
    木头人

    var txtUser:UITextField!初始化方法已改
    var txtUser:UITextField!()
    var txtUser:UITextField()
    var txtUser:UITextField.self
    目前还不知道着三种有什么区别

    站长回复

    这三种还真没细细研究过。不知是否有哪位网友能做个解答。

  • 1楼
    2015-11-04 20:11
    木头人

    完美

    站长回复

    ^_^