iOS用户界面


iOS用户界面

内容概述

  • UIResponder
  • UIView
  • UILabel
  • UITextView
  • UIButton
  • UITextField
  • UISwith
  • UISlider
  • UISegmentedControl
  • UIProgressView
  • UIActivityIndicatorView
  • UIAlertView
  • UIActionSheet
  • UIImageView
  • UIScrollView
  • UIWebView
  • UIDatePicker
  • UIPickerView
  • UIPageControl

iOS 程序设置遵循严格的MVC设计模式,用户界面是MVC中的视图View。一个优秀的App必定是界面简洁、大方,用户体验极佳的作品。所以,学好用户界面设计对于iOS开发来讲意义深远。下面列表是本章将要讲述到的核心类。

表18.1 本章核心类

类名称 类描述
UIResponder 响应事件视图
UIView 所有视图类的父类,是屏幕上的一个矩形区域,定义了视图类的一些基本功能。
UILabel 是一个静态的文本视图,常用来标示一些其它内容,例如,提示用户输入用户名称、密码等。
UITextView 多行文本视图
UIButton 按钮视图,一般响应一个动作事件,例如,点击事件。
UITextField 可编辑的输入框。
UISwitch 开关按钮视图
UISlider 可滑动的范围值视图
UISegmentedControl 分段切换视图
UIProgressView 进度条视图
UIActivityIndicatorView 进度标示视图
UIAlertView 警告提示视图
UIActionSheet 动作选项视图
UIImageView 图片视图
UIScrollView 滚动视图
UIWebView 网页视图
UIDatePicker 日期、时间选择视图
UIPickerView 选择视图
UIPageControl 页面控制视图

18.1 UIResponder

UIResponder类是所有视图类的父类,包括UIView、UIApplication和UIWindow,有关视图类的继承关系如图18.1所示。

图18.1 视图类的继承关系

该类定义了一些响应和处理事件的方法。事件分为触屏事件、移动事件和远程控制事件。触屏事件方法如下:

– touchesBegan:withEvent: 触屏开始

– touchesMoved:withEvent: 移动当中

– touchesEnded:withEvent: 触屏结束

– touchesCancelled:withEvent: 触屏取消

移动事件方法如下所示:

– motionBegan:withEvent: 开始移动

– motionEnded:withEvent: 结束移动

– motionCancelled:withEvent: 取消移动

另外,该类还定义了一些事件传递链的方法:

– nextResponder下一个响应者

– isFirstResponder 是否是第一响应者

– canBecomeFirstResponder 能否成为第一响应者

– becomeFirstResponder 成为第一响应者

– canResignFirstResponder 能取消第一响应者

– resignFirstResponder 取消第一响应者

这些方法在事件处理和输入控制方面起到了核心作用,例如,可以使用触屏事件实现一个画图软件,可以使用resignFirstResponder方法取消正在显示的键盘。

18.2 UIView

大部分你想要的可视化操作都是由视图对象,即UIView类的实例来完成的。一个视图对象定义了一个屏幕上的一个矩形区域,同时处理该区域的绘制和触屏事件。一个视图也可以作为其他视图的父视图,同时决定着这些子视图的位置和大小。UIView类做了大量的工作去管理这些内部视图的关系,但是需要的时候你也可以定制默认的行为。

UIView的主要行为分为如下三个方面:

  1. 绘制和动画

我们可以使用UIKit、Core Graphics和 OpenGL ES等技术进行视图的绘制。可以通过改变视图的属性实现一些动画效果,例如,alpha可以改变透明度,transform可以进行缩放、旋转和移动。

  1. 布局和子视图的管理

一个视图可以包含若干个子视图,可以动态添加和删除子视图。可以定义子视图相对于父视图的位置。

  1. 事件处理

UIView继承UIResponder可以实现UIResponder中的事件方法。可以调用addGestureRecognizer:方法为视图添加手势处理。

1.2.1 UIView的创建

大部分的应用程序都是使用系统定义好的视图,例如,按钮、输入框等。但有的时候我们也需要自己定义视图来实现一些高级功能,例如,在游戏开发中。自定义一个UIView的步骤如下所示。

  1. 使用XCode创建一个空项目。
  2. 创建一个类继承UIView,覆盖initWithFrame方法和drawRect方法。
#import "MyView.h"

@implementation MyView

- (id)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        // Initialization code

    }

    return self;

}

- (void)drawRect:(CGRect)rect

{

    // 获得上下文

    CGContextRef context = UIGraphicsGetCurrentContext();

    // 设置颜色

    CGContextSetFillColorWithColor(context,  [UIColor redColor].CGColor);

    // 矩形大小

    CGRect r = CGRectMake(20,20,200,200);

    // 添加矩形

    CGContextAddRect(context, r);

    // 绘制

    CGContextDrawPath(context, kCGPathFill);

}

@end
  1. 在代理的didFinishLaunchingWithOptions方法中,实例化MyView并添加到UIWindow中。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch.

    CGRect frame = CGRectMake(0, 0, 300, 300);

    MyView *myView = [[MyView alloc]initWithFrame:frame];

    self.window.backgroundColor = [UIColor whiteColor];

    [self.window addSubview:myView];

    [self.window makeKeyAndVisible];

    return YES;

}
  1. 程序运行结果如下所示。

图18.2 自定义UIView

1.2.2 UIView的核心属性

视图对象通过 frame、bounds、和 center 属性声明来跟踪自己的大小和位置 。

  1. frame 属性包含一个矩形,即边框矩形,用于指定视图相对于其父视图坐标系统的位置和大小。
  2. bounds 属性也包含一个矩形,即边界矩形,负责定义视图相对于本地坐标系统的位置和大小。虽然边界矩形的原点通常被设置为 (0,0),但这并不是必须的。
  3. center属性包含边框矩形的中心点。

在代码中,可以将 frame、bounds、和 center 属性用于不同的目的。边界矩形代表视图本地的坐标系统,因此,在描画和事件处理代码中 ,经常借助它来取得视图中发生事件或需要更新的位置。中心点代表视图的中心,改变中心点一直是移动视图位置的最好方法 。边框矩形是一个通过bound和 center 属性计算得到的便利值,只有当视图的变换属性被设置恒等变换时,边框矩形才是有效的。

下面通过一个实例来演示frame、bounds和center属性的用法。实例步骤如下:

  1. 在上一节的项目中创建一个视图控制器UIViewController。
  2. 在viewDidLoad方法中创建两个按钮,添加到当前视图,并为第二个按钮添加点击事件。
- (void)viewDidLoad

{

    [super viewDidLoad];

    // 实例化圆角Button

    self.myBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    // 边框大小

    CGRect frame = CGRectMake(20, 20, 100, 30);

    //设置按钮边框

    self.myBtn.frame = frame;

    // 设置标题

    [self.myBtn setTitle:@"Test" forState:UIControlStateNormal];

    // 添加视图到当前View

    [self.view addSubview:self.myBtn];



    // 实例化圆角Button

    self.changeBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    // 边框大小

    CGRect frame2 = CGRectMake(20, 100, 100, 30);

    //设置按钮边框

    self.changeBtn.frame = frame2;

    // 设置标题

    [self.changeBtn setTitle:@"Change" forState:UIControlStateNormal];

    // 添加视图到当前View

    [self.view addSubview:self.changeBtn];

    // 添加单击事件

    [self.changeBtn addTarget:self action:@selector(change:) forControlEvents:UIControlEventTouchUpInside];

}
  1. 在点击事件中改变bounds属性和center属性。
- (IBAction)change:(id)sender {

    // 1. 改变center属性

    // 创建点

    CGPoint center = CGPointMake(160, 240);

    // 改变按钮center属性到当前点

    self.myBtn.center = center;

    // 2. 改变bounds属性

    // 设置需要重新布局

    [self.myBtn setNeedsLayout];

    // bounds 大小

    CGRect bounds = CGRectMake(20, 20, 100, 60);

    // 设置按钮bounds属性

    self.myBtn.bounds =bounds;

}
  1. 程序运行结构如下图所示。

图18.3 UIView的核心属性

18.3 UILabel

UILabel是一个只读文本视图,可以使用该视图创建若干行静态文本,我们可以为UILabel设置一些属性来实现格式化的文本。

下面代码创建一个UILabel视图,并指定text属性。

// 1. UILabel 的创建

CGRect frame = CGRectMake(20, 20, 100, 100);

self.myLabel = [[UILabel alloc]initWithFrame:frame];

// 2. 设置Text属性

self.myLabel.text = @"Hello UILabel!";

[self.view addSubview:self.myLabel];

我们还可以设置UILabel的字体、文字颜色和对齐方式、设置字体大小适应label宽度、行数、阴影和缩略显示方式。

// 3. 设置字体

self.myLabel.font = [UIFont boldSystemFontOfSize:20];

// 4. 设置文字颜色

self.myLabel.textColor = [UIColor orangeColor];

// 5. 对齐方式

self.myLabel.textAlignment = UITextAlignmentRight;

// 6. 设置字体大小适应label宽度

self.myLabel.adjustsFontSizeToFitWidth = YES;

// 7. label行数

self.myLabel.numberOfLines = 2;

// 8. 设置阴影

self.myLabel.shadowColor = [UIColor redColor];

self.myLabel.shadowOffset = CGSizeMake(1.0,1.0);

// 9. 省略显示方式

self.myLabel.lineBreakMode = NSLineBreakByTruncatingTail;

缩略方式提供了如下枚举类型:

typedef NS\_ENUM(NSInteger, NSLineBreakMode) {

    NSLineBreakByWordWrapping = 0,

    NSLineBreakByCharWrapping,

    NSLineBreakByClipping,

    NSLineBreakByTruncatingHead,

    NSLineBreakByTruncatingTail,

    NSLineBreakByTruncatingMiddle

}

有时候我们需要文本大小动态创建UILabel视图,下面代码实现了该功能。

// 创建Label

UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 45, 0, 0)];

// 背景色

myLabel.backgroundColor = [UIColor lightTextColor];

// 行数

[myLabel setNumberOfLines:0];

// 缩略方式

myLabel.lineBreakMode = NSLineBreakByTruncatingTail;

// 字体

UIFont *fonts = [UIFont fontWithName:@"Arial" size:12];

myLabel.font = fonts;

// 尺寸大小

CGSize size = CGSizeMake(290, 1000);

myLabel.text = @"iOS 应用开发详解!iOS 应用开发详解!iOS 应用开发详解!iOS 应用开发详解!iOS 应用开发详解!iOS 应用开发详解!";

// 根据文本获得大小

CGSize msgSie = [myLabel.text sizeWithFont:fonts constrainedToSize:size lineBreakMode:NSLineBreakByTruncatingTail];

// 根据size设置frame

[myLabel setFrame:CGRectMake(15, 45, 290, msgSie.height)];

// 添加到视图

[self.view addSubview:myLabel];

图18.4  UILabel自适应大小

18.4 UITextView

UITextView继承UIScrollView是一个可滚动的多行视图文本区域。和UILabel一样可以对要显示的文本进行格式化。并且该文本可以进行编辑。

下面代码创建了一个UITextView,指定了text属性要显示的文本,textColor属性指定字体颜色,font属性指定字体,delegate指定代理,backgroundColor指定背景色,returnKeyType指定返回键类型,keyboardType指定键盘类型等。

- (void)viewDidLoad

{

  [super viewDidLoad];

  // 创建矩形框

  CGRect frame = CGRectMake(20, 20, 200, 200);

  // 实例化UITextView

self.tv = [[UITextView alloc]initWithFrame:frame];

  // 指定text属性

  self.tv.text=@"Hello UITextView! Hello UITextView! Hello UITextView! Hello UITextView! Hello UITextView!";

  //设置textview里面的字体颜色

  self.tv.textColor = [UIColor blackColor];

  //设置字体名字和字体大小

  self.tv.font = [UIFont fontWithName:@"Arial" size:18.0];

  //设置它代理托方法

  self.tv.delegate = self;

  //设置它的背景颜色

  self.tv.backgroundColor = [UIColor whiteColor];

  //返回键的类型

  self.tv.returnKeyType = UIReturnKeyDefault;

  //键盘类型

  self.tv.keyboardType = UIKeyboardTypeDefault;

  //是否可以拖动

  self.tv.scrollEnabled = YES;

  //自适应高度

  self.tv.autoresizingMask = UIViewAutoresizingFlexibleHeight;

// 圆角显示(注意:需要导入#import <QuartzCore/QuartzCore.h>)

  [self.tv.layer setCornerRadius:10];

  [self.view addSubview:self.tv];

}

可以为UITextView指定代理UITextViewDelegate来监控UITextView的编辑状态。步骤如下:

  1. 在.h中实现UITextViewDelegate协议。
@interface AmakerViewController : UIViewController<UITextViewDelegate>

@end
  1. 为UITextView的delegate属性指定为self。
self.tv.delegate = self;
  1. 实现代理方法。
// 内容将要开始编辑

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{

    NSLog(@"textViewShouldBeginEditing...");

    return YES;

}

// 内容将要结束编辑

- (BOOL)textViewShouldEndEditing:(UITextView *)textView{

    NSLog(@"textViewShouldEndEditing...");

    return YES;

}

// 内容已经开始编辑

- (void)textViewDidBeginEditing:(UITextView *)textView{

    NSLog(@"textViewDidBeginEditing...");

}

// 内容已经结束编辑

- (void)textViewDidEndEditing:(UITextView *)textView{

    NSLog(@"textViewDidEndEditing...");

}
  1. 程序运行结果如下所示。
2013-02-05 15:11:26.600 chapter18-04[3127:c07] textViewShouldBeginEditing...

2013-02-05 15:11:27.263 chapter18-04[3127:c07] textViewDidBeginEditing...

18.5 UIButton

UIButton是iOS中最常用的视图控件,常用来响应用户的点击事件。事件方法定义了要完成的动能。下面代码定义了一个UIButton实例,指定Button的类型为圆角矩形,并指定了边框frame属性,设置了标题,并为按钮添加了单击事件。

- (void)viewDidLoad

{

    [super viewDidLoad];

 // 实例化UIButton

    self.btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    // 设置边框

    self.btn1.frame = CGRectMake(20, 20, 100, 50);

    // 设置标题

    [self.btn1 setTitle:@"Hello" forState:UIControlStateNormal];

    // 添加单击事件

    [self.btn1 addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.btn1];

}

-(IBAction)click:(id)sender{

    UIButton *btn = (UIButton*)sender;

    NSString *title = btn.titleLabel.text;

    NSLog(@"%@",title);

}

可以为按钮指定不同的类型,从而呈现不同的样式,也可以自定义按钮。下面枚举定义了按钮的不同类型。

typedef NS\_ENUM(NSInteger, UIButtonType) {

    UIButtonTypeCustom = 0,

    UIButtonTypeRoundedRect,

    UIButtonTypeDetailDisclosure,

    UIButtonTypeInfoLight,

    UIButtonTypeInfoDark,

    UIButtonTypeContactAdd,

};

不同类型的按钮显示效果如下图所示。

图18.5  UIButton的不同类型展示

18.6 UITextField

UITextField是常用的输入控件,例如,登陆界面要求用户输入用户名称和密码等。可以为UITextField指定一些属性来控制输入,例如,是否显示为密码,内容的对齐方式,提示信息,是否显示清除按钮等。下面代码创建了一个UITextField实例,并指定了一些属性,来控制用户的输入。

- (void)viewDidLoad

{

    [super viewDidLoad];

    //边框大小

    CGRect frame = CGRectMake(20, 20, 150, 40);

    // 实例化

 self.tf = [[UITextField alloc]initWithFrame:frame];

    // 提示信息

    self.tf.placeholder = @"Please type Password...";

    // 边框样式

    self.tf.borderStyle = UITextBorderStyleRoundedRect;

    // 内容垂直方向对齐

    self.tf.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;

    // 内容水平方向对齐

    self.tf.textAlignment = NSTextAlignmentLeft;

    //密码

    self.tf.secureTextEntry = YES;

    // 是否自动验证输入内容

    self.tf.autocorrectionType = UITextAutocorrectionTypeNo;

    // 是否单词首字母大小写

    self.tf.autocapitalizationType = UITextAutocapitalizationTypeNone;

    // 键盘返回按键类型

    self.tf.returnKeyType = UIReturnKeyDone;

    // 编辑时的清除按钮

    self.tf.clearButtonMode = UITextFieldViewModeWhileEditing;

    [self.view addSubview:self.tf];

}

图18.6  UITextField

我们可以为UITextField添加代理UITextFieldDelegate来监控当前的编辑状态,下面我们就为按钮添加代理,并实现点击Done时隐藏键盘的动能。实现步骤如下:

  1. 实现代理协议。
#import <UIKit/UIKit.h>

@interface AmakerViewController : UIViewController<UITextFieldDelegate>

@end
  1. 指定代理。
self.tf.delegate = self;
  1. 实现隐藏键盘方法。
- (BOOL)textFieldShouldReturn:(UITextField *)textField{

    // 隐藏键盘

    [self.tf resignFirstResponder];

    return YES;

}

18.7 UISwitch

UISwitch是一个开关控件,常用来控制某个功能的开关状态,例如,蓝牙、GPS、wifi信号等。下面代码定义了一个UISwitch控件,指定了当前状态为开启,设置了不同状态中的颜色,并添加了值改变的事件方法。

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 矩形边框

    CGRect frame = CGRectMake(20, 20, 0, 0);

    // 实例化

 self.mySwitch = [[UISwitch alloc]initWithFrame:frame];

    // 设置当前状态为开启

    [self.mySwitch setOn:YES];

    //底色颜色

    self.mySwitch.tintColor = [UIColor redColor];

    // 开启后底色颜色

    self.mySwitch.onTintColor = [UIColor brownColor];

    // 滑块颜色

    self.mySwitch.thumbTintColor = [UIColor greenColor];

    // 添加事件

    [self.mySwitch addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];

    [self.view addSubview:self.mySwitch];

}

-(IBAction)change:(id)sender{

    UISwitch *swt = (UISwitch*)sender;

    if (swt.on) {

        NSLog(@"set on!");

    }else{

        NSLog(@"set off!");

    }

}

程序运行结果如下图所示。

图18.7  UISwitch

18.8 UISlider

UISlider 控件可以从一个连续的区间中选择一个值,例如,可以控制设备的当前音量、亮度等功能。下面代码创建了一个UISlider,指定了最小值、最大值、当前值和不同状态的颜色并添加了值改变事件。程序代码如下:

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 边框大小

    CGRect frame = CGRectMake(20, 20, 200, 0);

    // 实例化

 self.slider = [[UISlider alloc]initWithFrame:frame];

    // 最小值

    self.slider.minimumValue = 0;

    // 最大值

    self.slider.maximumValue = 100;

    // 是否连续触发事件处理

    self.slider.continuous = YES;

    // 当前值

    self.slider.value = 50;

    // 最小端颜色

    self.slider.minimumTrackTintColor = [UIColor redColor];

    // 最大端颜色

    self.slider.maximumTrackTintColor = [UIColor greenColor];

    // 滑块颜色

    self.slider.thumbTintColor = [UIColor blackColor];

    // 添加值改变事件方法

    [self.slider addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];

    [self.view addSubview:self.slider];

}

-(IBAction)change:(id)sender{

    UISlider *slider = (UISlider*)sender;

    float value = slider.value;

    NSLog(@"value=%f",value);

}

程序运行结果如下图所示。

图18.8  UISlider

18.9 UISegmentedControl

UISegmentedControl是一个多分段选择控件,允许用户在多个分段中做出选择。选中某个分段会触发一个值改变事件,事件方法会被调用。下面代码创建了一个UISegmentedControl实例,为某个指定索引设置标题,设置默认选择项索引,设置了样式和底色颜色,并添加了值改变事件。代码如下:

- (void)viewDidLoad

{

    [super viewDidLoad];

    NSArray *items = @[@"A",@"B",@"c"];

 self.seg = [[UISegmentedControl alloc]initWithItems:items];

    CGRect frame = CGRectMake(20, 20, 180, 50);

    self.seg.frame = frame;

    //设置指定索引的标题

    [self.seg setTitle:@"two" forSegmentAtIndex:1];

    //设置默认选择项索引

    self.seg.selectedSegmentIndex = 1;

    //底色颜色

    self.seg.tintColor = [UIColor redColor];

    //设置样式

    self.seg.segmentedControlStyle = UISegmentedControlStyleBar;

    //设置在点击后是否恢复原样

    self.seg.momentary = NO;

    //设置指定索引选项不可选

    [self.seg setEnabled:NO forSegmentAtIndex:2];

    // 添加事件

    [self.seg addTarget:self action:@selector(change:)

       forControlEvents:UIControlEventValueChanged];

    [self.view addSubview:self.seg];

}

-(IBAction)change:(id)sender{

    UISegmentedControl *seg = (UISegmentedControl*)sender;

    int index = seg.selectedSegmentIndex;

    NSString *title = [self.seg titleForSegmentAtIndex:index];

    switch (index) {

        case 0:

            NSLog(@"%@",title);

            break;

        case 1:

             NSLog(@"%@",title);

            break;

        case 2:

             NSLog(@"%@",title);

            break;

        default:

            break;

    }

}

程序运行结果如下图所示。

图18.9  UISegmentedControl

18.10 UIProgressView

UIProgressView 是进度条视图,用来显示某个任务的当前状态,例如,文件的下载进度、邮件的下载进度等。下面的程序通过一个计数器NSTimer来实现每隔一秒钟更新一次进度的功能。程序代码如下:

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 实例化NSTimer

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(change:) userInfo:nil repeats:YES];

    // 实例化UIProgressView

 self.pv = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];

    // 指定frame属性

    self.pv.frame = CGRectMake(20, 20, 180, 20);

    // 进度颜色

    self.pv.progressTintColor = [UIColor redColor];

    // 底色颜色

    self.pv.trackTintColor = [UIColor greenColor];

    // 当前进度

    self.pv.progress = 0.0;

    [self.view addSubview:self.pv];

}

-(void)change:(NSTimer*)myTimer{

    NSLog(@"Here...%f",self.pv.progress);

    if (self.pv.progress>=1) {

        // 停止NSTimer

        [self.timer invalidate];

    }else{

        // 进度+0.1

        self.pv.progress+=0.1;

    }

}

程序的运行结果如下所示。

图18.10  UIProgressView

18.11 UIActivityIndicatorView

UIActivityIndicatorView 顾名思义是活动标示视图,用来标示某个任务的状态,即忙还是空闲。下面的程序在界面上添加两个按钮和一个UIActivityIndicatorView,按钮用来开启和停止显示。代码如下:

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 实例化UIActivityIndicatorView

 self.aiv = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

    // 指定frame属性

    self.aiv.frame = CGRectMake(20, 20, 100, 100);

    [self.view addSubview:self.aiv];

    // 实例化开启Button

    self.startBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    self.startBtn.frame = CGRectMake(20, 100, 100, 50);

    // 设置标题

    [self.startBtn setTitle:@"Start" forState:UIControlStateNormal];

    // 添加开启事件方法

    [self.startBtn addTarget:self action:@selector(start:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.startBtn];

    // 实例化停止按钮

    self.stopBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    // 设置frame属性

    self.stopBtn.frame = CGRectMake(20, 180, 100, 50);

    // 设置标题

    [self.stopBtn setTitle:@"Stop" forState:UIControlStateNormal];

    // 添加停止事件方法

    [self.stopBtn addTarget:self action:@selector(stop:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.stopBtn];

}

-(IBAction)start:(id)sender{

    // 开启动画显示

    [self.aiv startAnimating];

}

-(IBAction)stop:(id)sender{

    // 停止动画显示

    [self.aiv stopAnimating];

}

程序运行结果如下所示。

图18.11  UIActivityIndicatorView

18.12 UIAlertView

UIAlertView视图为用户显示一个提示信息,例如,要求用户确认某个决定,从用户获得一些信息,例如,用户登陆等。

我们可以使用下列代码来实例化一个UIAlertView,并为其设置要显示的标题、信息、代理和按钮等。

// 实例化UIAlertView,并指定标题、信息和按钮

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"My Title" message:@"This is a message." delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",@"Other", nil];

// 显示

[alert show];

程序运行结果如下图所示。

图18.12  UIAlertView

我们可以为UIAlertView指定一个代理,来判断那个按钮被选中。下面代码展示了如何设置代理并判断那个按钮被选中。

@interface AmakerViewController : UIViewController<UIAlertViewDelegate>
- (IBAction)test2:(id)sender {

    // 实例化UIAlertView,并指定标题、信息、代理和按钮

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"My Title" message:@"This is a message." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",@"Other", nil];

    // 显示

    [alert show];

}

// 代理方法,判断那个按钮被点击

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

    // 获得当前索引按钮的标题

    NSString *buttonTitle = [alertView buttonTitleAtIndex:buttonIndex];

    // 根据标题判断那个按钮被单击

    if ([buttonTitle isEqualToString:@"Cancel"]) {

        NSLog(@"Cancel is clicked!");

    }else if([buttonTitle isEqualToString:@"OK"]){

        NSLog(@"OK is clicked!");

    }else if([buttonTitle isEqualToString:@"Other"]){

        NSLog(@"Other is clicked!");

    }else{

        NSLog(@"Error!");

    }

}

我们也可以为UIAlertView设置一些样式,方便从用户哪里收集一些信息。iOS SDK提供的UIAlertView样式有如下几种。

typedef NS\_ENUM(NSInteger, UIAlertViewStyle) {

    UIAlertViewStyleDefault = 0, // 默认样式

    UIAlertViewStyleSecureTextInput, // 密码输入框

    UIAlertViewStylePlainTextInput, // 普通文件输入框

    UIAlertViewStyleLoginAndPasswordInput // 登陆框

};

下面程序代码实现了一个UIAlertViewStylePlainTextInput的UIAlertView,并且可以获得用户输入的内容。

- (IBAction)test3:(id)sender {

// 实例化UIAlertView,并指定标题、信息、代理和按钮

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:@"your age?" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

// 设置显示样式

[alert setAlertViewStyle:UIAlertViewStylePlainTextInput];

UITextField *textField = [alert textFieldAtIndex:0];

textField.keyboardType = UIKeyboardTypeNumberPad;

[alert show];

}

// 获得索引为0的UITextField

UITextField *textField = [alertView textFieldAtIndex:0];

if (textField!=nil) {

    // 获得UITextField输入的内容

    NSString *content = textField.text;

    NSLog(@"%@",content);

}

程序运行结果如下图所示。

图18.13  UIAlertView样式

下面是一个登录样式的程序。

- (IBAction)test4:(id)sender {

  // 实例化UIAlertView,并指定标题、信息、代理和按钮

  UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:@"Login" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

  // 设置显示样式

  [alert setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];

  [alert show];

}

  // 获得索引为0的UITextField

  UITextField *textField = [alertView textFieldAtIndex:0];

  if (textField!=nil) {

      // 获得UITextField输入的内容

      NSString *content = textField.text;

      NSLog(@"%@",content);

  }

  // 获得索引为1的UITextField

  UITextField *textField1 = [alertView textFieldAtIndex:1];

  if (textField1!=nil) {

      // 获得UITextField输入的内容

      NSString *content = textField1.text;

      NSLog(@"%@",content);

  }

程序运行结果如下所示。

图18.14  UIAlertView登录样式

18.13 UIActionSheet

UIActionSheet和UIAlertView用法类似,区别在于UIActionSheet为用户提供了多个可选项,并且UIActionSheet需要指定它出现的位置。下面代码演示了如何创建一个UIActionSheet,并且在当前View中显示出来。

// 实例化UIActionSheet,并设置标题、代理和按钮等信息。

self.ac = [[UIActionSheet alloc]initWithTitle:@"Please select..." delegate:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"OK" otherButtonTitles:@"Other",@"Other2", nil];

[self.ac showInView:self.view];

程序运行结果如下所示。

图18.15  UIActionSheet

我们也可以为UIActionSheet设置代理,来判断那个按钮被点击。判断方法如下面代码所示。

// 实现代理协议

@interface AmakerViewController : UIViewController<UIActionSheetDelegate>

// 设置代理属性

self.ac.delegate = self;

// 覆盖代理方法

// 代理方法,判断那个按钮被点击

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{

    // 获得当前索引的按钮标题

    NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];

    if ([buttonTitle isEqualToString:@"OK"]) {

        NSLog(@"OK");

    }else if([buttonTitle isEqualToString:@"Cancel"]){

        NSLog(@"Cancel");

    }else if([buttonTitle isEqualToString:@"Other"]){

        NSLog(@"Other");

    }else if([buttonTitle isEqualToString:@"Other2"]){

        NSLog(@"Other2");

    }else{

        NSLog(@"Error");

    }

}

另外,我们可以设置UIActionSheet出现的位置,它除了可以从当前View出现外,还可以从TabBar、ToolBar和BarButtonItem出现。

// 2. 从TabBar显示

//AmakerAppDelegate *delegate = [UIApplication sharedApplication].delegate;

//[self.ac showFromTabBar:delegate.tb.tabBar];

// 3. 从ToolBar显示

//[self.ac showFromToolbar:self.tb];

// 4. 从BarButtonItem显示

[self.ac showFromBarButtonItem:self.item1 animated:YES];

18.14 UIImageView

UIImageView 可以在界面上显示图片或者动画,图片的来源可以是本地也可以是网络。下面的代码演示了如何展现一个UIImageView。

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 实例化UIImage

    UIImage *img = [UIImage imageNamed:@"test.jpg"];

    // 实例化UIImageView

    self.imageView = [[UIImageView alloc]initWithImage:img];

    // 设置UIImageView的frame属性

    self.imageView.frame = self.view.bounds;

    // 设置UIImageView的内容展示模式

    self.imageView.contentMode = UIViewContentModeScaleAspectFit;

    // 设置UIImageView的center属性

    self.imageView.center = self.view.center;

    [self.view addSubview:self.imageView];

}

程序运行结果如下所示。

图18.16  UIImageView

其中contentMode是一个非常重要的属性,设置了不同的内容模式显示效果会截然不同。下面是iOS SDK支持的内容模式。

typedef NS\_ENUM(NSInteger, UIViewContentMode) {

    UIViewContentModeScaleToFill, // 缩放至全屏

    UIViewContentModeScaleAspectFit,    // 缩放到合适比例

    UIViewContentModeRedraw,      // 重新绘制

    UIViewContentModeCenter,         // 中心对齐

    UIViewContentModeTop,  // 上对齐

    UIViewContentModeBottom,  // 底部对齐

    UIViewContentModeLeft, // 左对齐

    UIViewContentModeRight, // 右对齐

    UIViewContentModeTopLeft, // 左顶对齐

    UIViewContentModeTopRight, // 右顶对齐

    UIViewContentModeBottomLeft, // 左底对齐

    UIViewContentModeBottomRight,// 右底对齐

};

18.15 UIScrollView

UIScrollView 是一个滚动视图,用来实现当要显示的内容大于屏幕或组件尺寸时,滚动显示的功能。例如,显示大图片,大文本等内容时。下面的代码实现了滚动显示图片的功能。

- (void)viewDidLoad

{

    [super viewDidLoad];

    // 实例化UIImage

    UIImage *img = [UIImage imageNamed:@"test.jpg"];

    // 实例化UIImageView

    self.imgView = [[UIImageView alloc]initWithImage:img];

    // 实例化UIScrollView

 self.scroll = [[UIScrollView alloc]initWithFrame:self.view.bounds];

    // 设置是否显示水平垂直滚动条

    self.scroll.showsHorizontalScrollIndicator = YES;

    self.scroll.showsVerticalScrollIndicator = YES;

    // 设置代理属性

    self.scroll.delegate = self;

    // 添加图片到滚动视图

    [self.scroll addSubview:self.imgView];

    // 设置contentSize大小为图片大小

    self.scroll.contentSize = self.imgView.bounds.size;

    // 添加滚动视图到当前view

    [self.view addSubview:self.scroll];

}

程序运行结果如下所示。

图18.17  使用UIScrollView滚动显示图片

另外,可以为UIScrollView指定代理,来监控当前的滚动状态。实现步骤如下:

  1. 实现代理协议。
@interface AmakerViewController : UIViewController<UIScrollViewDelegate>

@end
  1. 设置代理属性。
self.scroll.delegate = self;
  1. 覆盖代理协议方法。
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;{

    NSLog(@"scrollViewWillBeginDragging...");

}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{

    NSLog(@"scrollViewDidScrollToTop...");

}

18.16 UIWebView

使用UIWebView可以实现一个Web浏览器,UIWebView可以实现加载静态HTML、动态URL地址、可以实现网页的导航,以及调用JavaScript等。

加载一个动态的URL地址的步骤如下:

  1. 实例化一个UIWebView。
self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
  1. 获得NSURLRequest实例。
NSString *str = @"http://www.baidu.com";

NSURL *url = [NSURL URLWithString:str];

NSURLRequest *request = [NSURLRequest requestWithURL:url];
  1. 调用loadRequest方法加载网页内容。
[self.webView loadRequest:request];

程序运行结果如下图所示。

图18.18  使用UIWebView动态加载网页

使用UIWebView也可以加载静态的HTML页面。

self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds];

  NSString *str = @"Hello <b>WebView</b>,<a href=http://developer.apple.com>More...</a>";

  [self.webView loadHTMLString:str baseURL:nil];

  [self.view addSubview:self.webView];

程序运行结果如下图所示。

图18.19  使用UIWebView动态加载网页

可以为UIWebView设置代理,来监控UIWebView的加载过程,下面的案例演示了如何在显示网页之前显示一个进度标示,当加载成功后加载网页。实现步骤如下所示:

  1. 实现UIWebViewDelegate协议。
@interface AmakerViewController : UIViewController<UIWebViewDelegate>
  1. 实例化UIWebView和UIActivityIndicatorView。
// 实例化UIWebView

self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds];

// 实例化UIActivityIndicatorView

self.aiv = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(20, 20, 100, 100)];

// 设置UIActivityIndicatorView样式

self.aiv.activityIndicatorViewStyle=UIActivityIndicatorViewStyleGray;

// 设置center属性为UIWebView的center

self.aiv.center = self.webView.center;
  1. 为UIWebView设置代理属性。
self.webView.delegate = self;
  1. 实例化NSURLRequest,并加载网页。
// 设置要访问的网络URL

NSString *str = @"http://www.any-phone.com";

// 实例化NSURL

NSURL *url = [NSURL URLWithString:str];

// 实例化NSURLRequest

NSURLRequest *request = [NSURLRequest requestWithURL:url];

// 加载页面

[self.webView loadRequest:request];

// 添加UIActivityIndicatorView到UIWebView

[self.webView addSubview:self.aiv];

[self.view addSubview:self.webView];
  1. 实现协议方法。
- (void)webViewDidStartLoad:(UIWebView *)webView{

  [self.aiv startAnimating];

  self.aiv.hidden = NO;

}

- (void)webViewDidFinishLoad:(UIWebView *)webView{

  [self.aiv stopAnimating];

  self.aiv.hidden = YES;

}
  1. 程序运行结果如下所示。

图18.20  为UIWebView设置代理

使用UIWebView还可以实现导航、刷新等操作,下面案例在界面上添加三个按钮,分别实现前进、后退、刷新。实现步骤如下:

  1. 在界面上添加四个按钮和一个输入框,并添加按钮的点击事件和输入框的属性。
  2. 在按钮的事件方法中分别实现加载、前进、后退和刷新的功能。
// 加载网页内容

- (IBAction)go:(id)sender {

    NSString *str = self.address.text;

    NSURL *url = [NSURL URLWithString:str];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [self.webView loadRequest:request];

}

// 前进

- (IBAction)forward:(id)sender {

    [self.webView goForward];

}

// 后退

- (IBAction)goback:(id)sender {

    [self.webView goBack];

}

// 刷新

- (IBAction)refresh:(id)sender {

    [self.webView reload];

}
  1. 程序运行结果如下图所示。

图18.21  UIWebView页面刷新和导航

UIWebView和网页的JavaScript之间可以相互通信,下面的案例在界面上添加一个按钮和一个UIWebView。当点击按钮时显示一个提示框。实现步骤如下:

  1. 在界面上添加一个按钮和一个UIWebView。
  2. 动态拼一个HTML和JavaScript,并使用UIWebView加载。
// 实例化NSMutableString

NSMutableString *mStr = [NSMutableString stringWithCapacity:20];

// 动态拼HTML和JavaScript

[mStr appendString:@"<html>"];

[mStr appendString:@"<head>"];

[mStr appendString:@"<script>"];

[mStr appendString:@"function showAlert(){alert(&#39;Hello&#39;);}"];

[mStr appendString:@"</script>"];

[mStr appendString:@"</head>"];

[mStr appendString:@"<body>"];

[mStr appendString:@"Test JavaScript."];

[mStr appendString:@"</body>"];

[mStr appendString:@"</html>"];

[self.webView loadHTMLString:mStr baseURL:nil];
  1. 在点击事件方法中加载JavaScript函数。
[self.webView stringByEvaluatingJavaScriptFromString:@"showAlert();"];
  1. 程序运行结果如下所示。

图18.22  UIWebView 和JavaScript通信

18.17 UIDatePicker

UIDatePicker 允许用户从滚轮控件中选择日期或时间,当我们选择新的日期或时间是,值改变事件UIControlEventValueChanged会被触发,我们可以在该方法中获得当前选择的日期或时间。下面的案例在界面上添加UIDatePicker控件和一个UILabel控件,当新的日期或时间被选择时,在值改变方法中获得当前值,并在UILabel中显示出来。程序实现步骤如下:

  1. 实例化UIDatePicker和UILabel并添加到当前view。
// 设置frame大小

CGRect frame = CGRectMake(0, 20, 320, 100);

// 实例化UIDatePicker控件

self.datePicker = [[UIDatePicker alloc]initWithFrame:frame];

// 设置显示模式

self.datePicker.datePickerMode = UIDatePickerModeDate;

// 添加到当前view

[self.view addSubview:self.datePicker];

// 设置UILabel的frame大小

CGRect frame2 = CGRectMake(0, 300, 320, 50);

// 实例化UILabel

self.label = [[UILabel alloc]initWithFrame:frame2];
  1. 给UIDatePicker添加点击事件。
// 添加事件
[self.datePicker addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];
  1. 实现事件方法,获得当前日期值在UILabel中显示。
-(IBAction)change:(id)sender{
    self.label.text = self.datePicker.date.description;
}
  1. 程序运行结果如下所示。

图18.23  UIDatePicker

在使用UIDatePicker中,有时候需要只显示日期,有时候需要显示时间,有时间日期和时间都需要显示。可以通过设置datePickerMode属性来改变。下面是iOS SDK提供的可选模式。

typedef NS\_ENUM(NSInteger, UIDatePickerMode) {

    UIDatePickerModeTime,       // 时间模式

    UIDatePickerModeDate,          // 日期模式

    UIDatePickerModeDateAndTime,    // 时间和日期模式

    UIDatePickerModeCountDownTimer // 计数计时器模式

};

18.18 UIPickerView

UIPickerView和UIDatePicker类似也是允许用户从滚轮视图中选择需要的数据,不过UIPickerView需要我们自己绑定数据,并实现数据源和代理的相应方法。下面实现一个UIPickerView视图并且当某个数据被选中时,使用UIAlertView显示选中的数据。实现步骤如下:

  1. 在.h中实现数据源和代理协议。
@interface AmakerViewController : UIViewController<

            UIPickerViewDataSource,

            UIPickerViewDelegate>

@end
  1. 在viewDidLoad方法中实例化UIPickerView并初始化数据源数据。
- (void)viewDidLoad

{

    [super viewDidLoad];

    // 初始化要显示的数据

    self.data = @[@"iOS",@"Android",@"WP7"];

    // 设置frame大小

    CGRect frame = CGRectMake(0, 0, 320, 100);

    // 实例化UIPickerView

 self.pickerView = [[UIPickerView alloc]initWithFrame:frame];

    // 设置代理

    self.pickerView.delegate = self;

    // 设置数据源

    self.pickerView.dataSource = self;

    // 添加到当前view

    [self.view addSubview:self.pickerView];

}
  1. 实现数据源方法和代理方法。
// 返回列数

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{

    return 1;

}

// 返回行数

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{

    return [self.data count];

}

// 绑定数据

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{

    return [self.data objectAtIndex:row];

}

// 当选择数据时,使用UIAlertView显示数据

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{

    NSString *str  = [self.data objectAtIndex:row];

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Select Item" message:str delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];

    [alert show];

}
  1. 程序运行结果如下所示。

图18.24  UIDatePicker