2.2 内容管理
2.2.1 UIView的内容
绘制原始的UIView时,需要绘制的可能只有背景色。但是当UIView中拥有一些内容后,例如是UILable或UIImageView这样的组成画面的基本元素,那么该如何进行UIView的绘制呢?或者说如何控制这些内容的显示方式呢?本节中,将以拥有各种形式内容的UIView来介绍如何控制具体内容显示方式的设置方法。
2.2.2 内容的自动尺寸调整
在UIImageView中,根据边框的大小,可以调整其中包含的图片的显示尺寸。默认为延伸到充满整个边框所占的空间,此时UIView的contentMode属性为UIViewcontent ModeScaleToFill。contentMode属性中可指定UIViewcontentMode类型的常量,通过设置不同常量值来进行内容的尺寸调整或位置调整。如表2-3所示是contentMode属性与内容尺寸、位置的对应情况。
表2-3 contentMode属性与内容尺寸、位置的对应关系表
续表
续表
当内容的绘制范围超出了UIView的frame属性标示的范围时,系统将会在frame属性标示的范围外进行内容绘制。如果想让绘制范围限制在UIView的边框范围内,需要事先将clipsToBounds属性设置为YES。
2.2.3 指定内容的伸缩区域
上一小节介绍了如何通过contentMode属性来改变UIView中内容的尺寸与位置。从iPhone OS 3.0开始追加了可以在内容伸缩时指定具体可伸缩区域的属性。这就是contentStretch属性。在contentStretch属性中以CGRect类型的数据来指定可伸缩的区域。此时,以x为横坐标、y为纵坐标,以及分别以0.0到1.0范围的数字指定宽、高的形式来进行设置。默认如下:
- origin.x = 0.0
- origin.y = 0.0
- size.width = 1.0
- size.height = 1.0
通过调整这些值,可以在调整内容尺寸时改变伸缩的区域。如表2-4所示是设置值与内容伸缩区域变化的对应表。
表2-4 contentStretch属性与伸缩区域的变化
续表
2.2.4 UIView适应内容
上一小节介绍了让内容根据UIView的大小进行尺寸调整。本节将介绍UIView本身如何根据内容的大小进行调整的方法。此时使用的是sizeToFit方法。例如在UILabel中使用sizeToFit方法后,可以根据UILabel中保持的文本字符串大小自动调整UILabel的大小。UIButton的情况下,根据按钮标题的大小自动调整按钮的大小。下面是使用sizeToFit方法的实例代码。
// 追加短标签 UILabel* label1 = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; label1.backgroundColor = [UIColor blueColor]; label1.textColor = [UIColor whiteColor]; label1.text = @"短字符串”; [label1 sizeToFit]; [self.view addSubview:label1]; // 追加长标签 UILabel* label2 = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; label2.backgroundColor = [UIColor blueColor]; label2.textColor = [UIColor whiteColor]; label2.text = @”长ーーーーーーーーーー字符串”; [label2 sizeToFit]; CGPoint newPoint = label2.center; newPoint.y += 50; label2.center = newPoint; [self.view addSubview:label2];
如图2-7所示是实例代码执行的结果。
图2-7 sizeToFit的执行结果
下面尝试修改一下sizeToFit方法中的处理。那么在自定义的UIView子类中该如何改变sizeToFit方法的处理呢?默认是无法进行任何改变的。但是sizeToFit方法中调用的sizeThatFits方法是在UIView中定义的,我们可以通过重写sizeThatFits方法来修改sizeToFit方法的处理。
我们尝试编写一个拥有两个UILabel的DoubleLabel(UIView子类),当此DoubleLabel的sizeToFit方法被调用时,想让两个UILabel的位置向里收紧一点。下面是sizeThatFits方法的实现代码。
// 此类为UIView的子类 // 其中包含了label1_与label2_两个UILabel -(CGSize)sizeThatFits:(CGSize)size { CGFloat x1,x2,y1,y2; // 将label1_与label2_中延伸的一方左侧的坐标设置成x1 if(label1_.frame.origin.x < label2_.frame.origin.x){ x1 = label1_.frame.origin.x; } else { x1 = label2_.frame.origin.x; } // 将label1_与label2_中延伸的一方右侧的坐标设置成x2 if(label1_.frame.origin.x + label1_.frame.size.width > label2_.frame.origin.x + label2_.frame.size.width) { x2 = label1_.frame.origin.x + label1_.frame.size.width; } else { x2 = label2_.frame.origin.x + label2_.frame.size.width; } // 将label1_与label2_中向上延伸的一方左侧的坐标设置成y1 if(label1_.frame.origin.y < label2_.frame.origin.y){ y1 = label1_.frame.origin.y; } else { y1 = label2_.frame.origin.y; } // 将label1_与label2_中向下延伸的一方右侧的坐标设置成y2 if(label1_.frame.origin.y + label1_.frame.size.height > label2_.frame.origin.y + label2_.frame.size.height) { y2 = label1_.frame.origin.y + label1_.frame.size.height; } else { y2 = label2_.frame.origin.y + label2_.frame.size.height; } // 新尺寸的设置 size.width = x2 - x1; size.height = y2 - y1; return size; }
2.2.5 Affine变换(扩大、缩小、反转、平移)
UIView中提供了对内容进行2次affine变换的功能。具体包括扩大、缩小、旋转、反转、平移等。进行affine变换时,要向UIView的transform属性中设置CGAffineTransform的结构体(见表2-5)。图2-8中显示了此结构体的各个值在3×3 affine变换行列式中的具体位置。
表2-5 CGAffineTransform结构体
图2-8 3×3 affine变换行列式
设置CGAffineTransform结构体的值时,需要有关affine变换行列式的知识。但是UIKit中同样提供了不需要变换行列式的知识的相关方法。表2-6中就罗列了变形的种类与实现函数的列表。
表2-6 变形种类与CGAffineTransform函数对照表
将这些变形实际使用到UIImageView中的效果如图2-9所示。
图2-9 affine变换的使用效果
下面列举一个将UIImageView旋转90度的实例代码。
imageView_.transform = CGAffineTransformMakeRotation(90 *(M_PI/ 180.0));
不仅可在UIImageView中使用,其他如UILabel及UIButton等UIView子类中都可以使用。