最终效果图如下:
注意事项:
输入框的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里面的初始的登录控制器