UI基础-自定义视图、视图控制器

自定义视图

自定义视图:系统标准UI之外,自己组合而出的新的视图。
iOS提供了很多UI组件,借助它们,我们可以做各种程序。
尽管如此,实际开发中,我们还需自定义视图。积累自己的代码库。 方便开发。自己封装的视图,能像系统UI控件一样,用于别的项目中,能大大降低开发成本,提高开发效率。

自定义视图创建步骤:

1.创建一个继承自UIView类
2.重写新类的初始化方法
3.把想添加的视图 封装到新类中(初始化到新类中)
4.为了方便外部进行赋值或者取值 把添加的视图写成属性(别忘了dealloc释放)
5.测试一下

label-textField视图

假设我们使用LTView类代表label-textfield视图。
我们创建一个LTView类继承于UIView。
我们将LTView作为一个容器,在LTView的初始化方法中创建并添加 label和textField。
此时的LTView就变成了一个具有label和textField的视图了。

创建方法:

1.新建一个LTView
在LTView.h中将label和textField定义成属性,方便外部取出
2.在LTView.m中重写初始化方法

- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {

    // 动态获取宽度
CGFloat width = frame.size.width;
    // 动态获取高度
CGFloat height = frame.size.height;
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width / 3, height)];
   // 添加到自己身上
[self addSubview:self.label];
   // 释放
[_label release];
self.textField = [[UITextField alloc] initWithFrame:
CGRectMake(width / 3 + 20, 0, width *2/3 - 20, height)];
self.textField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:self.textField];
[_textField release];
}
return self;
}

把Label和Textfield封装到LTView中,在一定程度上简化了我们的代 码。
往往我们需要对LTView中的Label或者Textfield进⾏行一定的控制,比如:设置Label的text,获取Textfield的text,给Textfield指定 delegate,设置textColor等。
为了方便外界操作Label和Textfield,因此我们要为外界提供一些方法。

3.新建一个LoginView

  • 在LoginView.h中,声明需要使用的控件属性
  • 在LoginView.m中,重写初始化方法

    - (instancetype)initWithFrame:(CGRect)frame
    {
    self = [super initWithFrame:frame];
    if (self) {
    self.userNameLTView = [[LTView alloc] initWithFrame:CGRectMake((kScreenWidth - 300) /2, 100, 300, 50)];
    self.userNameLTView.label.text = @"账   号:";
    self.userNameLTView.textField.placeholder = @"请输入账号";
    [self addSubview:self.userNameLTView];
    [self.userNameLTView release];
    
    self.passwordLTView = [[LTView alloc] initWithFrame:CGRectMake(self.userNameLTView.frame.origin.x, self.userNameLTView.frame.origin.y + self.userNameLTView.frame.size.height + kRowHeight, self.userNameLTView.frame.size.width, self.userNameLTView.frame.size.height)];
    self.passwordLTView.label.text = @"密   码:";
    self.passwordLTView.textField.placeholder = @"请输入密码";
    [self addSubview:self.passwordLTView];
    [self.passwordLTView release];
    
     // 利用循环创建button
    NSArray *arr = @[@"登录", @"注册", @"找回密码"];
    for (int i = 0; i < 3; i++) {
     UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)];
     button.frame = CGRectMake(30 + (100 * i), 300, 90, 50);
     [button setTitle:arr[i] forState:(UIControlStateNormal)];
     [button setTitleColor:[UIColor orangeColor] forState:(UIControlStateNormal)];
        // 加标签 方便取出button 与属性的button 相对应
        button.tag = 100 + i;
        [self addSubview:button];
    }
    // 属性与循环的button 进行关联
    self.loginButton = (UIButton *)[self viewWithTag:100];
    self.registButton = (UIButton *)[self viewWithTag:101];
    self.findPasswordButton = (UIButton *)[self viewWithTag:102];  
    }
    return self;
    }
    
    • 在Application中导入LoginView头文件
      创建LoginView

      LoginView *loginView = [[LoginView alloc] initWithFrame:[UIScreen mainScreen].bounds];

      // 添加button标题(或者直接在LoginView.m中利用数组进行赋值)
      [loginView.loginButton setTitle:@”登录” forState:(UIControlStateNormal)];
      [loginView.registButton setTitle:@”注册” forState:(UIControlStateNormal)];
      [loginView.findPasswordButton setTitle:@”找回密码” forState:(UIControlStateNormal)];
      [self.window addSubview:loginView];
      [loginView release];

自定义LTView使用了一种设计模式:复合设计模式。
复合设计模式:A类中,使用B类(或者更多类)作为自己的成员(实例变量)。
iOS中复合是特别常见的设计模式。iOS新控件往往都是用已有控件组合而成的。

注意:动态获取尺寸可使用宏定义(提高代码质量)

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

// 行间距
#define kRowHeight 30

视图控制器

概述:

UIViewController:视图控制器。
控制视图显示,响应事件。
分担AppDelegate的工作。
实现模块独立,提高复用性。

功能:

控制视图大小变换、布局视图、响应事件。
检测以及处理内存警告。
检测以及处理屏幕旋转。
检测视图的切换。

MVC概述:

UIViewController是MVC设计模式的核心。
MVC是一个框架级的设计模式。
M是Model,主要用于建立数据模型(即数据的结构)
V是View,我们能看到的所有控件都是view,view主要的功能是展示数据。
C是控制器,主要是控制M和V的通信。

视图控制器的使用

步骤:

定义UIViewController的子类
创建视图控制器对象,作为window的根视图控制器
在viewDidLoad中使⽤用默认创建好的视图对象view

1.新建一个RootViewController继承于UIViewController 将其设置为根视图控制器 重写loadView方法

// 每一个视图控制器 都自带一个 view
// 并且这个view 跟屏幕一样大小
// 这个方法是加载视图的
// 并且 加载的 自己自带的那个view
- (void)loadView
{
// 调用父类的方法 去加载自身的视图
[super loadView];

// 用上午的loginView 替换 控制器自带的view
LoginView *loginView = [[LoginView alloc] initWithFrame:[UIScreen mainScreen].bounds];
loginView.tag = 1000;

// 帮系统给self.view 赋值
self.view = loginView;

// 释放
[loginView release];
}

2.使用创建好的LoginView 指定为controller的view(见上述代码)
视图控制器指定自定义View
为什么使用自定义视图类:
UIViewController自带一个空的view,与需求不符合。
视图控制器只负责控制视图显示,响应事件。
3.在viewDidLoad方法中进行设置:添加action、设置delegate和代理方法的实现等等。

// 视图已经加载完成
- (void)viewDidLoad {
[super viewDidLoad];

// 更改一下自身view的颜色
// self.view.backgroundColor = [UIColor orangeColor];

// 控制器中写逻辑部分
// 给button添加一个点击方法

LoginView *loginView = (LoginView *)self.view;
// button添加方法
[loginView.loginButton addTarget:self action:@selector(buttonClick:) forControlEvents:(UIControlEventTouchUpInside)];

// 给textField设置代理
loginView.userNameLTView.textField.delegate = self;
loginView.passwordLTView.textField.delegate = self;
}
// button添加方法
- (void)buttonClick:(UIButton *)button
{
NSLog(@"lalala.....");
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}

检测屏幕旋转

屏幕横屏时 改变原来的布局(横屏)
屏幕竖屏时 变回原来的布局 (竖屏)
1.允许屏幕旋转
2.指定屏幕旋转的方向
3.找到旋转触发的方法
4.判断屏幕方法 更改布局
5.测试一下
将工程General下的Deployment Info中的Device Orientation都打勾

  • 根视图的.m文件中 添加方法
    // 1.允许屏幕旋转

    • (BOOL)shouldAutorotate
      {
      return YES;
      }

    // 2.指定屏幕旋转的方向

    • (NSUInteger)supportedInterfaceOrientations
      {
      return UIInterfaceOrientationMaskAll;
      }

    // 3.找到旋转触发的方法

    • (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator: (id)coordinator
      {
      NSLog(@”%@”,NSStringFromCGSize(size));
      }
  • 在自定义视图类中重新布局子视图

    // frame发生变化的时候会触发layoutSubviews方法
    - (void)layoutSubviews
    {
    // 因为不知道父类这个方法做了什么
    // 所以需要再重写的 先调用一下父类的方法
    // 然后再写自己的
    [super layoutSubviews];
    // frame发生变化 相当于 横屏了
    // 这时 咱们需要重新布局视图
    // 判断横屏还是竖屏
    // 1、把应用程序取出来
    // 2、判断一下当前应用程序 屏幕的朝向
    
    // 取出应用程序 单例方法的命名规范share什么的
    UIApplication *app = [UIApplication sharedApplication];
    // 判断方向
    if (app.statusBarOrientation == UIInterfaceOrientationPortrait || app.statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    NSLog(@"竖着");
    self.passwordLTView.frame = CGRectMake(self.userNameLTView.frame.origin.x, self.userNameLTView.frame.origin.y + self.userNameLTView.frame.size.height + kRowHeight, self.userNameLTView.frame.size.width, self.userNameLTView.frame.size.height);
    } else {
    NSLog(@"横着");
    self.passwordLTView.frame = CGRectMake(self.userNameLTView.frame.origin.x + self.userNameLTView.frame.size.width + 10, self.userNameLTView.frame.origin.y, self.userNameLTView.frame.size.width, self.userNameLTView.frame.size.height);
    for (int i = 0; i < 3; i++) {
        UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)];
        button.frame = CGRectMake(60 + (100 * i), 100, 90, 50);
        [button setTitleColor:[UIColor orangeColor] forState:(UIControlStateNormal)];
        // 加标签 方便取出button 与属性的button 相对应
        button.tag = 100 + i;
        [self addSubview:button];
         }
    }
    

处理内存警告

根视图中的内存警告方法:
// 接到内存警告触发的方法
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
NSLog(@”hahahaha”);
// 内存警告了 要干点什么?
// 释放已经显示过的视图 并且 不是当前显示的视图
// 如果这个视图 正在被显示 那么 这个视图的window属性不是空的
if ([self isViewLoaded] == YES && self.view.window == nil) {
// 把当前视图 释放
self.view = nil;
}
}
模拟内存警告:模拟器 -> 硬件 -> 模拟内存警告。查看方法执⾏行

容器视图控制器

常用方法:

self.view显示:viewWillAppear: 和 viewDidAppear:
self.view消失:viewWillDisappear: 和 viewDidDisappear:
当self.view添加到父视图上时,执行appear方法: 当self.view从父视 图上移除时,执行disappear方法。

顺序:

1.定义FirstViewController、SecondViewController类,first作为window 的根视图控制器。

// 创建控制器
RootViewController *rootVC = [[RootViewController alloc] init];
// 创建根视图控制器
self.window.rootViewController = rootVC;
// 释放
[rootVC release];

2.将SecondViewController的view添加到FirstViewController的view上。
3. 将SecondViewController的view移除。
rootViewController中:

 - (void)viewDidLoad {
[super viewDidLoad];

// 如果你不想替换self.view 一般都写在viewDidLoad方法中
self.secondVC = [[SecondViewController alloc] init];
// 把secondVC添加成子控制器 让rootVC去管理
[self addChildViewController:self.secondVC];
// 把secondVC.view 添加到rootVC.view 上
[self.view addSubview:self.secondVC.view];
// 释放
[self.secondVC release];
self.view.backgroundColor = [UIColor yellowColor];

// 添加一个按钮 移除视图 移除子控制器
UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)];
button.frame = CGRectMake(100, 100, 100, 50);
button.backgroundColor = [UIColor blackColor];
// button.layer.cornerRadius = 15;
// 添加到rootVC.view上
[button addTarget:self action:@selector(buttonClick:) forControlEvents:(UIControlEventTouchUpInside)];
[self.view addSubview:button];    
}
- (void)buttonClick:(UIButton *)button
{
// 删除视图
[self.secondVC.view removeFromSuperview];
// 移除子控制器
[self.secondVC removeFromParentViewController];
}

4. 查看SecondViewController中4个方法的执行顺序。

 // 视图生命周期
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"视图将要出现");
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"视图已经出现");
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"视图将要消失");
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(@"视图已经消失");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值