UIView的用法

作为iOS的初学者,在使用一些基本控件的时候总是遇到一些坑,每次google再google,基本能解决问题,但不免浪费了时间。于是在这里把控件的常规用法以及需要特别注意的地方记录下来,如有不对之处,还请指正。

UIView简介

  • UIView可称之为控件或视图,是所有控件的父控件。
  • 一个app所呈现出来的,看得到的,如图片、文字等都是来自于UIView,如下图所示,绿色背景为最为常用的控件。
UIView的用法_第1张图片
UIView继承体系图
  • 不难想象,一个视图要呈现出来,必须有位置和大小等属性,所以View提供了各个控件所需的最基本属性和方法。

UIView属性

  • frame属性
    frame属性为视图呈现的最基本元素,由位置和大小构成,OC抽象为CGRect这个结构。
struct CGRect {
    CGPoint origin;
    CGSize size;
};
typedef struct CGRect CGRect;

frame属性的基本设置方法:

UIView *view = [UIView alloc]init];
view.frame = CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height);

我们看到这里用了alloc,再init的方法,即分配内存进而初始化对象,那为什么不直接用new呢?从new方法的原型可以看到alloc方法和new方法几乎没有区别。在原始的OC方法中创建对象一般也是用new方法,在引入Cocoa等框架后,设计者逐渐明白了不能在一棵树上吊死的理念,才逐步将分配内存和初始化对象分开来,使得初始化有了更多的选择,如常用的initWith方法。

 + (id) new
{
    return [[self alloc] init];
}

差点跑偏,说好的View呢!
UIView通过CGRectMake方法返回一个CGRect,即一个View的坐标原点和大小。在UIKit中,坐标系的原点(0,0)在左上角,x值向右正向延伸,y值向下正向延伸,如下图所示。


UIView的用法_第2张图片
UIKit坐标系

一个view的frame是相对其父类而言的,即view的坐标原点是相对父类view偏离的位置。

  • bounds属性
    bounds属性和frame属性类似,其主要区别是坐标系的不同,frame以其父类bounds.origin为原点,如上图ViewA以父类O(0,0)为原点,位置为O'(x,y)。bounds属性以自己为原点,位置坐标为(0,0)。
frame = a view's location and size using the parent view's coordinate system
Important for: placing the view in the parent
bounds = a view's location and size using its own coordinate system
Important for: placing the view's content or subviews within itself

当然bounds属性也是可以修改的,当bounds属性origin被修改后产生怎样一种效果呢?如下图所示:

UIView *redView= [[UIView alloc]initWithFrame:CGRectMake(100, 200, 200, 200)];
//修改了redView的bounds
redView.bounds = CGRectMake(50, 50, 200, 200);
redView.backgroundColor = [UIColor redColor];
UIView *blueSubView= [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
blueSubView.backgroundColor = [UIColor blueColor];
subView.alpha = 0.5;
[self.view addSubview:redView];
[redView addSubview:blueSubView];
UIView的用法_第3张图片
bounds origin改变示意图

从上图可以看到,当父类redView的bounds.origin修改后,子类frame origin为(0,0)的blueView左上角并没有与父类redView左上角重合,为什么会出现这种现象呢?因为一个视图的渲染是以父类bounds的坐标系为基础的。当redView的bounds.origin设置(50,50),也即是redView左上角O点的坐标在bounds的坐标系中为(50,50),由此可见bounds坐标系的坐标原点(0,0)由原来的O点变为O'点。因此在新的坐标系下blueView出现的位置就可以理解。
事实上,要知道一个view在它父视图什么地方时,记住这个公式:

//下图O'坐标-50 = 0 - 50;
CompositedPosition.x = View.frame.origin.x - Superview.bounds.origin.x;
CompositedPosition.y = View.frame.origin.y - Superview.bounds.origin.y;
  • backgroundColor属性
    设置背景颜色方法:
    点语法或set方法,虽然点语法的实质就是set方法,但某些情况点语法是失效的(跟控件状态有关的属性),需要特别注意。如果希望uivew透明,可以设置其背景色为clearColor,即白色透明度为0的背景色。
view.backgroundColor = [UIColor redColor];
or [view setBackgroundColor:[UIColor redColor]];
or view.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.5 alpha:1];
  • alpha属性
    设置透明度方法:
    透明度范围为0-1,0为全透明,1为不透明。
view.alpha = 0.5;
  • tintColor属性
    tintColor是ios7加入的新属性,有点魔法色的意思,可以重新渲染图片的色彩。如果一个view没有显示的指定tintColor,那它会继承父类的tintColor,如果view层级没有父类则默认为blue color,通过设置keywindow的tintColor就可以设置整个app的主题色。
[[UIApplication sharedApplication] keyWindow].tintColor = [UIColor redColor];

uivew设置tintColor,button类型需为UIButtonTypeSystem,否则无效。

[self.view setTintColor:[UIColor redColor]];
UIView的用法_第4张图片
tintColor变化示意图

tint还有一些值得研究的地方,这里不做细讲,另写一篇笔记以其为主题。

UIView移动层级方法

相关方法很多,列出常用的几个。

//添加子view
- (void)addSubview:(UIView *)view;
//插入view在某个view下
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
//插入view在某个view上
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
//移动view到最上层
- (void)bringSubviewToFront:(UIView *)view;

UIView单击事件

UIView不同于UIButton,UIButton继承于UIControl有addTarget的添加单击事件的方法,UIView添加单击方法可以通过重写UIResponder相关方法和添加手势来实现。

1. UIResponder
UIResponder是专门用来响应用户操作处理各种事件的类。

  • 触摸屏幕
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touch begin");
}
  • 在屏幕上移动
 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    //检测touch点是否在targetView上
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    if (CGRectContainsPoint(self.targetView, location)) {
        NSLog(@"touch location in the targetView");
    }
}
  • 手指离开屏幕,触摸结束
 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touch end");
}
  • 系统事件干扰(电话干扰等)
 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touch cancle");
}

2. Gesture
UIKit框架提供了UIGestureRecognizer手势识别这个类来对触摸进行处理。

    //添加单击手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click)];
    [self.view addGestureRecognizer:tap];

UIResponder和Gesture在这里都不做深入探讨,在其相应主题再行研究。
第一篇iOS笔记,大家一起学习。

PS: I am xinghun who is on the road.

你可能感兴趣的:(UIView的用法)