当前位置: 首页 > 工具软件 > UIView-Blur > 使用案例 >

勿在浮沙筑高台——重新认识UIView

戴靖
2023-12-01

最近在做项目时,使用UIView的时候,有点唯唯诺诺,生怕出错,所以重新读了一遍文档中UIView类的OverView,许多模糊的问题,得到了答案,真是侯捷先生的那句“勿在浮沙筑高台”。

本文章的前半部分为文档中UIView概述的翻译,后半部分为自己的一些理解和一些代码实例。

UIView概述

UIVIew定义

UIView类,按照UIView的OverView定义一个屏幕上矩形区域和用来管理这个区域内容的一些接口。在运行时,一个视图对象处理它区域内内容的渲染(注:CALayer),并且处理这个区域内的交互行为。UIView类自身提供基本的用背景颜色填充矩形区域的方法,想要显示更复杂的内容(注:比如圆环套圆环的背景),需要子类化UView,并实现绘图和事件处理方法。UIKit框架包含一组标准的UView子类,从简单的按钮(注:UIButton)到复杂的表(注:UITableView),都可以直接使用。

因为视图对象是应用程序与用户进行交互的主要方式,它们有许多职责。例如:

绘图和动画:

绘图使用技术例如UIKit, Core Graphics, and OpenGL ES,绘制矩形区域的内容。

视图的一些属性在变成新值时,可以使用动画效果。

布局和子视图管理:
  一个视图可以包含零个或多个视图。
  每个视图通过它的父视图定义自己的缺省大小。
  在需要时,视图可以手动改变它的子视图的大小和位置。

事件处理:
  视图是个应答器,可以处理触摸事件和UIResponder类定义的其他事件。
  视图可以使用addGestureRecognizer:方法 安装的手势识别器来处理常见的手势。

视图可以嵌入其他视图和创建复杂的可视层次。这将创建一个父子关系嵌入的视图(称为子视图)和被嵌入的视图(称为父视图)。通常,一个子视图的可视区域是不受父视图边界限制的,但在iOS可以通过clipsToBounds属性改变这种设置。一个父视图可以包含任意数量的子视图,但自视图只有一个父视图,该父视图负责恰当地定位它的子视图。

通过frame, bounds, and center 这些几何属性定义一个视图,Frame在父视图坐标系统定义视图的起点和大小,并且常用在布局去调整视图的大小或位置。Center属性可以用在不改视图大小光调整视图位置。Bounds在自己的坐标体系定义了视图内部的尺寸,通常只被用在自定义渲染代码。Frame和Bounds的大小部分是耦合在一起,以便改变矩形区域的大小,两者的尺寸部分都会更新。

创建一个视图
  以编程方式创建一个视图,可以使用代码如下:

CGRect viewRect = CGRectMake(10、10、100、100);
  UIView * myView =[[UIView alloc]initWithFrame:viewRect];

这段代码创建了一个视图,其位于父视图坐标系统(一旦它被添加到父视图)点(10,10),使用addSubview:方法,添加子视图去另一个视图中。在iOS,兄弟视图可以互相重叠没有任何问题,并允许复杂的视图放置。addSubview: 方法放置的制定视图在其他兄弟视图之上。你可以通过insertSubview:aboveSubview:和insertSubview:belowSubview:方法添加视图,以指定自视图Z坐标的顺序。你也可以通过使用exchangeSubviewAtIndex:withSubviewAtIndex:方法,交换已添加视图的位置。

创建一个视图时,对于autoresizingMask属性分配一个适当的值来确保视图的正确地调整大小是重要的。视图调整主要是发生在你的应用程序界面的方向变化,它也可能发生在其他时间。例如,调用setNeedsLayout方法迫使你的视图更新它的布局。

视图绘制周期

视图绘制发生在需要的基础上,当视图第一次显示,或由于布局变化,视图的全部或部分变得可视,或系统要求视图重绘它的内容。对于使用UIKit or Core Graphics自定义内容的视图,系统调用视图的drawRect:方法。你方法的实现负责绘制视图的内容到 ,被系统先前自动调用的方法设置的当前图形上下文,这将创建一个你的视图内容的可视展现,然后内容将显示在屏幕上。

当你的视图的实际内容变法时,你需要负责去通知系统你的视图需要重绘,你可以通过调用你视图的setNeedsDisplay或setNeedsDisplayInRect:方法来完成。这些方法让系统知道它应该在接下来的渲染周期,更新视图。因为系统将等到下一个渲染周期更新视图,所以你可以在多个视图中调用这些方法,使其在同一时间更新。

动画

改变一些视图属性可以触发动画,其效果是改变的属性,创建一个在很短的一段时间内展现给用户这些改变的动画。执行这些实际的动画的工作 ,主要由视图类来做,但你仍然需要指出哪些属性更改你想成为动画。有两种不同的方法来启动动画:

在iOS 4和之后,使用基于block的动画的方法。(推荐)
使用begin/commit animation的方法。

视图的下列属性是可以设置动画的
  •   @property frame

  •   @property bounds

  •   @property center

  •   @property transform

  •   @property alpha

  •   @property backgroundColor

  •   @property contentStretch

线程问题

必须在主线程操作应用程序的用户界面。因此,你应该在代码运行在应用程序的主线程中,调用UIView类的方法。当创建视图对象本身时,不是所有的执行都一定要在主线程中,这是唯一不严格约束的情况。

子类化说明

(略)

翻译部分结束


UIVIew的定义

我的理解,UIView中CALayer的本质,是一块包含一幅位图的缓冲区,主要负责渲染,而UIView继承自UIResponder,通过响应链来处理交互。而在CocoaTouch框架下,所有的编程都是围绕着UIView,即基于视图编程,这种关系就像MFC中,基于对话框编程,程序由数个对话框以及他们之间的关系组成,APP就由数个视图构成。

实现drawRect:方法

通过实现drawRect:方法,使得View显示复杂内容,现在代码点击这里。实现了圆环套圆环(靶心)的显示。

- (void)drawRect:(CGRect)rect
{
    // What rectangle am I filling?
    CGRect bounds = [self bounds];
    
    // Where is its center?
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;
    
    // From the center, how far out to a corner?
    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;
    
    // Get the context being drawn upon
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // All lines will be drawn 10 points wide
    CGContextSetLineWidth(context, 10);
    
    // Set the stroke color to light gray
    [[UIColor lightGrayColor] setStroke];

    // Draw concentric circles from the outside in
    for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20)
    {
        CGContextAddArc(context, center.x, center.y, 
                        currentRadius, 0.0, M_PI * 2.0, YES);
        CGContextStrokePath(context);
    }
    
    // Create a string
    NSString *text = @"You are getting sleepy.";
    
    // Get a font to draw it in
    UIFont *font = [UIFont boldSystemFontOfSize:28];
    
    // Where am I going to draw it?
    CGRect textRect;
    textRect.size = [text sizeWithFont:font];
    textRect.origin.x = center.x - textRect.size.width / 2.0;
    textRect.origin.y = center.y - textRect.size.height / 2.0;
    
    // Set the fill color of the current context to black
    [[UIColor blackColor] setFill];
    
    // Set the shadow to be offset 4 points right, 3 points down,
    // dark gray and with a blur radius of 2 points
    CGSize offset = CGSizeMake(4, 3);
    CGColorRef color = [[UIColor darkGrayColor] CGColor];
    CGContextSetShadowWithColor(context, offset, 2.0, color);
    
    // Draw the string
    [text drawInRect:textRect
            withFont:font];
}

子视图管理

通过addSubview:方法添加视图,如果子视图不再使用时,记得使用removeFromSuperview方法,断开与父视图或者窗口的连结。

添加手势实例

IOS5.0后,手势识别这块有类可以直接使用,这里给出的官网的新的手势识别实例。点击这里下载代码

动画调用实例

其中packageInfo需要为UIView类或其子类,使用时要替换为自己的UIView实例名的位置改变。视图切换时的动画,可以查看这里

begin/conmit方法

  [UIView beginAnimations:@"View Easy In" context:nil];
    [UIView setAnimationDelay:0.2];
    [UIView setAnimationDuration:1];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    packageInfo.frame = CGRectMake(0, 180, 200, 260);
    [UIView commitAnimations];

Block动画方法(推荐使用)

[UIView animateWithDuration:1 delay:0.2 options:UIViewAnimationCurveEaseIn animations:^{packageInfo.frame = CGRectMake(0, 180, 200, 260);} completion:NULL];


大概就写到这里,还有什么其他的,想到了再补充。



 类似资料: