最终效果图如下:
注意事项:
输入框的return Key
Main.storyboard中为 LoginController 设置一个storyboardID,
以便可以在代码中通过Storyboard对象实例,创建Main.storyboard里面的控制器
仿QQ窗口抖动
dispach_after模拟延时
输入框的return Key的不同处理方式
Login控制器代码
// // LoginController.m // 28_QQ空间 // // Created by beyond on 14-9-1. // Copyright (c) 2014年 com.beyond. All rights reserved. // Main.storyboard中初始化时的控制器,登录控制器 验证成功后,跳转至主控制器 #import "LoginController.h" // 验证成功后,跳转至主控制器 #import "BeyondViewController.h" @interface LoginController () <UITextFieldDelegate> #pragma mark - 拖线 属性 // 登录框整体 @property (weak, nonatomic) IBOutlet UIView *loginContentView; // 帐号 @property (weak, nonatomic) IBOutlet UITextField *usernameField; // 密码 @property (weak, nonatomic) IBOutlet UITextField *passwordField; // 登录按钮 @property (weak, nonatomic) IBOutlet UIButton *loginBtn; // 记住密码btn @property (weak, nonatomic) IBOutlet UIButton *rememberPwdBtn; // 自动登录btn @property (weak, nonatomic) IBOutlet UIButton *autoLoginBtn; // 加载中... @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator; #pragma mark - 拖线 方法 // 登录按钮被点击 - (IBAction)loginBtnClicked; // 点击了记住密码 或 自动登录 - (IBAction)checkboxBtnClicked:(UIButton *)sender; @end @implementation LoginController - (void)viewDidLoad { [super viewDidLoad]; // 1.设置登陆控制器 的背景色 为全局深黑色 self.view.backgroundColor = kGlobalBgColor; // 2.设置登录按钮不同状态下的背景 [self.loginBtn setBtnBgImgForNormal:@"login_button_normal" highlightedName:@"login_button_pressed"]; } // 点击屏幕空白处,退出键盘 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } #pragma mark - 拖线方法 // 点击了记住密码 或 自动登录 - (IBAction)checkboxBtnClicked:(UIButton *)sender { // 设置勾选 或 取消勾选 sender.selected = ! sender.isSelected; // 重要~~~ if (sender == self.rememberPwdBtn && !sender.isSelected) { // 取消了“记住密码”,这时候 就可以同时取消 自动登录了,因为用户不想记住密码,自然就无法实现 自动登录功能 self.autoLoginBtn.selected = NO; } else if (sender == self.autoLoginBtn && sender.isSelected) { // 当用户 选中了“自动登录”,那么表示他想自动登录,那么可以同时把记住密码勾选上 self.rememberPwdBtn.selected = YES; } } // 点击登录按钮 - (IBAction)loginBtnClicked { // 1.验证帐号 NSString *account = self.usernameField.text; if (account.length == 0) { [self showError:@"请输入帐号"]; return; } // 2.验证密码 NSString *password = self.passwordField.text; if (password.length == 0) { [self showError:@"请输入密码"]; return; } // 3.发送请求 self.view.userInteractionEnabled = NO; [self.activityIndicator startAnimating]; // 模拟延时 CGFloat delay = 2.0; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 4.登录完毕(请求完毕) [self.activityIndicator stopAnimating]; self.view.userInteractionEnabled = YES; // 5.账号密码同时为123才是正确 if (![account isEqualToString:@"123"]) { [self showError:@"帐号或密码错误"]; return; } if (![password isEqualToString:@"123"]) { [self showError:@"帐号或密码错误"]; return; } // 6.登录成功 跳转到主页 self.view.window.rootViewController = [[BeyondViewController alloc] init]; }); } #pragma mark - 自定义方法 // 提示错误信息 - (void)showError:(NSString *)errorMsg { // 1.弹框提醒 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"登录失败" message:errorMsg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; // 2.仿QQ窗口抖动 // 核心动画之 关键帧动画 CAKeyframeAnimation *shakeAnim = [CAKeyframeAnimation animation]; // 哪一个成员属性 需要动画,答:x shakeAnim.keyPath = @"transform.translation.x"; shakeAnim.duration = 0.15; CGFloat delta = 10; // 数组,指定每一帧时的x值 shakeAnim.values = @[@0, @(-delta), @(delta), @0]; shakeAnim.repeatCount = 2; // 让view所在的图层执行 关键帧动画 [self.loginContentView.layer addAnimation:shakeAnim forKey:nil]; } #pragma mark - UITextField代理方法 // 控制器 键盘上returnKey在不同输入框下的作用,如Next 或 Done - (BOOL)textFieldShouldReturn:(UITextField *)textField { if (textField == self.usernameField) { // 帐号输入框(Next) [self.passwordField becomeFirstResponder]; } else { // 密码框(Done),调用自定义方法,执行登录 [self loginBtnClicked]; } return YES; } @end
退出,并且回到Main.storyboard里面的初始的登录控制器