提示:
- UIView基类: UILabel,UIControl,UIScrollView,UIImageView,UIProgressView,UIAlertView,UIActionSheet,UIPickerView,UIWebView,UIToolBar,UISearchBar,UINavigationBar,UITabBar。
- UIControl基类: UIButton,UITextField,UISwitch,UISegmentedControl,UISlider,UIDatePicker,UIStepper。
- UIScrollView基类:UITextView,UITableView,UICollectionView。
一、UI控件概述
iOS所有的UI控件都集成了UIView,而UIView继承了UIResponder基类,UIResponder代表用户操作的响应者。
1、活动、静态和被动控件
iOS的UI控件大致可分为如下三类:
- (1)、活动控件:大部分活动控件都继承了UIControl基类,活动控件可以与用户交互,当用户操作活动控件时,该控件可以激发相应地事件,该事件就会激发该控件上为该事件绑定的事件处理方法。比如:UIButton。
- (2)、静态控件:静态控件通常只是继承了UIView,并不继承UIControl。静态控件只用于显示应用状态,用户不能对静态控件执行任何操作。比如:UILabel,UIImageView。
- (3)、被动控件:被动控件可以接受用户操作,但它们通常仅用于接受用户输入的值,知道用户输入完成为止,这些控件不会触发任何IBAction方法。典型的被动控件就是文本框,这些文本框可用于接受用户输入,但它们不会触发任何方法。
2、UIControl基类介绍
通过代码为UIControl的子类控件绑定事件处理方法。UIControl提供了如下常用的方法:
- (1)、- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
- (2)、- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
- (3)、- (NSArray *)actionsForTarget:(id)target forControlEvent:(UIControlEvents)controlEvent;
- (4)、- (NSSet *)allTargets;
- (5)、- (UIControlEvents)allControlEvents;
每个UI控件都有4中不同的状态,并且它们在任意时刻总处于且只能处于一下状态之一:
- (1)、普通:普通状态是所有控件的默认状态;
- (2)、高亮:当UI控件需要突出显示时,它处于高亮状态。对按钮来说,点用户手指放在按钮上时,它才处于高亮状态。
- (3)、禁用:当UI控件被关闭时,它处于禁用状态。禁用状态的UI控件是不可操作的,如果要禁用某个控件,可以在Interface Builder中取消选中Enabled复选框,或将控件的enabled属性设为NO;
- (4)、选中:选中状态通常用于标识该控件已启用或被选中。很多时候,选中状态与高亮状态比较相似,但UI控件可以在用户不再继续保持选中状态。
为了判断UI控件所处的状态,UIControl提供了系列属性来检测该控件的状态,包括是否可用、是否高亮等。这些状态可通过如下常用属性来判断:
- (1)、enabled:该属性判断该UIControl控件是否可用;
- (2)、selected:该属性判断该UIControl控件是否被选中;
- (3)、highlighted:该属性判断该UIControl控件是否高亮;
有些时候,如果我们需要定制用户触碰UIControl控件时的外观,可通过重写UIControl控件的如下方法实现:
- (1)、- (BOOL)beginTrackingWithTouch:(UITouch )touch withEvent:(UIEvent )event;当用户开始触碰该UIControl控件时,将会自动调用该方法,重写该方法即可在用户开始触碰该UIControl时定制该控件的外观;
- (2)、- (BOOL)continueTrackingWithTouch:(UITouch )touch withEvent:(UIEvent )event;当用户连续触碰该UIControl控件时,将会自动调用该方法,重写该方法即可在用户连续触碰该UIControl时定制该控件的外观;
- (3)、- (void)endTrackingWithTouch:(UITouch )touch withEvent:(UIEvent )event;当用户结束触碰该UIControl控件时,将会自动调用该方法,重写该方法即可在用户触碰该UIControl时定制该控件的外观;
二、按钮(UIButton)
按钮是最普通的UI控件,它继承了UIControl基类,默认属于活动控件,它可以与用户交互,并激发相应地事件处理方法。
(1)、Type(UIButtonType):该属性用于为按钮选择类型,该列表支持如下表项:
- ①、UIButtonTypeCustom:如果选择它,该按钮的外观行为主要依靠开发者的设置;
- ②、UIButtonTypeSystem:iOS默认的按钮风格。在早期版本的iOS中,该属性值为Rounded Rect,也就是对应于圆角矩形按钮;
- ③、UIButtonTypeDetailDisclosure:原本显示“>”图标(iOS7中显示i图标)的图形按钮,该按钮通常用于显示当前列表表项的详情;
- ④、UIButtonTypeInfoLight:显示“i”图标的图形按钮,该按钮通常用于显示简短的说明信息;
- ⑤、UIButtonTypeInfoDark:显示“i”图标的图形按钮,该按钮通常用于显示简短的说明信息;
⑥、UIButtonTypeContactAdd:显示黑色“+”图标的图形按钮,该按钮通常用于添加联系人;
提示:如果开发者需要开发自定义的按钮,建议在Type列表中选择Custom列表项,如果选择其他列表项,该按钮将具有自己的默认行为。
例如:
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
(2)、
State Config(UIControlState):该属性用于设置按钮的状态,UIButton具有以下4种状态:- ①、默认状态(UIControlStateNormal):按钮默认的状态就是该状态;
- ②、高亮状态(UIControlStateHighlighted):当用户触碰该按钮时,该按钮显示高亮状态;
- ③、选择状态(UIControlStateSelected):按钮被选中时的状态;
- ④、禁用状态(UIControlStateDisabled):按钮被禁用时的状态;
UIButton提供了如下方法来设置外观:
- ①、- (void)setTitle:(NSString *)title forState:(UIControlState)state;为不同状态的按钮设置文本标题;
- ②、- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;为不同状态的按钮设置文本标题的颜色;
- ③、- (void)setTitleShadowColor:(UIColor *)color forState:(UIControlState)state;为不同状态的按钮中文本的阴影设置颜色;
- ④、- (void)setImage:(UIImage *)image forState:(UIControlState)state;为不同状态的按钮设置图片;
- ⑤、- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;为不同状态的按钮设置背景颜色;
(3)、Title:该属性的第一个列表框可用于选择不同的文本方式,它支持Plain和Attributed两种设置方式,一般使用Plain方式设置即可。接下来的文本框内的字符串就是该按钮所显示的字符串,该文本框可输入任何字符串。
例如:[button setTitle:@"我是好人" forState:UIControlStateNormal];
(4)、Font:该属性用于控制该UILabel中文本的字体、字体大小和字体风格,如果单击该属性对应的输入框最右边的向上、向下箭头,Xcode即可改变该UILabel中文字的大小。
例如:button.titleLabel.font = [UIFont systemFontOfSize:27];
(5)、TextColor:该属性用于控制该按钮的文本标题的颜色。
例如:[button setTitleColor:[UIColor purpleColor] forState:UIControlStateNormal];
(6)、Shadow Color:该属性用于控制按钮的文本标题阴影颜色。
例如:[button setTitleShadowColor:[UIColor yellowColor] forState:UIControlStateNormal];
(7)、Image:该属性用于为该按钮设置一张图片,如果设置该属性,该按钮将会表现为一个图片按钮,前面为该按钮设置的Title属性将不会起作用。
例如:[button setImage:[UIImage imageNamed:@"slide_autoLogin_N.png"] forState:UIControlStateNormal];
(8)、Background:该属性用于为该按钮设置背景图片,如果希望按钮既有背景图片,又有文本标题,可通过该文本框来设置背景图片,而不是通过Image文本框来设置图片。
例如:[button setBackgroundImage:image forState:UIControlStateNormal];
(9)、Shadow Offset:该属性控制UILabel控件内的阴影文本与正常文本之间的偏移,该属性区需要指定Horizontal和Vertical两个属性值,分别指定阴影文本与正常文本在水平和垂直方向的偏移距。对于Horizontal属性值,如果该属性值大于0,阴影文本相对于正常文本向右偏移;如果该属性值小于0,阴影文本相对于正常文本向左偏移。对于Vertical属性值,如果该属性值大于0,阴影文本相当于正常文本向下偏移;如果该属性值小于0,阴影文本相当于正常文本向上偏移。
例如:[button setTitleShadowOffset:CGSizeMake(2, 2)];
(10)、Line Break:该属性控制对UILabel控件内文本的截断。
例如:[button setLineBreakMode:NSLineBreakByTruncatingMiddle];
(11)、Edge:该属性控制按钮的边界,其属性值是一个列表框,该列表框支持如下属性值:
- ①、Content:该属性设置以该按钮的内容作为按钮边界;
- ②、Title:该属性值设置以该按钮的标题文本作为按钮边界;
③、Image:该属性设置以该按钮的图片作为按钮边界;
例如:[button setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; [button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; [button setContentEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
(12)、Inset:该属性控制按钮的边界间距(相当于在按钮四周留白,这些区域既不会显示图片,也不会显示按钮文本)。该属性支持Top(上)、Bottom(下)、Left(左)和Right(右)4个值,这四个值分别代表按钮上、下、左、右的间距。
(13)、showsTouchWhenHighlighted设置为YES的时候,按钮点击时会发光;
例如:button.showsTouchWhenHighlighted = YES;
(14)、设置按钮文本的位置(UIControlContentHorizontalAlignment)( UIControlContentVerticalAlignment)
例如:水平方向:button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
垂直方向:
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; button.contentVerticalAlignment = UIControlContentVerticalAlignmentBottom; button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
(15)、获取按钮的文字
例如:NSString* title = [button titleForState:UIControlStateNormal];
(16)、获取按钮的文字颜色
例如:UIColor* color = [button titleColorForState:UIControlStateNormal];
(17)、获取按钮内部的小图片
例如:UIImage* image = [button imageForState:UIControlStateNormal];
(18)、获取按钮的背景图片
例如:UIImage* backImage = [button backgroundImageForState:UIControlStateNormal];
三、文本框(UITextField)
文本框控件(UITextField)继承了UIControl控件,也可作为活动控件使用。
之前介绍过的属性
textField.text = @"aaaa";
textField.textColor = [UIColor redColor];
textField.font = [UIFont systemFontOfSize:20];
textField.textAlignment = NSTextAlignmentCenter;
(1)、Placeholder:当用户还没有在该文本框内输入任何内容时,该文本框内将会显示一段灰色的文本,用来作为该文本框的提示消息。
例如:textField.placeholder = @"请输入名字";
(2)、Border Style(UITextBorderStyle):该属性用于设置该文本框的边框分风格,iOS的文本框支持4种常见的风格。
例如:textField.borderStyle = UITextBorderStyleNone; textField.borderStyle = UITextBorderStyleLine; textField.borderStyle = UITextBorderStyleBezel; textField.borderStyle = UITextBorderStyleRoundedRect;
(3)、Clear Button(UITextFieldViewMode):该属性控制文本是否显示清除按钮。
Clear Button属性用于控制合适显示清除按钮,该属性列表框支持如下列表项:- ①、Never Appears:从不显示清除按钮;
- ②、Appears while editing:当编辑内容时显示清除按钮;
- ③、Appears unless editing:除了编辑之外,都会显示清除按钮;
④、Is always visible:清除按钮一直可见;
例如:textField.clearButtonMode = UITextFieldViewModeNever;//重不出现 textField.clearButtonMode = UITextFieldViewModeWhileEditing;//编辑时出现 textField.clearButtonMode = UITextFieldViewModeUnlessEditing;//除了编辑外都出现 textField.clearButtonMode = UITextFieldViewModeAlways;//一直出现
在Clear Button区,还有一个Clear when editing begins复选框,如果勾选该复选框,表明每次用户重新开始编辑该文本框内容时,都会自动清除该文本框内原有的内容;
例如:textField.clearsOnBeginEditing = YES;
(4)、Min Font Size与Adjust to Fit:Adjust to Fit复选框用于指定文本的字体大小是否随着文本框的贱笑而自动缩小。勾选该复选框可以确保整个文本在文本框内总是可见,即使文本长度超出了文本框的大小。在文本框内文本字体自动变小的过程中,Min Font Size属性值则指定该文本框内文本的最小值,这样就可以保证文本框内文本不会因为太小而看不见;
例如:textField.adjustsFontSizeToFitWidth = YES; textField.minimumFontSize = 4.0;
(5)、Capitalization(UITextAutocapitalizationType):该属性控制是否转换该文本框输入文本的大小写,该属性支持如下属性值:
- ①、None:不自动切换大小写;
- ②、Words:自动将该文本框内每个单词的首字母转换为大写;
- ③、Sentence:自动将该文本框内每个句子的首字母转换为大写;
④、All Characters:自动将文本框内每个字母转为大写;
例如:textField.autocapitalizationType = UITextAutocapitalizationTypeNone;//不自动大写 textField.autocapitalizationType = UITextAutocapitalizationTypeWords;//单词首字母大写 textField.autocapitalizationType = UITextAutocapitalizationTypeSentences;//句子的首字母大写 textField.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;//所有字母都大写
(6)、Correction(UITextAutocorrectionType):该属性控制是否对文本框的文本进行自动更正。它支持如下属性值:
- ①、YES:自动更正文本框内的文本;
②、NO:不自动更正文本框内的文本;
例如:textField.autocorrectionType = UITextAutocorrectionTypeDefault;//默认 textField.autocorrectionType = UITextAutocorrectionTypeNo;//不自动纠错 textField.autocorrectionType = UITextAutocorrectionTypeYes;//自动纠错
(7)、Keyboard(UIKeyboardType):该属性用于设置该文本框关联的键盘——由于iphone和ipad等设备都没有提供物理键盘,因此,当用户开始编辑该文本框内容时,程序将控制系统显示一个虚拟键盘,该属性则用于这是到底显示哪一种虚拟键盘。它支持如下常用的属性值:
- ①、Default:显示默认的虚拟键盘;
- ②、ASCII Capable:显示英文字母键盘;
- ③、Numbers and Punctuation:显示数字和标点符号键盘;
- ④、Number Pad:显示数字键盘;
- ⑤、Phone Pad:显示电话拨号键盘;
- ⑥、E-mail Address:显示输入E-mail地址的虚拟键盘;
⑦、Decimal Pad:显示可输入数字和小数字的虚拟键盘 ;
例如:textField.keyboardType = UIKeyboardTypeDefault;//默认键盘,支持所有字符 textField.keyboardType = UIKeyboardTypeASCIICapable;//支持ASCII的默认键盘 textField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;//标准电话键盘,支持+*#字符 textField.keyboardType = UIKeyboardTypeNumberPad;//数字键盘 textField.keyboardType = UIKeyboardTypePhonePad;//电话键盘 textField.keyboardType = UIKeyboardTypeEmailAddress;//用于输入电子 邮件地址的键盘 textField.keyboardType = UIKeyboardTypeDecimalPad;//数字键盘 有数字和小数点 textField.keyboardType = UIKeyboardTypeURL;//URL键盘,支持.com按钮 只支持URL字符 textField.keyboardType = UIKeyboardTypeNamePhonePad;//电话键盘,也支持输入人名 textField.keyboardType = UIKeyboardTypeTwitter;//优化的键盘,方便输入@、#字符 textField.keyboardType = UIKeyboardTypeWebSearch; textField.keyboardType = UIKeyboardTypeAlphabet;
(8)、Return Key(UIReturnKeyType):该属性用于设置当用户在文本框内按下return键(位于虚拟键盘右下角的按键)后的行为,比如,当我们在Safari的搜索框下输入文本时,按下return键后将会直接打开搜索。对于普通的需要与其他控件共享屏幕的文本框,按下return代表输入完成,因此,通常在该列表中选择Done;
例如:textField.returnKeyType = UIReturnKeyDefault;//默认 灰色按钮,标有Return textField.returnKeyType = UIReturnKeyGo;//标有Go的蓝色按钮 textField.returnKeyType = UIReturnKeyGoogle;//标有Google的蓝色按钮,用语搜索 textField.returnKeyType = UIReturnKeyJoin;//标有Join的蓝色按钮 textField.returnKeyType = UIReturnKeyNext;//标有Next的蓝色按钮 textField.returnKeyType = UIReturnKeyRoute;//标有Route的蓝色按钮 textField.returnKeyType = UIReturnKeySearch;//标有Search的蓝色按钮 textField.returnKeyType = UIReturnKeySend;//标有Send的蓝色按钮 textField.returnKeyType = UIReturnKeyYahoo;//标有Yahoo的蓝色按钮 textField.returnKeyType = UIReturnKeyYahoo;//标有Yahoo的蓝色按钮 textField.returnKeyType = UIReturnKeyDone;// textField.returnKeyType = UIReturnKeyEmergencyCall;//紧急呼叫按钮
Return Key列表框下卖弄还有如下两个复选框:
- ①、Auto-enable Return Key:如果勾选该复选框,那么虚拟键盘上的return键默认是禁用的;只有当该用户在该文本框内输入内容后return键才会变为可用。通过这种方式可强制用户必须在该文本框内输入内容;
②、Secure:如果勾选该复选框,当用户在该文本框内输入内容时,文本框将以黑点来代替用户输入的字符。如果勾选该复选框用于设置密码输入框。
例如:textField.secureTextEntry = YES;
(9)、文本框外观
例如:textField.keyboardAppearance=UIKeyboardAppearanceDefault;//默认外观,浅灰色 textField.keyboardAppearance=UIKeyboardAppearanceDark; textField.keyboardAppearance=UIKeyboardAppearanceLight; textField.keyboardAppearance=UIKeyboardAppearanceAlert;//深灰 石墨色
(10)、设置代理方式
例如:@interface RootViewController : UIViewController<UITextFieldDelegate> textField.delegate = self;
(11)、添加时时监听
[_MyTextField addTarget:self action:@selector(edit:) forControlEvents:UIControlEventEditingChanged];
(12)、委托方法UITextFieldDelegate
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
//返回一个BOOL值,指定是否循序文本字段开始编辑
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
//开始编辑时触发,文本字段将成为first responder
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
//返回BOOL值,指定是否允许文本字段结束编辑,当编辑结束,文本字段会让出first responder
//要想在用户结束编辑时阻止文本字段消失,可以返回NO
//这对一些文本字段必须始终保持活跃状态的程序很有用,比如即时消息
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
//返回一个BOOL值指明是否允许根据用户请求清除内容
//可以设置在特定条件下才允许清除内容
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
//string就是此时输入的那个字符 textField就是此时正在输入的那个输入框 返回YES就是可以改变输入框的值 NO相反
if ([string isEqualToString:@"\n"])//按会车可以改变
{
return YES;
}
NSString* toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string]; //得到输入框的内容
if (_MyTextField == textField) //判断是否时我们想要限定的那个输入框
{
if ([toBeString length] > 20) { //如果输入框内容大于20则弹出警告
textField.text = [toBeString substringToIndex:20];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"超过最大字数不能输入了" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[alert show];
return NO;
}
}
//当用户使用自动更正功能,把输入的文字修改为推荐的文字时,就会调用这个方法。
//这对于想要加入撤销选项的应用程序特别有用
//可以跟踪字段内所做的最后一次修改,也可以对所有编辑做日志记录,用作审计用途。
//要防止文字被改变可以返回NO
//这个方法的参数中有一个NSRange对象,指明了被改变文字的位置,建议修改的文本也在其中
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField{
//点击文本中的清除按钮,返回是否清楚所有内容
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
//返回一个BOOL值,指明是否允许在按下回车键时结束编辑
//如果允许要调用resignFirstResponder 方法,这回导致结束编辑,而键盘会被收起[textField resignFirstResponder];
[textField resignFirstResponder];
return YES;
}
- (13)重新绘制行为
除了UITextField对象的风格选项,你还可以定制化UITextField对象,为他添加许多不同的重写方法,来改变文本字段的显示行为。这些方法都会返回一个CGRect结构,制定了文本字段每个部件的边界范围。以下方法都可以重写。
#import "MyTF.h"
@implementation MyTF
- (CGRect)textRectForBounds:(CGRect)bounds{
//重写来重置文字区域
return CGRectMake(0, 20, 320, 20);
}
- (void)drawTextInRect:(CGRect)rect{
//改变绘文字属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了.
[super drawTextInRect:rect];
}
- (CGRect)placeholderRectForBounds:(CGRect)bounds{
//重写来重置占位符区域
return CGRectMake(0, 0, 100, 40);
}
- (void)drawPlaceholderInRect:(CGRect)rect{
//重写改变绘制占位符属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了.
}
- (CGRect)borderRectForBounds:(CGRect)bounds{
//重写来重置边缘区域
return CGRectMake(0, 0, 0, 0);
}
- (CGRect)editingRectForBounds:(CGRect)bounds{
//重写来重置编辑区域
return CGRectMake(20, 0, 100, 40);
}
- (CGRect)clearButtonRectForBounds:(CGRect)bounds{
//重写来重置clearButton位置,改变size可能导致button的图片失真
return CGRectMake(300, 0, 20, 40);
}
@end
(14)对UITextField进行监听,通知中心
UITextField派生自UIControl,所以UIControl类中的通知系统在文本字段中也可以使用。除了UIControl类的标准事件,你还可以使用下列UITextField类特有的事件:
例如:NSNotificationCenter* cationCenter = [NSNotificationCenter defaultCenter]; [cationCenter addObserver:self selector:@selector(didBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil]; [cationCenter addObserver:self selector:@selector(didChange:) name:UITextFieldTextDidChangeNotification object:nil]; [cationCenter addObserver:self selector:@selector(didEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
①、完成输入后关闭键盘
例如:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
//返回一个BOOL值,指明是否允许在按下回车键时结束编辑
//如果允许要调用resignFirstResponder 方法,这回导致结束编辑,而键盘会被收起[textField resignFirstResponder];
[textField resignFirstResponder];
return YES;
}
②、触碰背景关闭键盘
可以给背景添加UIControl控件,然后添加触碰事件。
四、多行文本控件(UITextView)
多行文本控件(UITextView)继承了UIScrollView:UIView控件,因此它默认带有滚动条。
UITextView与UITextField都是文本编辑、显示控件。大部分属性都是相同的,区别有三点:
- (1)、UITextView是一个多行文本框,而UITextField只是单行文本框;
- (2)、UITextView没有继承UIControl控件,因此不能在Interface Builder中为该控件的时间绑定IBAction事件处理方法;也不能调用UIControl提供的addTarget:action:forControlEvents:方法来绑定事件处理方法;
(3)、UITextView继承了UIScrollView,因此它具有UIScrollView的功能和行为;
UITextView的各种属性:(1)、Text:设置文本框默认显示的文本,下面的输入框设置文本框文本的内容
例如:textView.text = @"我是好人”;
(2)、Color:设置文本框文本的颜色
例如:textView.textColor = [UIColor redColor];
(3)、Font:设置文本框文本的字体
例如:textView.font = [UIFont systemFontOfSize:13];
(4)、Alignment:设置文本框内文本的对齐方式
例如:textView.textAlignment = NSTextAlignmentCenter;
(5)、Behavior:该下面与连个复选框
①、Editable:设置文本框是否可编辑
例如:textView.editable = YES;
- ②、Selectable:设置文本框是否可选择;
- (6)、Detection:设置自动检测文本框的那些特殊内容
- (7)、Capitalization:设置自动大写文本框内文本的风格
- (8)、Correction:设置文本框的自动更正风格;
(9)、Keyboard Type(UIKeyboardType):设置文本框关联的键盘类型
例如:textView.keyboardType = UIKeyboardTypeDefault;
类型同UITextField
(10)、Return Key(UIReturnKeyType):这是虚拟键盘上回车键的文本
例如:textView.returnKeyType = UIReturnKeyDefault;
类型同UITextField
(11)对UITextView进行监听,通知中心
使用下列UITextView类特有的事件:
例如:NSNotificationCenter* cationCenter = [NSNotificationCenter defaultCenter]; [cationCenter addObserver:self selector:@selector(didBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil]; [cationCenter addObserver:self selector:@selector(didChange:) name:UITextViewTextDidChangeNotification object:nil]; [cationCenter addObserver:self selector:@selector(didEndEditing:) name:UITextViewTextDidEndEditingNotification object:nil];
(12)、textView的选中范围
例如:NSLog(@"%d",textView.selectedRange.length);
下面先介绍UIScrollView支持的各种属性:
1、UIScrollView支持的属性
UIScrollView代表一个可滚动的额控件,该控件允许用户拖动手指来滑动该控件中的内容。通过滚动控件的支持,UIScrollView可以显示多个屏幕的内容,甚至可以显示超过能放在内容中的内容。
UIScrollView默认已经实现并处理放大和缩小手势,因此,UIScrollView及其子类默认可以通过手指的捏合动作来放大、缩小;
UIScrollView支持如下三个控制显示区域的属性:
(1)、contentSize:该属性是一个CGSize类型的值,CGSize并不是类,而是一个结构体,它包含width、height两个成员变量,用于代表UIScrollView所需要显示内容的完整宽度和完整高度;
例如:_MyScrollView.contentSize = CGSizeMake(320 * 4, 480);
(2)、contentInset:该属性是一个UIEdgeInsets类型的值,UIEdgeInsets并不是类,而是一个结构体,它包含top、left、bottom、right四个成员变量,分别代表UIScrollView所需要显示内容在上、左、下、右的留白。
例如:_MyScrollView.contentInset = UIEdgeInsetsMake(20, 20, 20, 20);
(3)、contentOffSet:该属性是一个CGPoint类型的值,CGPoint也是一个结构体,它包含x、y两个成员变量,用于代表该UIScrollView的可是区域在显示内容上滑动的距离。
例如:_MyScrollView.contentOffset = CGPointMake(100, 0);
下面来介绍Xcode属性检查面板中为UIScrollView提供的属性:
(1)、Scroll Indicators:
下面有两个复选框:①、Shows Horizontal Indicator:如果勾选该复选框(该复选框对应该控件的showsHorizontalScrollIndicator属性),当用户水平滑动该UIScrollView控件时,该控件将会显示水平滑动条。
例如:_MyScrollView.showsHorizontalScrollIndicator = NO;
②、Shows Vertical Indicator:如果勾选该复选框(该复选框对应该控件的showsVerticalScrollIndicator属性),当用户垂直滑动该UIScrollView控件时,该控件将会显示垂直滑动条。
例如:_MyScrollView.showsVerticalScrollIndicator = NO;
(2)、Scrolling:
下面有三个复选框:①、Scrolling Enabled:只有勾选该复选框(该复选框对应该控件的scrollEnabled属性),该UIScrollView控件才能滚动它包含的内容;
例如:_MyScrollView.scrollEnabled = YES;
②、Paging Enabled:只有勾选该复选框(该复选框对应该控件的pagingEnabled属性),该UIScrollView将会对它所有包含的内容进行分页。也就是说,每当用户滚动该控件时,不能随心所欲的停留,只能停留在UIScrollView按分页逻辑分出的某一“页”上;
例如:_MyScrollView.pagingEnabled = YES;
③、Direction Lock Enabled:如果没有勾选该复选框(该复选框对应该控件的directionalLockEnabled属性),用户可以同时在水平和垂直方向上滑动该UIScrollView;如果勾选该复选框,当用户第一次在水平或垂直方向滑动该UIScrollView之后,系统将不会允许在其他方向上滚动该UIScrollView控件;
例如:_MyScrollView.directionalLockEnabled = YES;
(3)、Bounce:
该属性提供了三个可勾选的复选框,其含义如下:①、Bounces:如果勾选该复选框(该复选框对应该控件的Bounces属性),则该UIScrollView控件是有“弹性”的,当用户拖动该控件内容遇到边界时,该控件会显示“弹回”效果;如果没有勾选该复选框,点那个用户拖动该控件的内容遇到边界时会立即停止;
例如:_MyScrollView.bounces = YES;
②、Bounce Horizontally:如果勾选该复选框(该复选框对应该控件的alwaysBounceHorizontal属性),则该UIScrollView控件在水平方向上是有“弹性”的,如果还勾选了Bounces复选框,那么即使在水平方向已经到了内容边界,用户也可像拉伸橡皮筋一样滑动该控件的内容,但控件的内容会自动弹回去;
例如:_MyScrollView.alwaysBounceHorizontal = NO;
③、Bounce Vertically:如果勾选该复选框(该复选框对应该控件的alwaysBounceVertically属性),则该UIScrollView控件在垂直方向上是有“弹性”的,如果还勾选了Bounces复选框,那么即使在垂直方向已经到了内容边界,用户也可像拉伸橡皮筋一样滑动该控件的内容,但控件的内容会自动弹回去;
例如:_MyScrollView.alwaysBounceVertical = NO;
(4)、zoom:
该属性区提供了一下两个文本框供用户填写:①、Min:设置该UIScrollView最小的可缩放比例。(此处的设置对应于该控件的minimumZoomScale属性);
例如:_MyScrollView.minimumZoomScale = 0.5;
②、Max:设置该UIScrollView最大的可缩放比例。(此处的设置对应于该控件的maximumZoomScale属性);
例如:_MyScrollView.minimumZoomScale = 0.5;
(5)、设置该UIScrollView控件的滑动条的类型(UIScrollViewIndicatorStyle)
例如:_MyScrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack;
(6)、Touch:
该属性区提供了如下三个复选框:①、Bounces Zoom:该复选框控制该UIScrollView对内容进行缩放时是否具有弹性(该复选框对应该控件的BouncesZoom属性)。如果勾选该复选框,当用户通过手势对该UIScrollView进行缩放时,如果缩放比例超过该控件的minimunZoomScale属性,或者放大比例超过maximunZoomScale属性,该控件将会短暂的超过该缩放限制,然后迅速弹回最小缩放比例或最大缩放比例;
例如:_MyScrollView.bouncesZoom = YES;
②、Delays Content Touches:如果勾选该复选框(该复选框对应该控件的delaysContentTouches属性),该UIScrollView将延迟到真正确定滚动意图才去处理触碰手势。如果没有勾选该复选框,只要用户触碰该控件,该UIScrollView立即调用touchesShouldBegin:withEvent:inContentView方法处理滚动;
例如:_MyScrollView.delaysContentTouches = YES;
③、Cancelable Content Touches:如果勾选该复选框(该复选框对应该控件的CancelContentTouches属性),如果该UIScrollView中的内容已经跟踪用户手指触碰动作的情况下,且用户拖动手指以启动一个滚动事件,该UIScrollView控件将会调用touchesCancelled:withEvent:方法,并将该手指拖动事件当成滚动该UIScrollView控件。但如果没有勾选该复选框,只要该UIScrollView控件的内容已经跟踪用户手指触碰事件,将不会理会手指在该控件上的其他移动。通常建议勾选该复选框。即假如你设置canCancelContentTouches为YES,那么当你在UIScrollView上面放置任何子视图的时候,当你在子视图上移动手指的时候,UIScrollView会给子视图发送touchCancel的消息。而如果该属性设置为NO,ScrollView本身不 处理这个消息,全部交给子视图处理。
例如:_MyScrollView.canCancelContentTouches = YES;
附加:例子
单独图片添加手势实现放大缩小功能
- (void)pinch:(UIPinchGestureRecognizer *)sender{
//将试图放在页面最上面
[self.view bringSubviewToFront:[(UIPinchGestureRecognizer*)sender view]];
//当手指离开屏幕时,将lastscale设置为1.0
if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
lastScale = 1.0;
return;
}
CGFloat scale = 1.0 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];
lastScale = [(UIPinchGestureRecognizer*)sender scale];
}
利用UIScrollView实现图片的放大缩小功能
RootViewController.h的接口部分
#import <UIKit/UIKit.h>
@interface RootViewController : UIViewController<UIScrollViewDelegate>{
UIScrollView *_scrollview;
UIImageView *_imageview;
}
@end
RootViewController.m的实现部分
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//添加 UIScrollView
//设置 UIScrollView的位置与屏幕大小相同
_scrollview=[[UIScrollView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_scrollview];
//2添加图片
//有两种方式
//(1)一般方式
// UIImageView *imageview=[[UIImageView alloc]init];
// UIImage *image=[UIImage imageNamed:@"minion"];
// imageview.image=image;
// imageview.frame=CGRectMake(0, 0, image.size.width, image.size.height);
//(2)使用构造方法
UIImage *image=[UIImage imageNamed:@"1.png"];
_imageview=[[UIImageView alloc]initWithFrame:_scrollview.bounds];
_imageview.image = image;
//调用initWithImage:方法,它创建出来的imageview的宽高和图片的宽高一样
[_scrollview addSubview:_imageview];
//设置UIScrollView的滚动范围和图片的真实尺寸一致
_scrollview.contentSize= self.view.bounds.size;
//设置实现缩放
//设置代理scrollview的代理对象
_scrollview.delegate=self;
//设置最大伸缩比例
_scrollview.maximumZoomScale=2.0;
//设置最小伸缩比例
_scrollview.minimumZoomScale=0.5;
}
#pragma mark UIScrollViewDelegate
//告诉scrollview要缩放的是哪个子控件
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return _imageview;
}
//缩放完毕的时候调
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view{
_imageview.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
}
//正在缩放的时候调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
_imageview.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
}
@end
- (7)、双击缩小时常用方法
- ①、- (void)setZoomScale:(CGFloat)scale animated:(BOOL)animated;
//这种方法调整的zoomScale进行必要的缩放以便使内容视图成为由矩形定义的区域 - ②、- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated;
//把从scrollView里截取的矩形区域缩放到整个scrollView当前可视的frame里面。所以如果截取的区域大于scrollView的frame时,图片缩小。如果截取区域小于frame,会看到图片放大。一般情况下rect需要自己计算出来。
- ①、- (void)setZoomScale:(CGFloat)scale animated:(BOOL)animated;
(8)、UIScrollViewDelegate
#pragma mark UIScrollViewDelegate
①、缩放Delegate
//告诉scrollview要缩放的是哪个子控件 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; //缩放开始的时候调用 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view; //正在缩放的时候调用 - (void)scrollViewDidZoom:(UIScrollView *)scrollView; //缩放完毕的时候调 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale;
②、滑动的时候调用
//只要view有滚动(不管是拖、拉、放大、缩小等导致)都会执行此函数 - (void)scrollViewDidScroll:(UIScrollView *)scrollView; //将要开始拖拽,手指已经放在view上并准备拖动的那一刻 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; //将要结束拖拽,手指已拖动过view并准备离开手指的那一刻,注意:当属性pagingEnabled为YES时,此函数不被调用 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset; //已经结束拖拽,手指刚离开view的那一刻 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; //view将要开始减速,view滑动之后有惯性 - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView; //view已经停止滚动 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; //有动画时调用 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView; //如果你不是完全滚动到滚轴视图的顶部,你可以轻点状态栏,那个可视的滚轴视图会一直滚动到顶部,那是默认行为,你可以通过该方法返回NO来关闭它 - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView; //判断是哪一个可以返回滚轴视图的顶部 当有多个UIScrollView时,必须保证有且只有一个UIScrollView才能有效 - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
2、使用委托对象处理UITextView
UITextViewDelegate协议定义如下方法:
- (1)、- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;//用户将要开始编辑该UITextView的内容时会激发该方法
- (2)、- (void)textViewDidBeginEditing:(UITextView *)textView;//用户开始编辑该UITextView的内容时会激发该方法
- (3)、- (BOOL)textViewShouldEndEditing:(UITextView *)textView;//用户将要结束编辑该UITextView的内容时会激发该方法
- (4)、- (void)textViewDidEndEditing:(UITextView *)textView;//用户结束编辑该UITextView的内容时会激发该方法
- (5)、- (BOOL)textView:(UITextView )textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString )text;//该UITextView内指定范围内的文本内容将要被替换时激发该方法
- (6)、- (void)textViewDidChange:(UITextView *)textView;//该UITextView中包含的文本内容发生改变时会激发该方法
- (7)、- (void)textViewDidChangeSelection:(UITextView *)textView;//当用户选中该UITextView控件内某些文本时会激发该方法
3、关闭虚拟键盘
- (1)、如果程序界面带导航条,可通过导航条来关闭虚拟键盘;
- (2)、通过自定义虚拟键盘附件来关闭虚拟键盘;
4、自定义选择内容后的菜单
当用户在UITextView中选择部分内容后,系统默认会系那是几个菜单项,实际上,用户也可以添加自己的菜单。
例如:
//首先创建两个菜单选项
UIMenuItem* mailShare = [[UIMenuItem alloc]initWithTitle:@"邮件分享" action:@selector(mailShare:)];
UIMenuItem* weiboShare = [[UIMenuItem alloc]initWithTitle:@"微博分享" action:@selector(weiboShare:)];
UIMenuController* menu = [UIMenuController sharedMenuController];
[menu setMenuItems:[NSArray arrayWithObjects:mailShare,weiboShare, nil]];
//重写UIResponder的canPerformAction:withSender:方法
//当该方法返回YES时,该界面将会显示该Action对应的控件
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
//如果Action是mailShare:或weiboShare:方法
if (action == @selector(mailShare:)||action == @selector(weiboShare:)) {
//如果textView选中的内容长度大于0,返回YES,
//当该方法返回YES时,该Action对应的控件将会显示出来
if (textView.selectedRange.length > 0) {
return YES;
}
}
return NO;
}
五、开关按钮(UISwitch)
UISwitch控件代表一个开关按钮,类似于传统的物理开关。UISwitch继承了UIControl基类,因此可以当成活动控件使用,通过ValueChanged事件来检测开关按钮的状态切换;
(1)、State:设置该开关按钮的初始状态;
例如:MySwitch.on = YES;
(2)、On Tint:设置该按钮处于打开状态的颜色;
例如:MySwitch.onTintColor = [UIColor redColor];
(3)、Thumb Tint:设置该按钮的颜色;
例如:MySwitch.thumbTintColor = [UIColor purpleColor];
(4)、On Image:设置按钮处于打开状态时的图片
例如:MySwitch.onImage = image;
(5)、Off Image:设置按钮处于关闭状态时的图片
例如:MySwitch.offImage = image;
(6)、实现基类UIControl的方法:
例如:[MySwitch addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventValueChanged];
六、分段控件(UISegmentedControl)
分段控件提供一栏按钮,当每次只能激活其中一个按钮。UISegmentedControl控件也继承了UIControl,因此它也可以作为活动控件:
SegmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"",@"",@"", nil]];
1、Style:该属性支持一个列表项,该列表可支持如下三个列表项;
- ①、Plain:如果选择该列表项,该分段控件将使用最普通的风格;
- ②、Bordered:如果选择该列表项,该分段控件将在最普通的风格周围添加一圈边框;
③、Bar:如果选择该列表项,该分段控件将会使用工具条风格;
例如:SegmentedControl.segmentedControlStyle = UISegmentedControlStylePlain;
2、State:该属性区提供了一个Momentary复选框,u如果勾选该复选框,那么该分段控件将不会保存控件的状态,当用户点击分段控件的某个分段时,该控件只在用户点击时高亮显示,用户点击结束时,该分段控件不会继续高亮显示用户点击的那个分段。
例如:SegmentedControl.momentary = NO;
3、Tint:该属性的值是一个颜色选择框,用于设置该分段控件被选中分段的高亮颜色;
例如:SegmentedControl.tintColor = [UIColor redColor];
- 4、Segments:该属性的值是一个整数,用于控制该分段控件总共被分为几段;
注意:该属性只读不写
例如:
NSLog(@"number = %lu",(unsigned long)SegmentedControl.numberOfSegments);
- 5、Segment:该属性是一个列表框,用于徐那种指定的分段。该列表框所包含的列表项会动态改变,如果开发者将前面的Segments设置为4,那么该列表框将包含四个选项,供开发者选择指定的列表项进行配置;
该列表框中Segment 0代表第一个分段,Segment 1代表第二个分段,以此类推。 6、Title:该属性用于为Segment列表框中选择中的分段设置标题。随着前面Segment列表框所选中分段的不同,此处的Title用于为不同的分段设置标题;
例如:[SegmentedControl setTitle:@"11" forSegmentAtIndex:1];
7、Image:该属性用于为Segment列表框中选中的分段设置图片,随着前面的Segment列表框所选中分段的不同,此处的Image用于为不同的分段设置图片;
例如:[SegmentedControl setImage:image forSegmentAtIndex:1];
8、Behavior:该属性包含以下两个复选框。
①、Enabled:该属性用于控制Segment列表框中的分段是否可用。如果取消勾选该复选框,那么Segment列表框中选中的分段将变为不可用。
例如:[SegmentedControl setEnabled:NO forSegmentAtIndex:1];
②、Selected:该属性用于控制Segment列表框中选中的分段是否被选中。如果勾选该复选框,那么Segment列表框中的分段将变成高亮被选中状态;
例如:[SegmentedControl setSelectedSegmentIndex:1];
1、通过分段控件控制背景颜色
例如:
[SegmentedControl addTarget:self action:@selector(segmentControl:) forControlEvents:UIControlEventValueChanged];
- (void)segmentControl:(UISegmentedControl *)segmentControl{
switch ([segmentControl selectedSegmentIndex]) {
case 0:
self.view.backgroundColor = [UIColor redColor];
break;
case 1:
self.view.backgroundColor = [UIColor yellowColor];
break;
case 2:
self.view.backgroundColor = [UIColor purpleColor];
break;
default:
break;
}
}
2、动态删除、添加分段
例如:
①、添加:
[SegmentedControl insertSegmentWithImage:image atIndex:1 animated:YES]; [SegmentedControl insertSegmentWithTitle:@"2" atIndex:1 animated:YES];
②、删除:
例如:[SegmentedControl removeSegmentAtIndex:1 animated:YES];
七、图像控件(UIImageView)
UIImageView代表一个图片显示控件,他直接继承了UIView基类,UIImageView只能作为图片的显示控件,不能接受用户输入,也不能与用户交互,他只是一个静态控件。
创建UIImageView对象之后,接下来可以通过以下两个属性访问或设置该控件显示的图片:
- ①、image:访问或设置该控件显示的图片;
- ②、highlightedImage:访问或设置该控件处于高度状态时显示的图片;
除此之外,UIImageView还可以使用动画显示一组图片,使用UIImageView动画显示一组图片的属性和方法如下:
- (1)、animationImages:访问或者设置该UIImageView需要动画显示的多张图片,该属性的值是一个NSArray;
- (2)、highlightedAnimationImages:访问或者设置该UIImageView高亮状态下需要动画显示的多张图片,该属性值是一个NSArray;
- (3)、animationDuration:访问或者设置该UIImageView的动画持续时间;
- (4)、animationRepeatCount:访问或者设置该UIImageView的动画重复次数;
- (5)、startAnimating:开始播放动画;
- (6)、stopAnimating:停止播放动画;
- (7)、isAnimating:该方法判断该UIImageView是否在播放动画;
UIImageView的属性:
1、image:设置该控件显示的图片
例如:imageView.image = image;
2、Highlighted:设置该控件高亮状态显示的图片
例如:imageView.highlightedImage = highLightedImage;
3、设置该控件是否处于高亮状态
例如:imageView.highlighted = NO;
4、Mode
Mode属性用于控制该UI控件内图片的对齐方式,以及是否缩放该图片来适应该控件,其属性值支持一个弹出菜单。- ①、Scale to Fit:不保持纵横缩放图片,是图片完全适应该UIImageView控件;
- ②、Aspect Fit:保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整的将图片显示出来;
- ③、Aspect Fill:保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取;
- ④、Center:不缩放图片,只显示图片的中间区域;
- ⑤、Top:不缩放图片,只显示图片的顶部部分;
- ⑥、Bottom:不缩放图片,值显示图片的底部区域;
- ⑦、Left:不缩放图片,值显示图片的左边区域;
- ⑧、Right:不缩放图片,值显示图片的右边区域;
- ⑨、Top Left:不缩放图片,值显示图片的左上边区域;
⑩、Top Right:不缩放图片,值显示图片的右上边区域;
例如:imageView.contentMode = UIViewContentModeScaleAspectFit;
1、图片浏览器//当触碰时图片截图放大一倍
例如:当触碰时图片截图放大一倍
- (void)tap:(UITapGestureRecognizer *)tap{
UIImage* srcImage = imageView.image;//获取正在显示的原始位图
//获取用户手指在imageView控件上的触碰点
CGPoint point = [tap locationInView:imageView];
//获取正在显示的原图对应的CGImageRef
CGImageRef sourceImageRef = [srcImage CGImage];
//获取图片实际大小与图片的缩放比例
CGFloat scale1 = srcImage.size.width/self.view.frame.size.width;
CGFloat scale2 = srcImage.size.height/self.view.frame.size.height;
CGFloat x;
CGFloat y;
NSLog(@"point.x * scale = %f weight = %f",point.x * scale1,srcImage.size.width/4);
if (point.x * scale1 < srcImage.size.width/4) {
x = 0;
}else if(point.x * scale1 > srcImage.size.width/4 * 3){
x = srcImage.size.width/4 * 3;
}else{
x = point.x * scale1 - srcImage.size.width/4;
}
if (point.y * scale2 < srcImage.size.height/4) {
y = 0;
}else if(point.y * scale2 > srcImage.size.height/4 * 3){
y = srcImage.size.height/4 * 3;
}else{
y = point.y * scale2 - srcImage.size.height/4;
}
NSLog(@"x = %f,y = %f",x,y);
//调用CGImageCreateWithImageInRect函数获取sourceImageRef中指定区域的图片
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, CGRectMake(x, y, srcImage.size.width/2, srcImage.size.height/2));
//让imageView控件显示newImageRef对应的图片
imageView.image = [UIImage imageWithCGImage:newImageRef];
}
2、“幻灯片”播放器
例如:
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
image = [NSArray arrayWithObjects:[UIImage imageNamed:@"1.png"],[UIImage imageNamed:@"2.png"],[UIImage imageNamed:@"3.png"],[UIImage imageNamed:@"4.png"],[UIImage imageNamed:@"5.png"],[UIImage imageNamed:@"6.png"], nil];
//设置imageView控件需要动画的图片为image集合元素
imageView.animationImages = image;
imageView.animationDuration = 12;
imageView.animationRepeatCount = 44;
[imageView startAnimating];
[self.view addSubview:imageView];
八、进度条
广义的进度条包括两个控件:UIProgressView与UIActivityIndicatorView,其中UIProgressView用于向用户显示某个耗时操作完成的百分比。因此,它可以动态的显示进度,从而更好地提高用户界面的友好性;而UIActivityIndicatorView则显示一个旋转的齿轮,它仅仅显示某个耗时操作正在执行中,但并不明确完成的百分比。
1、UIProgressView
UIProfressView直接继承了UIView,因此它一般作为静态控件使用,只是想用户显示某个耗时操作完成的百分比,不会参与用户交互。
属性如下:
- (1)、Style(UIProgressViewStyle):该属性的属性值是一个列表框,该列表框支持如下来个那个列表项。
- ①、Default:设置使用默认风格的进度条;
- ②、Bar:设置使用工具条风格的进度条;
例如:
UIProgressView* progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
- (2)、Progress:该属性设置该进度条中任务的完成比例,其属性值是0.0~1.0之间的一个浮点值,其中1.0代表任务完成了100%,即全部完成。
例如:
progressView.progress = 0.5;
- (3)、Progress Tint:该属性设置进度条上已经完成进度的颜色;
例如:
progressView.progressTintColor = [UIColor redColor];
- (4)、Track Tint:该属性设置进度条的轨道颜色;
例如:
progressView.trackTintColor = [UIColor blackColor];
- (5)、ProgressImage:设置该进度条完成部分的图片;
例如:
progressView.progressImage = [UIImage imageNamed:@"1.png"];
- (6)、trackImage:访问或设置该进度条的轨道图片;
例如:
progressView.trackImage = [UIImage imageNamed:@"1.png"];
- (7)、设置进度
例如:
[progressView setProgress:1.0 animated:YES];
2、UIActivityIndicatorView
UIActivityIndicatorView用于表示任务正在进行中,该控件显示一个旋转的进度环,由于该进度环只是用旋转来表示任务正在进行中,它不会精确显示进度完成的百分比。因此该控件实质上相当于不显示进度的进度环。
属性如下:
(1)、Style:该属性设置该控件的风格,其属性值支持如下三个列表项;
- ①、Large White:设置大的、白色的风格;
- ②、White:设置白色风格;
③、Gray:设置灰色风格;
例如:UIActivityIndicatorView* activityIndicatorView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
(2)、Color:该属性用于直接设置该进度环的颜色,该属性的设置会覆盖前面风格中选择的颜色,前面风格选择的大小依然起作用。Color属性设置的颜色只是改变进度环的颜色;
例如:activityIndicatorView.color = [UIColor redColor];
(3)、Behavior:该属性支持如下两个复选框;
①、Animating:勾选该复选框控制进度环显示出来后立即开始转动;
例如:NSLog(@"%d",activityIndicatorView.isAnimating);
②、Hides When Stopped:勾选该复选框设置进度环停止时自动隐藏;
例如:activityIndicatorView.hidesWhenStopped = YES;
(4)、UIActivityIndicatorView提供了如下两个方法来启动进度环的转动和停止转动
- ①、- (void)startAnimating;控制进度环开始转动;
②、- (void)stopAnimating;控制进度环停止转动;
注意:UIActivityIndicatorView控件是不允许改变大小的,它标准风格显示时大小是20像素*20像素;大的风格显示时,大小是37像素*37像素。
提示:系统的刷新设置: [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
九、拖动条(UISlider)
拖动条通常用于对系统的某种数值进行调节,比如调节音量,控制播放进度等。
拖动条UISlider继承了UIControl,因此UISlider可以作为活动控件与用户交互,但必须用Value Change来绑定事件
属性如下:
(1)、Value:设置拖动条的最大值和最小值以及当前值;
例如:slider.minimumValue = 0.0; slider.maximumValue = 1.0; slider.value = 0.5;
(2)、Min Image:设置拖动条最小值边界的图标;
例如:slider.minimumValueImage = image;
(3)、Max Image:设置拖动条最大值边界的图标;
例如:slider.maximumValueImage = image;
(4)、Min Track Tin:设置该拖动条的完成部分的轨道颜色;
例如:slider.minimumTrackTintColor = [UIColor redColor];
(5)、Max Track Tin:设置该拖动条的未完成部分的轨道颜色;
例如:slider.maximumTrackTintColor = [UIColor grayColor];
(6)、Thumb Tint:设置滑块的颜色;
例如:slider.thumbTintColor = [UIColor blackColor];
(7)、Events:滑动时是否连接触发事件;
例如:[slider addTarget:self action:@selector(slider:) forControlEvents:UIControlEventValueChanged];
同UIProgressView类似的是,UISlider同样支持高度定制,包括定制拖动条的轨道、也完成进度的外观。例如如下方法:
- ①、- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state;//设置拖动条已完成进度的轨道图片
- ②、- (void)setMinimumTrackImage:(UIImage *)image forState:(UIControlState)state;//设置拖动条外完成进度的轨道图片
- ③、- (void)setMaximumTrackImage:(UIImage *)image forState:(UIControlState)state;//设置滑动条上滑块的图片
十、警告框(UIAlertView)与UIActionSheet
UIAlertView和UIActionSheet都是iOS系统自带的弹出式对话框。当UIAlertView或UIActionSheet显示出来时,用户无法与应用界面中的其他控件交互。UIAlertView与UIActionSheet的最大区别在于:UIAlertView表现为显示在屏幕中央的弹出警告框;UIActionSheet则表现为显示在底部的按钮列表;
1、UIAlertView的基本用法
- ①、创建UIAlertView,创建该对象时刻指定该警告框的标题、消息内容,以及该警告框包含多少个按钮等信息。如果程序需要监听用户点击了警告框的哪个按钮,还需要在创建UIAlertView时设置UIAlertViewDelegate委托对象;
- ②、调用UIAlertView显示出来即可;
- ③、如果需要监听用户点击了警告框中的哪个按钮,为委托对象是吸纳UIAlertViewDelegate协议中的方法。
例如:
MyAlertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"警告框用法真的很简单" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"按钮一",@"按钮二",@"按钮三", nil];
[MyAlertView show];
#pragma mark -UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (alertView == MyAlertView) {
NSString* msg = [NSString stringWithFormat:@"您点击了第%ld个按钮",(long)buttonIndex];
UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"提示" message:msg delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
}
}
#pragma mark -UIAlertViewDelegate委托方法
- (1)、- (void)willPresentAlertView:(UIAlertView *)alertView;//当警告框将要显示出来时将会激发该方法;
- (2)、 - (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView;//当该警告框中第一个非Cancel按钮被启用时激发该方法;
- (3)、 - (void)didPresentAlertView:(UIAlertView *)alertView;//当警告框完全显示出来后将会激发该方法;
- (4)、 - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex;//当用户通过单击某个按钮将要隐藏该警告框时激发该方法;
- (5)、 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;//当用户单击该警告框中某个按钮时激发该方法,其中buttonIndex参数代表用户单击的按钮的索引,该索引从0开始;
- (6)、 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;//点那个用户用过单击某个按钮完全隐藏该警告框时激发该方法;
- (7)、 - (void)alertViewCancel:(UIAlertView *)alertView;//当该对话框被取消时(如用户点击了Home键)激发该方法;
2、带输入框的UIAlertView
(1)、在使用UIAlertView控件时,该控件支持一个actionSheetStyle属性,该属性用于设置该UIAlertView的风格,它支持如下枚举值:
(UIAlertViewStyle) UIAlertViewStyleDefault:默认的警告框风格; UIAlertViewStyleSecureTextInput:警告框中包含一个密码的输入框; UIAlertViewStylePlainTextInput:警告框中包含一个普通的输入框; UIAlertViewStyleLoginAndPasswordInput:警告框中包含用户名、密码两个输入框。
例如:
MyAlertView.alertViewStyle = UIAlertViewStyleDefault;
通过该百年UIAlertView的actionSheerStyle属性,即可控制警告框使用不同的风格,包括带普通文本框、带密码框、带用户名和密码输入框的警告框。
(2)、如果UIAlertView控件中带有输入框,程序可通过如下方法来访问该警告框中的输入框:
- (UITextField *)textFieldAtIndex:(NSInteger)textFieldIndex;获取textFieldIndex索引对应的文本框。第一个文本框的索引为0;
通过上述的方式获取UIAlertView中包含的UITextView控件之后,接下来就可以对该UITextField进行任何操作,包括定制其外观(改变它的字体和颜色、关联的键盘灯等)。也可以获取用户在UITextView中输入的字符。
例如:UITextField* textField = [MyAlertView textFieldAtIndex:0];
(3)、当想改变UIAlertView中的message中的UILabel的属性时,可在UIAlertView将要出现的时候遍历其子视图,然后设置属性,例如:
- (void)willPresentAlertView:(UIAlertView *)alertView{
for (UIView* view in alertView.subviews) {
if ([view isKindOfClass:[UILabel class]]) {
UILabel* label = (UILabel *)view;
label.textAlignment = NSTextAlignmentLeft;
}
}
}
3、使用UIActionSheet
UIActionSheet变现为显示底部按钮列表,用户通过单击某个按钮来表明自己的态度,默认情况下,UIActionSheet只支持一个标题和多个按钮,UIActionSheet会有两个固定的按钮和多个其他按钮,两个固定按钮如下:
- (1)、灰色背景的取消按钮,该按钮用户取消显示该UIActionSheet。
(2)、红色背景的销毁按钮,当用户视图删除某个文件或某条记录时,可让用户通过该按钮来确认删除。
使用UIActionSheet时同样通过actionSheetStyle属性来控制该控件的风格,该属性支持如下枚举值(UIActionSheetStyle):UIActionSheetStyleDefault:默认风格,灰色背景上显示白色文字; UIActionSheetStyleBlackTranslucent:在透明的黑色背景上显示白色文字; UIActionSheetStyleBlackOpaque:在纯黑的背景上显示白色文字;
例如:
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
在创建之后需要完成UIActionSheetDelegate委托方法:
例如:
actionSheet = [[UIActionSheet alloc]initWithTitle:@"提示" delegate:self cancelButtonTitle:@"确定" destructiveButtonTitle:@"取消" otherButtonTitles:@"按钮一",@"按钮二",@"按钮三", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showInView:self.view];
#pragma mark -UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
NSLog(@"%ld",(long)buttonIndex);
}
#pragma mark -UIActionSheetDelegate委托方法
- (1)、- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;//当用户单击该警告框中某个按钮时激发该方法,其中buttonIndex参数代表用户单击的按钮的索引,该索引从0开始;
- (2)、 - (void)actionSheetCancel:(UIActionSheet *)actionSheet;//当该对话框被取消时(如用户点击了Home键)激发该方法;
- (3)、 - (void)willPresentActionSheet:(UIActionSheet *)actionSheet;//当警告框将要显示出来时将会激发该方法;
- (4)、- (void)didPresentActionSheet:(UIActionSheet *)actionSheet;//当警告框完全显示出来后将会激发该方法;
- (5)、- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex;//当用户单击该警告框中某个按钮时激发该方法,其中buttonIndex参数代表用户单击的按钮的索引,该索引从0开始;
- (6)、- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex;//点那个用户用过单击某个按钮完全隐藏该警告框时激发该方法;
十一、日期选择器(UIDatePicker)
UIDatePicker是一个可以用来选择日期和时间的控件。除此之外,它也可以作为倒计时控件。
日期选择器(UIDatePicker)继承了UIControl,因此UIDatePicker可以作为活动控件使用,能用用户交互。
注意:需使用ValueChanged事件绑定处理方法。
UIDatePicker的属性如下:
(1)、Mode(UIDatePickerMode):该属性用于设置该UIDatePicker的模式,它支持如下表项。
- ①、Date:该UIDatePicker控件仅显示日期,不显示时间;
- ②、Time:该UIDatePicker控件仅显示时间,不显示日期;
- ③、Date and Time:该UIDatePicker控件同时显示日期和时间;
④、Count Down Timer:该UIDatePicker控件仅显示为倒计时器。
例如:datePicker.datePickerMode = UIDatePickerModeDateAndTime;
(2)、Locale:该属性用于设置该UIDatePicker的股计划Locale,假设设置该UIDatePicker控件国际化Locale为简体中文环境,那么它将以简体中文习惯显示日期。实际上,我们通常无须手动设置Locale,该UIDatePicker控件默认使用iOS系统的国际化Locale;
例如:datePicker.locale = [[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"];
(3)、Interval:仅当该UIDatePicker控件采用Time、Date and Time和Count Down Timer这三种模式时有效,该属性设置UIDatePicker控件上两个时间之间的间隔。单位为分钟;
例如:datePicker.minuteInterval = 30;
(4)、Date:该属性设置开始时间;
例如:datePicker.date = [NSDate date];
(5)、Constraints:该属性为UIDatePicker控件设置最小时间和最大时间。如果设置了该属性值,用户无法通过该UIDatePicker控件选择超出该范围的日期和时间。
例如:datePicker.minimumDate = date;
datePicker. maximumDate = date;
(6)、Timer:仅当UIDatePicker控件采用Count Down Timer模式时有效,该属性设置该控件作为倒计时剩下的秒数。
例如:datePicker.countDownDuration = 360;
注意:点击确定获取选择的时间
- (void)btn{
//获取用户通过UIDatePicker设置的日期和时间
NSDate* selected = [datePicker date];
//创建一个日期格式器
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc]init];
//为日期各时期设置字符串
[dateFormatter setDateFormat:@"yyyy年MM月dd日 HH:mm+0800"];
//使用日期格式器格式化日期、时间
NSString* dateString = [dateFormatter stringFromDate:selected];
NSLog(@"dateString = %@",dateString);
}
十二、选择器(UIPickerView)
UIPickerView可以生成单列的选择器,也可生成多列的选择器,而且开发者完全可以自定义选择项的外观。
UIPickerView能设置出了日期之外的其它内容,不过需要两个非常重要的协议:UIPickerViewDelegate,UIPickerViewDataSource。
UIPickerView直接继承UIView,UIPickerView的处理事件由其委托对象完成。
UIPickerView的常用属性和方法如下:
(1)、//获取UIPickerView指定列表中包含的列表项的数量。该属性只是一个只读属性。
@property(nonatomic,readonly) NSInteger numberOfComponents;
例如:
NSLog(@"number = %ld",(long)cxPickerView.numberOfComponents);
(2)、//该属性控制是否显示UIPickerView中的选中标记(以高亮背景作为选中标记)。
@property(nonatomic)BOOL showsSelectionIndicator;
例如:
cxPickerView.showsSelectionIndicator = YES;
(3)、//获取UIPickerView包含的列数量。
- (NSInteger)numberOfRowsInComponent:(NSInteger)component;
例如:
NSLog(@"%ld",[cxPickerView numberOfRowsInComponent:0]);
(4)、//获取UIPickerView包含的指定列表中列表项的大小。该方法返回一个CGSize的对象。
- (CGSize)rowSizeForComponent:(NSInteger)component;
例如:
CGSize size = [cxPickerView rowSizeForComponent:0];
(5)、//该方法设置选中该UIPickerView中指定列的特定列表项,最后一个参数控制是否使用动画。
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
例如:
[cxPickerView selectRow:5 inComponent:0 animated:YES];
(6)、//该方法返回该UIPickerView指定列表中被选中的列表项。
- (NSInteger)selectedRowInComponent:(NSInteger)component;
例如:
NSInteger row = [cxPickerView selectedRowInComponent:0];
(7)、//该方法放回该UIPickerView指定列的列表选项所使用UIView控件。
- (UIView *)viewForRow:(NSInteger)row forComponent:(NSInteger)component;
例如:
UIView* view = [cxPickerView viewForRow:1 forComponent:0];
如果程序想要控制该控件包含多少列,各列包含多少个列表项,则有UIPickerViewDataSource对象负责。开发者必须为UIPickerView设置UIPickerViewDataSource对象,并实现如下两个方法:
#pragma mark - UIPickerViewDataSource
- (1)、- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;//该UIPickerView将通过该方法来判断应该包含多少列。
- (2)、- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;//该UIPickerView将通过该方法来判断指定列应该包含多少个列表项。
如果程序需要控制UIPickerView中各列的宽度,以及各列中列表项的大小和外观,或程序需要为UIPickerView的选中事件提供响应,都需要为UIPickerView设置UIPickerViewDelegate委托对象,并根据需要是吸纳该委托对象中的如下方法:
#pragma mark - UIPickerViewDelegate
- (1)、- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;//该方法返回的CGFloat值作为该UIPickerView控件中指定列的宽度;
- (2)、 - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component; //该方法返回的CGFloat值将作为UIPickerView控件中指定列中列表项的高度;
- (3)、 - (NSString )pickerView:(UIPickerView )pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;//该方法返回的NSString值将作为该UIPickerView控件中指定列的列表项的文本标题;
- (4)、- (NSAttributedString )pickerView:(UIPickerView )pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component;//该方法待定
- (5)、 - (UIView )pickerView:(UIPickerView )pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;//该方法返回的UIView控件将直接作为该UIPickerView控件中指定列的指定列表项;
- (6)、 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;//当用户选中该UIPickerView控件的指定列表列表项时将会激发该方法。
1、单项选择器
注意:UIPickerView高度有三种大小,最大的是216。
可以利用CALayer来改变UIPickerView,具体如下:
cxPickerView = [[UIPickerView alloc]init];
CALayer* layer = cxPickerView.layer;
[layer setFrame:CGRectMake(100, 100, 200, 40)];
@interface RootViewController ()
{
UIPickerView* cxPickerView;
NSArray* array;
NSInteger selectRow;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
array = [[NSArray alloc]initWithObjects:@"疯狂iOS讲义",@"疯狂Android讲义",@"疯狂Ajax讲义",@"疯狂XML讲义",@"疯狂英语", nil];
cxPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(60, 100, 200, 60)];
cxPickerView.delegate = self;
cxPickerView.dataSource = self;
cxPickerView.showsSelectionIndicator = YES;
[self.view addSubview:cxPickerView];
}
#pragma mark - UIPickerViewDataSource
//列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
//行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return array.count;
}
//高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return 40;
}
//宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
return 200;
}
//自定义view
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 40)];
label.textAlignment = NSTextAlignmentCenter;
label.text = [array objectAtIndex:row];
if (row == selectRow) {
label.textColor = [UIColor redColor];
}else{
label.textColor = [UIColor blackColor];
}
return label;
}
//选中调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
selectRow = row;
[pickerView reloadComponent:0];
}
2、多项选择器
@interface RootViewController ()
{
UIPickerView* cxPickerView;
NSArray* array1;
NSArray* array2;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
array1 = [[NSArray alloc]initWithObjects:@"泰戈尔",@"冯梦龙",@"李刚", nil];
array2 = [[NSArray alloc]initWithObjects:@"飞鸟集",@"吉檀迦利",@"醒世恒言",@"喻世明言",@"警世通言",@"疯狂Android讲义",@"疯狂iOS讲义",@"疯狂Ajax讲义",@"疯狂XML讲义", nil];
cxPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(10, 100, 300, 0)];
cxPickerView.delegate = self;
cxPickerView.dataSource = self;
cxPickerView.showsSelectionIndicator = YES;
[cxPickerView selectRow:1 inComponent:0 animated:YES];
[cxPickerView selectRow:1 inComponent:1 animated:YES];
[self.view addSubview:cxPickerView];
}
#pragma mark - UIPickerViewDataSource
//列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 2;
}
//行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if (component == 0) {
return array1.count;
}else{
return array2.count;
}
}
//高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return 30;
}
//宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
return 150;
}
//自定义view
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 150 , 40)];
label.textAlignment = NSTextAlignmentCenter;
if (component == 0) {
label.text = [array1 objectAtIndex:row];
}else{
label.text = [array2 objectAtIndex:row];
}
return label;
}
//选中调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
UILabel* label = (UILabel *)[pickerView viewForRow:row forComponent:component];
label.textColor = [UIColor redColor];
}
3、相互依赖的多列选择器
为了让第二列能根据第一列的选择动态加载,程序需要用户选择第一列的事件,并根据该时间动态加载第二列的数据,然后强制重新加载UIPickerView,例如:
UIPickerVie刷新
- (1)、- (void)reloadAllComponents; //全部刷新
- (2)、- (void)reloadComponent:(NSInteger)component;//刷新指定的某一列;
@interface RootViewController ()
{
UIPickerView* cxPickerView;
NSDictionary* books;
NSArray* authors;
//selectedAuthor保存当前选中的作者
NSString* selectedAuthor;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建并初始化NSDictionary对象
books = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObjects:@"飞鸟集",@"吉檀迦利", nil],@"泰戈尔", [NSArray arrayWithObjects:@"醒世恒言",@"喻世明言",@"警世通言", nil],@"冯梦龙",[NSArray arrayWithObjects:@"疯狂Android讲义",@"疯狂iOS讲义",@"疯狂Ajax讲义",@"疯狂XML讲义", nil],@"李刚",nil];
//使用authors保存所有key组成的NSArray排序后的而结果
authors = [[books allKeys]sortedArrayUsingSelector:@selector(compare:)];
selectedAuthor = [authors objectAtIndex:0];
cxPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(10, 100, 300, 0)];
cxPickerView.delegate = self;
cxPickerView.dataSource = self;
cxPickerView.showsSelectionIndicator = YES;
[self.view addSubview:cxPickerView];
}
#pragma mark - UIPickerViewDataSource
//列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 2;
}
//行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if (component == 0) {
return authors.count;
}else{
return [[books objectForKey:selectedAuthor] count];
}
}
//高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return 30;
}
//宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
if (component == 0) {
return 90;
}else{
return 150;
}
}
//自定义view
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel* label;
if (component == 0) {
label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 90 , 40)];
}else{
label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 150 , 40)];
}
label.textAlignment = NSTextAlignmentCenter;
if (component == 0) {
label.text = [authors objectAtIndex:row];
}else{
label.text = [[books objectForKey:selectedAuthor] objectAtIndex:row];
}
return label;
}
//选中调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if (component == 0) {
//改变被选中的作者
selectedAuthor = [authors objectAtIndex:row];
[pickerView reloadComponent:1];
}
}
4、自定义选择器视图
UIPickerView允许开发者对列表进行任意定制,开发者只要实现UIPickerViewDelegate协议中的- (UIView )pickerView:(UIPickerView )pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;方法即可,该方法返回的UIView将作为UIPickerView制定和列表项的视图控件。
实例:“老虎机游戏”
在.h文件中的声明部分
#import <UIKit/UIKit.h>
#import "MyScrollView.h"
@interface RootViewController : UIViewController<UIPickerViewDelegate,UIPickerViewDataSource]] >
//分别绑定到应用界面的三个UI控件
@property (nonatomic,strong)UIPickerView* picker;
@property (nonatomic,strong)UIImageView* image;
@property (nonatomic,strong)UIButton* startBn;
@end
.m的实现部分
@interface RootViewController (){
UIImage* loseImage;
UIImage* winImage;
NSArray* images;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
loseImage = [UIImage imageNamed:@"7.png"];
winImage = [UIImage imageNamed:@"8.png"];
//依次加载6张图片,生成对应的Image对象
images = [NSMutableArray arrayWithObjects:[UIImage imageNamed:@"11.png"],[UIImage imageNamed:@"12.png"],[UIImage imageNamed:@"13.png"],[UIImage imageNamed:@"14.png"],[UIImage imageNamed:@"15.png"],[UIImage imageNamed:@"16.png"], nil];
self.picker = [[UIPickerView alloc]initWithFrame:CGRectMake(10, 100, 300, 100)];
_picker.delegate = self;
_picker.dataSource = self;
[self.view addSubview:_picker];
//开始按钮
self.startBn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_startBn setTitle:@"开始" forState:UIControlStateNormal];
_startBn.frame = CGRectMake(0, 300, 320, 40);
[_startBn addTarget:self action:@selector(start) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_startBn];
//显示输赢的图片
self.image = [[UIImageView alloc]initWithFrame:CGRectMake(100, 340, 40, 40)];
[self.view addSubview:_image];
}
//开始旋转
- (void)start{
self.startBn.enabled = NO;//禁用该按钮
self.image.image = nil;//清空界面上image控件中的图片
//定义一个NSMutableDictionary来记录每个随机数的出现次数
NSMutableDictionary* result = [[NSMutableDictionary alloc]init];
for (int i = 0; i < 5; i ++) {
int selectedVal = arc4random()%images.count;
[self.picker selectRow:selectedVal inComponent:i animated:YES];
//在result中已经为该随机数记录了出现的次数
if ([result objectForKey:[NSNumber numberWithInt:selectedVal]]) {
//获取该result中该随机数的出现次数
int newCount = [[result objectForKey:[NSNumber numberWithInt:selectedVal]]intValue];
[result setObject:[NSNumber numberWithInt:(newCount + 1)] forKey:[NSNumber numberWithInt:selectedVal]];
}else{
//使用result记录该随机数的出现次数为1
[result setObject:[NSNumber numberWithInt:1] forKey:[NSNumber numberWithInt:selectedVal]];
}
//使用该变量记录随机数的最出现次数
int maxOccurs = 1;
for (NSNumber* num in [result allKeys]) {
//只要任何随机数的出现次数大于maxOccurs
if ([[result objectForKey:num] intValue] > maxOccurs) {
maxOccurs = [[result objectForKey:num] intValue];
}
}
if (i == 4) {
//如果某个随机数的出现字数大于或者等于3
if (maxOccurs >= 3) {
[self performSelector:@selector(showWin) withObject:nil afterDelay:0.5];
}else{
[self performSelector:@selector(showLose) withObject:nil afterDelay:0.5];
}
}
}
}
- (void)showWin{
self.image.image = winImage;
self.startBn.enabled = YES;
}
- (void)showLose{
self.image.image = loseImage;
self.startBn.enabled = YES;
}
#pragma mark - UIPickerViewDataSource
//列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 5;
}
//行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
NSLog(@"%@",images);
return images.count;
}
//高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return 40;
}
//宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
return 40;
}
//自定义view
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
if (view.tag != kImageTag) {
view = [[UIImageView alloc]initWithImage:[images objectAtIndex:row]];
view.frame = CGRectMake(0, 0, 40, 40);
view.tag = kImageTag;
//设置不允许用户交互
view.userInteractionEnabled = NO;
}
return view;
}
十三、微调器(UIStepper)
UIStepper是iOS5新增的控件,该控件的外观和UISwitch相似,但是该控件上包含了“+”,“-”两个按钮,共同用于控制某个值的增、减。它继承UIControl基类,默认属于活动控件,他可以与用户交互并激发相应地事件处理方法。
UIStepper属性如下:
(1)、Value:该区域支持指定如下的4个属性
①、Minimum:该属性用于控制UIStepper控件的最小值。对应于minimumValue属性,默认为0。当该属性被设为大于或等于maximumValue时,会报一个NSInvalidArgumentException异常;
例如:stepper.minimumValue = 1;
②、Maximum:该属性用于控制UIStepper控件的最大者。对应于MaximumValue属性,默认为100。当该属性被设为小于或等于minimumValue时,会报一个NSInvalidArgumentException异常;
例如:stepper.maximumValue = 100;
③、Current:该属性用于控制该UIStepper中数值的当前值。对应于value属性,上限是maximumValue,下限是minimumValue,当数值改变时,会发送事件激发对应的事件处理方法;
例如:stepper.value = 50;
④、Step:该属性用于控制该UIStepper中数值变化的步长。对应于stepValue属性,该属性默认为1。当该属性值为10时,用户每单击一次“+”图标,该UIStepper就增加10;用户每单击一个“-”,该UIStepper就减少10;
例如:stepper.stepValue = 2;
(2)、Behavior:该支持勾选如下三个复选框
①、Autorepeat:对应于autorepeat属性,该属性默认为YES。当该属性为YES时,标识用户按住加好或减号不松手,数字会持续变化。
例如:stepper.autorepeat = NO;
②、Continuous:对应于continuous属性,该属性的默认值为YES。当该属性为YES时,表示当该用户交互时会立刻发送ValueChange事件,NO则表示只有等用户交互结束时才发送ValueChange事件;
例如:stepper.continuous = NO;
③、Wrap:岁英语wraps属性,该属性的默认值为NO。当该属性为YES时,若value加到超过maximumValue,value将自动“转头”变成minimumValue的值;若减到比minimumValue还小,则value将自动“转头”变成maximumValue的值。
例如:stepper.wraps = YES;
(3)、自定义“+”或者“-”号图片
例如:改变“+”号图片:[stepper setIncrementImage:image forState:UIControlStateNormal];
例如:改变“-”号图片:
[stepper setDecrementImage:image forState:UIControlStateNormal];
十四、页面控件(UIWebView)
通过使用UIWebView控件,可以是实现一个内置的浏览器(类似于Safari),而且可以直接将这个浏览器内嵌到应用的任意位置。
UIWebView直接继承了UIView基类。UIWebView属性如下:
(1)、Scales Page To Fit:对应属性检查器中的Scale Page To Fit。该属性控制是否缩放网页以适应该控件。
例如:webView.scalesPageToFit = YES;
(2)、dataDetectionTypes(UIDataDetectorTypes):对应属性面板中的Detection属性,该属性支持如下枚举值。
- ①、UIDataDetectorTypePhoneNumber:自动检测网页上的电话号码,点击该号码就会拨号;
- ②、UIDataDetectorTypeLink:自动检测网页上的超链接,点击该链接就会导航到链接对应的页面;
- ③、UIDataDetectorTypeAddress:自动检测网页上的地址;
- ③、UIDateDetectorTypeCalendarEvent:自动检测网页上的日历事件;
- ④、UIDataDetectorTypeNone:不检测网页上的任何内容;
⑤、UIDataDetectorTypeAll:自动检测网页上的所有特殊内容;
例如:webView.dataDetectorTypes = UIDataDetectorTypeAll;
设置完UIWebView对象之后,接下来可通过如下方法控制UIWebView加载内容
- (1)、- (void)loadHTMLString:(NSString )string baseURL:(NSURL )baseURL;加载并显示HTML字符串;
- (2)、- (void)loadRequest:(NSURLRequest *)request;加载并显示指定URL对应网页;
- (3)、- (NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;执行指定的JavaScript字符串,并返回执行结果。
- (4)、- (void)goBack;后退;
- (5)、- (void)goForward;前进;
- (6)、- (void)reload;重新加载网页;
- (7)、- (void)stopLoading;停止加载网页;
#pragma mark - UIWebViewDelegate
当UIWebView加载网页时,程序可为UIWebView设置一个delegate委托(该委托对象必须实现UIWebViewDelegate协议),该协议中包含如下方法:
- (1)、- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType;该UIWebView将要开始装载指定URL对应的网页时激发该方法;
- (2)、- (void)webViewDidStartLoad:(UIWebView *)webView;该UIWebView开始装载时激发该方法;
- (3)、- (void)webViewDidFinishLoad:(UIWebView *)webView;该UIWebView装载完成时激发该方法;
(4)、- (void)webView:(UIWebView )webView didFailLoadWithError:(NSError )error;该UIWebView装载响应出现错误时激发该方法;
例如:NSMutableString* sb = [[NSMutableString alloc]init];
//拼写一段HTML代码
[sb appendString:@"<html>"];
[sb appendString:@"<head>"];
[sb appendString:@"<title>欢迎你</title>"];
[sb appendString:@"</head>"];
[sb appendString:@"<body>"];
[sb appendString:@"<h2>欢迎您访问<a href=\"http://www.crazyit.org\">"];
[sb appendString:@"疯狂Java联盟</a></h2>"];
//HTML代码中支持Javacript脚本
[sb appendString:@"<script language='javascript'>"];
[sb appendString:@"alert('欢迎使用UIWebView');</script>"];
[sb appendString:@"</body>"];
[sb appendString:@"</html>"];
webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 20, 320, 480)];
webView.scalesPageToFit = YES;
webView.dataDetectorTypes = UIDataDetectorTypeAll;
//加载并显示HTML代码
[webView loadHTMLString:sb baseURL:[NSURL URLWithString:@"http://www.fkit.org"]];
[self.view addSubview:webView];
实例:迷你浏览器
借助UIWebView的loadRequest:方法,可让该控件加载并显示指定URL对应的网页,通过这个功能,可实现自己的额浏览器。
例如:
声明部分
#import <UIKit/UIKit.h>
#import "MyScrollView.h"
@interface RootViewController : UIViewController<UIWebViewDelegate]] >
@end
实现部分
@interface RootViewController (){
UIWebView* webView;
UITextField* textField;
UIActivityIndicatorView* activityIndicatorView;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, 40)];
textField.text = @"baidu.com";
[self.view addSubview:textField];
//设置自动缩放网页以适应该控件
webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 60, self.view.frame.size.width, self.view.frame.size.height - 60)];
webView.scalesPageToFit = YES;
//为webView控件设置委托
webView.delegate = self;
[self.view addSubview:webView];
//创建一个UIActivityIndicatorView控件
activityIndicatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)];
//控制UIActivityIndicatorView在视图的正中央
[activityIndicatorView setCenter:self.view.center];
//隐藏UIActivityIndicatorView控件
activityIndicatorView.hidden = YES;
[self.view addSubview:activityIndicatorView];
[self goClicked:nil];
}
- (void)goClicked:(id)sender{
[textField resignFirstResponder];
//获取用户输入的字符串
NSString* reqAddr = textField.text;
//如果regAddr不一http://开头,为该用户输入的网址添加http://前缀
if (![reqAddr hasPrefix:@"http://"]) {
reqAddr = [NSString stringWithFormat:@"http://%@",reqAddr];
textField.text = reqAddr;
}
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:reqAddr]];
//加载指定URL对应的网址
[webView loadRequest:request];
}
#pragma mark - UIWebViewDelegate
//当UIWebView开始加载时激发该方法
- (void)webViewDidStartLoad:(UIWebView *)webView{
//显示UIActivityIndicatorView控件
activityIndicatorView.hidden = NO;
//启动UIActivityIndicatorView控件的转动
[activityIndicatorView startAnimating];
}
//当UIWebView加载完成时调用该方法
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//停止UIActivityIndicatorView控件的转动
[activityIndicatorView stopAnimating];
//隐藏UIActivityIndicatorView控件
activityIndicatorView.hidden = YES;
}
//当UIWebView加载失败时激发该方法
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
//使用UIAlertView显示错误信息
UIAlertView* alertView = [[UIAlertView alloc]initWithTitle:@"" message:[error localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
[alertView show];
}
@end
十五、工具条(UIToolBar)
UIToolBar控件代表工具条,该工具条本身可以被放在应用界面的任意位置。
UIToolBar继承了UIView,它通常仅作为多个UIBarButtonItem的容器,每个UIBarButtonItem代表工具条上的一个控件。UIToolBar属性如下:
(1)、barStyle(UIBarStyle):该属性指定工具条的风格,它支持如下枚举值
- ①、UIBarStyleDefault(默认风格);
- ②、UIBarStyleBlack(黑色背景,白字风格);
- ③、UIBarStyleBlackOpaque(黑色不透明背景、白字风格);
④、UIBarStyleBlackTranslucent(黑色透明背景、白字风格);
例如:toolBar.barStyle = UIBarStyleDefault;
- (2)、items:该属性值是一个NSArray对象,该NSArray对象包含多个BarButtonItem对象,每个BarButtonItem对象代表工具条上的一个控件。
- (3)、工具条上的按钮:
- ①、BarButtonItem:工具条上的按钮;
- ②、Fixed Space Bar Button Item:工具条上固定宽度的空白间隔。该对象其实也是UIBarButtonItem的实例;
- ③、Flexible Space Bar Button Item:工具条上课伸缩宽度的空白间隔。该对象也是UIBarButtonItem的实例。该空白间隔默认会“努力占据”更多的宽度。
- (4)、UIBarButtonItem的初始化方法:
- ①、- (instancetype)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action;初始化包装普通按钮的UIBarButtonItem;
- ②、- (instancetype)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action;初始化包装UIImageView的UIBarButtonItem;
- ③、- (instancetype)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action;初始化包装系统按钮的UIBarButtonItem。这个系统按钮的图标,风格都是固定的。该方法需要一个UIBarButtonSystemItem类型的枚举值;
- ④、- (instancetype)initWithCustomView:(UIView *)customView;初始化包装任意UI控件的UIBarButtonItem。该初始化方法需要传入一个UIView参数,UIBarButtonItem就是用于包装该参数代表的控件;
实例:自定义工具条控件
@interface RootViewController (){
UIToolbar* toolBar;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个工具条,并设置它的大小和位置
toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 44, self.view.frame.size.width, 44)];
toolBar.barStyle = UIBarStyleDefault;
[self.view addSubview:toolBar];
//创建使用文本标题的UIBarButtonItem
UIBarButtonItem* bn1 = [[UIBarButtonItem alloc]initWithTitle:@"OK" style:UIBarButtonItemStylePlain target:self action:@selector(clicked:)];
//创建使用自定义图片的UIBarButtonItem
UIBarButtonItem* bn2 = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"hsvrb.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(clicked:)];
//创建使用系统图标的UIBarButtonItem
UIBarButtonItem* bn3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(clicked:)];
//创建一个可伸缩的UIBarButtonItem—自动填充
UIBarButtonItem* flexItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIProgressView* pro = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
//固定距离来填充
UIBarButtonItem* button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:@selector(buttonClick)];
button.width = 28;
//设置UIProgressView的大小
pro.frame = CGRectMake(0, 0, 80, 20);
//设置该进度条的进度为0.5
pro.progress = 1;
//创建使用UIView的UIBarButtonItem
UIBarButtonItem* bn4 = [[UIBarButtonItem alloc]initWithCustomView:pro];
//为工具条设置工具按钮
toolBar.items = [NSArray arrayWithObjects:bn1,bn2,bn3,flexItem,bn4, nil];
}
- (void)clicked:(id)sender{
}
@end
提示:系统自带的toolBar,必须带有导航的视图才可使用
[self.navigationController setToolbarHidden:YES];
[self setToolbarItems:[NSArray arrayWithObjects:bn1,bn2,bn3,flexItem,bn4, nil]];
十六、表格(UITableView)与表格控制器(UITableViewController)
各种表格效果:单分区表格,分区页眉,分区页脚,分区索引。
UITableView继承了UIScrollView,它具有UIScrollView的功能,默认情况下,UITableViewController实例被自动设为UIScrollView委托。
注意:在带有导航的前提下,加载UITableView,tableView的位置默认为在导航的下面,当导航隐藏的时候,默认在状态栏的下面,若想改变这个情况,可将视图控制器的属性 automaticallyAdjustsScrollViewInsets设为NO;
UITabelView属性如下:
(1)、Style:该属性指定该表格的风格,它对应的UITableView对象的style属性。该属性支持如下两个属性值;
- ①、Plain:指定该表格使用最普通的风格;
②、Grouped:指定该表格使用分组风格;
例如:_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
(2)、Separator(UITableViewCellSeparatorStyle):该区域的属性用于指定表格行之间分隔条的样式,该区域可配置两个属性;
①、分隔条样式:该分区的第一个列表框用于设置分隔条样式,该列表框可选择Single Line(单线)和Single Line Etched(被蚀刻的单线);
UITableViewCellSeparatorStyleNone, UITableViewCellSeparatorStyleSingleLine, UITableViewCellSeparatorStyleSingleLineEtched
例如:
_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLineEtched;
②、分隔条颜色;
例如:_tableView.separatorColor = [UIColor purpleColor];
(3)、Selection:该属性用于控制该表格的选择风格,该属性对应的列表框可支持如下属性值:
- ①、NO Selection:不允许选中;
- ②、Single Selection:只允许选中;
③、Multiple Selection:允许多选;
例如:_tableView.allowsSelection = YES; _tableView.allowsMultipleSelection = YES;
(4)、Editing:该属性用于控制当表格处于编辑状态是否允许选择,该属性对应的列表框可支持如下属性值;
- ①、No Selection During Editing:编辑状态时不允许选中;
- ②、Single Selection During Editing:编辑状态时只允许单选;
③、Multiple Selection During Editing:编辑状态时允许多选;
例如:_tableView.allowsSelectionDuringEditing = YES; _tableView.allowsMultipleSelectionDuringEditing = YES;
在程序中获取UITableView对象之后,接下来即可通过如下属性或方法来设置该表格控件的外观。
- (1)、style:只读属性,用于返回该表格的样式。该属性可能返回UITableViewStylePlain(普通)和UITableViewStyleGrouped(分组)两个样式;
(2)、rowHeight:该属性用于返回或设置表格的行高。通常来说,建议实现表格对应的委托对象的tableView:heightForRowAtIndexPath:方法来设置行高;
例如:_tableView.rowHeight = 50.0f;
(3)、separateStyle:该属性用于返回或设置表格的分隔条样式。它支持UITableViewCellSeparateStyleNone(无分隔条)、UITableViewCellSeparatorStyleSingleLine(单线分隔条)、UITableViewCellSeparatorStyleSingleLineEtched(被蚀刻的单线分隔条)这三个枚举值。
例如:_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLineEtched;
(4)、separateColor:该属性用于设置分隔条的颜色;
例如:_tableView.separatorColor = [UIColor purpleColor];
(5)、backgroundView:该属性用于返回或者设置表格的背影控件。它可以设置一个任意的UIView控件,该UIView控件将呗自动缩放匹配该表格;
例如:_tableView.backgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1.png"]];
(6)、tableHeaderView:该属性设置或返回该表格的页眉控件;
例如:_tableView.tableHeaderView = imageView1;
(7)、tableFooterView:该属性设置或返回该表格的页脚控件;
例如:_tableView.tableFooterView = imageView2;
(8)、- (NSInteger)numberOfRowsInSection:(NSInteger)section;该属性返回指定分区包含的行数;
例如:NSLog(@"%ld",[_tableView numberOfRowsInSection:0]);
(9)、- (NSInteger)numberOfSections;该属性返回表格所包含的分区数;
例如:NSLog(@"%ld",[_tableView numberOfSections]);
UITableView只负责最通用的行为,而该控件包含多少个分区,每个分组包含多少表格行、各表格行对应的UI控件都有UITableViewDataSource提供。因此开发者必须为UITableView设置UITableViewDataSource对象,并根据需要实现如下方法:
#pragma mark -UITableViewDataSource
- (1)、- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;必需方法。该方法返回的UITableViewCell对象将作为指定IndexPath对应表格的控件;
- (2)、- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;必需方法。该方法返回的NSInteger值决定指定分区包含的表格行数量;
- (3)、- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;可选方法。该方法返回NSInteger值决定该表格所包含的分区数量。如果不实现该方法,该表格默认只包含一个分区
1、简单表格
声明部分:
#import <UIKit/UIKit.h>
#import "MyScrollView.h"
@interface RootViewController : UIViewController<UITableViewDataSource,UITableViewDelegate]] >
@property (nonatomic,strong)UITableView* table;
@property (nonatomic,strong)NSArray* books;
@property (nonatomic,strong)NSArray* details;
@end
实现部分
@interface RootViewController (){
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - 20) style:UITableViewStylePlain];
//设置tableView控件的dataSource
_table.dataSource = self;
[self.view addSubview:_table];
//为UITableView控件设置页眉控件
// self.table.tableHeaderView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"3.png"]];
//为UITableView控件设置页脚控件
// self.table.tableFooterView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"6.png"]];
self.books = [NSArray arrayWithObjects:@"疯狂Android讲义",@"疯狂iOS讲义",@"疯狂Ajax讲义",@"疯狂XML讲义", nil];
self.details = [NSArray arrayWithObjects:@"长期雄踞各网点销量排行榜榜首的图书",@"全面而详细的iOS开发图书",@"Ajax开发图书",@"系统介绍XML相关知识", nil];
}
#pragma mark -UITableViewDataSource
//该方法的返回值决定指定分区内包含多少个表格行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//由于表格只有一个分区,直接返回books中集合元素个数代表表格的行数
return _books.count;
}
//该方法返回值决定各表格行的控件
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//为表格行定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
//如果取出的列表行为为nil
if (cell == nil) {
switch (indexPath.row % 4) {
case 0:
//创建一个UITableViewCell对象,使用UITableViewCellStyleSubtitle风格
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
break;
case 1:
//创建一个UITableViewCell对象,使用默认风格
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
break;
case 2:
//创建一个UITableViewCell对象,使用UITableViewCellStyleValue1风格
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellId];
break;
case 3:
//创建一个UITableViewCell对象,使用UITableViewCellStyleValue2风格
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:cellId];
default:
break;
}
}
//将单元格的边框设置为圆角
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = YES;
//从InsexPath参数中获取当前行的行号
NSUInteger rowNo = indexPath.row;
//从取出books中索引为rowNo的元素作为UITableViewCell的标题
cell.textLabel.text = [_books objectAtIndex:rowNo];
//为UITableViewCell的左端设置图片
cell.imageView.image = [UIImage imageNamed:@"1.png"];
//为UITableViewCell的左端设置高亮状态时的图片
cell.imageView.highlightedImage = [UIImage imageNamed:@"3.png"];
//取出details中索引为rowNo的元素作为UITableViewCell的详细内容
cell.detailTextLabel.text = [_details objectAtIndex:rowNo];
return cell;
}
@end
默认的UITableViewCell中包含五个可配置的属性:
- (1)、textLabel:该属性是一个UILabel控件,代表该UITableViewCell显示的标题;
- (2)、detailTextLabel:该属性是一个UILabel控件,代表该UITableViewCell显示的详细内容;
- (3)、imageView:该属性是一个UIImageView对象,代表UITableViewCell左边的图标;
- (4)、accessoryType:该属性设置附件类型,支持如下:
- ①、UITableViewCellAccessoryDetailDisclosureButton:附件是一个圆形的大于符号图标(>)的按钮;
- ②、UITableViewCellAccessoryCheckMark:附件是一个复选框;
- ③、UITableViewCellAccessoryDisclosureIndicator:附件是一个大于符号图标的(>)的按钮
- (5)、selectionStyle:该属性设置单元格的选中状态,支持如下:
- ①、UITableViewCellSelectionStyleNone:无选择状态;
- ②、UITableViewCellSelectionStyleBlue:选择蓝色状态;
- ③、UITableViewCellSelectionStyleGray:选择灰色状态;
- ④、UITableViewCellSelectionStyleDefault:默认状态;
另外可点击该附件调用方法为:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
提示:layer属性的cornerRadius、masksToBounds两个属性赋值,这两行代码用于给UIView控件增加圆角边框。
UITableViewCellStyle的4种不同的风格:
- ①、UITableViewCellStyleSubtitle:detailTextLabel字体略小,显示在textLabel的下方。
- ②、UITableViewCellStyleDefault:不显示detailTextLabel,只显示textLabel。
- ③、UITableViewCellStyleValue1:textLabel以淡蓝色显示,显示在表格的右边;
- ④、UITableViewCellStyleValue2:textLabel以淡蓝色、略小字体显示;detailTextLabel以大字体显示在表格的右边;不显示imageView控件;
获取UITableView控件之后,可通过如下方法访问表格控件的表格行和分区;
- (1)、- (UITableViewCell )cellForRowAtIndexPath:(NSIndexPath )indexPath;返回该表格中指定NSIndexPath对应的表格行;
- (2)、- (NSIndexPath )indexPathForCell:(UITableViewCell )cell;获取该表格中指定表格行对应的NSIndexPath;
- (3)、- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;获取该表格中指定点所在的NSIndexPath;
- (4)、- (NSArray *)indexPathsForRowsInRect:(CGRect)rect;获取该表格中指定区域内所有NSIndexPath组成的数组;
- (5)、- (NSArray *)visibleCells;返回该表格中所有可见区域内的表格行组成的数组;
- (6)、- (NSArray *)indexPathsForVisibleRows;返回该表格中所有可见区域内的表格行对应的NSIndexPath组成的数组;
也可以通过如下方法来控制表格控件的滚动:
- (1)、- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;控制该表格滚动到指定NSIndexPath对应的表格的顶端、中间或下方;
- (2)、- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;控制该表格滚动到选中表格行的顶端、中间或下方;
2、处理单元格的选中
UITableView提供了如下属性来配置表格的选中状态:
- (1)、@property (nonatomic) BOOL allowsSelection;该属性控制该表格是否允许被选中;
- (2)、@property (nonatomic) BOOL allowsMultipleSelection;该属性控制该表格是否允许多选;
- (3)、@property (nonatomic) BOOL allowsSelectionDuringEditing;该属性控制该表格处于编辑状态时是否允许被选中;
- (4)、@property (nonatomic) BOOL allowsMultipleSelectionDuringEditing;该属性控制该表格处于编辑状态时是否允许多选;
除此之外,也可通过UITableView提供的如下方法来操作表格中被选中的行:
- (1)、- (NSIndexPath *)indexPathForSelectedRow;获取选中表格中对应的NSIndexPath;
- (2)、- (NSArray *)indexPathsForSelectedRows;获取选中表格中对应的NSIndexPath组成的数组;
- (3)、- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;控制该表格选中指定NSIndexPath对应的表格行,最后一个参数控制是否滚动到被选中行的顶端、中间和底部;
- (4)、- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;控制取消选中该表格中指定NSIndexPath对应的表格行;
UITableView处理选中事件
如果程序需要响应表格行选中事件,就需要借组UITableView的委托对象,委托对象必须实现UITableViewDelegate对象——当UITableView的表格行发生选中相关事件时,都会激发该委托对象的响应方法。UITableViewDelegate中定义了如下方法:
#pragma mark -UITableViewDelegate
- (1)、- (NSIndexPath )tableView:(UITableView )tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;当用户将要选中表格中的某行时激发该方法;
- (2)、- (void)tableView:(UITableView )tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath;当用户完成选中表格中的某行时激发的方法;
(3)、- (NSIndexPath )tableView:(UITableView )tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath;当用户将要取消选中表格中某行时激发该方法;
(4)、- (void)tableView:(UITableView )tableView didDeselectRowAtIndexPath:(NSIndexPath )indexPath;当用户完成取消选中表格中的某行时激发的方法;
实例:编辑选中行
RootViewController页面部分
声明部分
#import <UIKit/UIKit.h>
#import "MyScrollView.h"
@interface RootViewController : UIViewController<UITableViewDataSource,UITableViewDelegate]] >
@property (nonatomic,strong)UITableView* table;
@property (nonatomic,strong)NSMutableArray* books;
@property (nonatomic,strong)NSMutableArray* details;
@end
实现部分
#import "RootViewController.h"
#import "AppDelegate.h"
#import "SecondViewController.h"
@interface RootViewController (){
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - 20) style:UITableViewStylePlain];
//设置tableView控件的dataSource
_table.dataSource = self;
_table.delegate = self;
[self.view addSubview:_table];
self.books = [NSMutableArray arrayWithObjects:@"疯狂Android讲义",@"疯狂iOS讲义",@"疯狂Ajax讲义",@"疯狂XML讲义", nil];
self.details = [NSMutableArray arrayWithObjects:@"长期雄踞各网点销量排行榜榜首的图书",@"全面而详细的iOS开发图书",@"Ajax开发图书",@"系统介绍XML相关知识", nil];
}
#pragma mark -UITableViewDataSource
#pragma mark -UITableViewDelegate
//该方法的返回值决定指定分区内包含多少个表格行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//由于表格只有一个分区,直接返回books中集合元素个数代表表格的行数
return _books.count;
}
//该方法返回值决定各表格行的控件
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//为表格行定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
//如果取出的列表行为为nil
if (cell == nil) {
//创建一个UITableViewCell对象,使用UITableViewCellStyleSubtitle风格
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}
//将单元格的边框设置为圆角
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = YES;
//从InsexPath参数中获取当前行的行号
NSUInteger rowNo = indexPath.row;
//从取出books中索引为rowNo的元素作为UITableViewCell的标题
cell.textLabel.text = [_books objectAtIndex:rowNo];
//为UITableViewCell的左端设置图片
cell.imageView.image = [UIImage imageNamed:@"1.png"];
//为UITableViewCell的左端设置高亮状态时的图片
cell.imageView.highlightedImage = [UIImage imageNamed:@"3.png"];
//取出details中索引为rowNo的元素作为UITableViewCell的详细内容
cell.detailTextLabel.text = [_details objectAtIndex:rowNo];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SecondViewController* sec = [[SecondViewController alloc]init];
sec.string1 = [_books objectAtIndex:indexPath.row];
sec.string2 = [_details objectAtIndex:indexPath.row];
[self presentViewController:sec animated:YES completion:nil];
}
SecondViewController页面部分
声明部分
#import <UIKit/UIKit.h>
@interface SecondViewController : UIViewController
@property (nonatomic,strong)UITextField* textField1;
@property (nonatomic,strong)UITextField* textField2;
@property (nonatomic,strong)NSString* string1;
@property (nonatomic,strong)NSString* string2;
@end
实现部分
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.textField1 = [[UITextField alloc]initWithFrame:CGRectMake(20, 100, self.view.frame.size.width - 40, 40)];
self.textField2 = [[UITextField alloc]initWithFrame:CGRectMake(20, 160, self.view.frame.size.width - 40, 40)];
_textField1.borderStyle = UITextBorderStyleRoundedRect;
_textField2.borderStyle = UITextBorderStyleRoundedRect;
_textField1.text = self.string1;
_textField2.text = self.string2;
[self.view addSubview:_textField1];
[self.view addSubview:_textField2];
}
3、定制表格行
如果只是使用系统提供的UITableViewCell,UITableView控件的表格只支持有限的样式,而且每个表格行只是包含textLabel、detailTextLabel、UIImageView这三个控件。因此,程序猿需要对表格进行定制。
实例1:继承UITableViewCell定制表格行
#import "FKTableViewCell.h"
@implementation FKTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//创建所需要的控件 然后添加到self.contentView中;
}
return self;
}
@end
实例2:使用动态单元格原型定制表格行
实例3:利用XIB文件定制表格行
UserCell.xib继承UserCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString* cellId = @"cellId";
UserCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell) {
cell = [[[NSBundle mainBundle]loadNibNamed:@"UserCell" owner:self options:nil]lastObject];
}
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
cell.backgroundColor = indexPath.row%2?[UIColor redColor]:[UIColor purpleColor];
((UserCell*)cell).nameLabel.backgroundColor = [UIColor blackColor];
}
4、编辑表格
UITableView生成的表格控件功能非常灵活,不仅可作为数据显示控件,还可支持对表格行执行移动、删除和插入等操作。
(1)、- (void)setEditing:(BOOL)editing animated:(BOOL)animated;editing属性来判断该表格控件是否处于编辑状态,如果该表格处于编辑状态,该属性返回YES;否则返回NO。
例如:[_table setEditing:YES animated:YES];
- (2)、- (void)beginUpdates;对表格控件执行多个连续的插入、删除和移动操作前,先调用该方法开始更新;
- (3)、- (void)endUpdates;对表格控件执行多个连续的插入、删除和移动操作后,调用该方法结束并提交更新;
//对表格行操作 - (4)、- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;在一个或者多个NSIndexPath处插入表格行;
- (5)、- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;删除一个或者多个NSIndexPath处的表格行;
- (6)、- (void)moveRowAtIndexPath:(NSIndexPath )indexPath toIndexPath:(NSIndexPath )newIndexPath;将指定NSIndexPath处的表格行移动到另一个NSIndexPath处;
- (7)、- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;刷新一个或者多个NSIndexPath处的表格行;
//对分区操作 - (8)、- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;在指定的NSIndexSet所包含的一个或多个分区号对应的位置插入分区;
- (9)、- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;删除指定NSIndexSet所包含的一个或者多个分区号对应的分区;
- (10)、- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;将指定分区移动到另一个位置。
- (11)、- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;刷新指定NSIndexSet所包含的一个或者多个分区号对应的分区.
#pragma mark - UITableViewDataSource
为了让动态编辑表格,必须实现UITableView对应的dataSource对象中的如下方法(这些方法都是由UITableViewDataSource协议定义的)
- (1)、- (BOOL)tableView:(UITableView )tableView canEditRowAtIndexPath:(NSIndexPath )indexPath;该方法的返回值决定指定NSIndexPath对应的表格行是否可编辑;
- (2)、- (void)tableView:(UITableView )tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath )indexPath;当用户对指定表格行编辑(包括删除或插入)完成时激发该方法;
- (3)、- (BOOL)tableView:(UITableView )tableView canMoveRowAtIndexPath:(NSIndexPath )indexPath;该方法返回值据顶指定NSIndexPath对应的表格行是否可移除;
- (4)、- (void)tableView:(UITableView )tableView moveRowAtIndexPath:(NSIndexPath )sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;该方法告诉该DataSource将指定的表格行移动到另一个位置;
#pragma mark - UITableViewDelegate
除此之外UITableViewDelegate协议也为编辑表格定义了如下方法
- (1)、- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;开始编辑某个表格行时激发该委托对象的该方法;
- (2)、- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;当编辑完某个表格行时激发该委托对象的该方法;
- (3)、- (UITableViewCellEditingStyle)tableView:(UITableView )tableView editingStyleForRowAtIndexPath:(NSIndexPath )indexPath;该方法返回值决定了该表格行的编辑状态;该方法返回UITableViewCellEditingStyleNone、UITableViewCellEditingStyleDelete、UITableViewCellEditingStyleInsert这三个枚举值之一,其中后面两个分别代表删除和插入两种编辑状态;
- (4)、- (NSString )tableView:(UITableView )tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;该方法返回的NSString将作为删除指定表格时确定按钮的文本;
- (5)、- (BOOL)tableView:(UITableView )tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath )indexPath;该方法返回的BOOL决定指定表格行处于编辑状态时,该表格行是否应该缩进。如果开发者没有重写该方法,默认所有的表格行处于编辑状态都会缩进。
实例:移动、删除和插入表格行
@interface RootViewController ()
{
NSMutableArray* list;
//记录当前正在执行的操作,0代表删除,1代表插入
NSUInteger action;
UIButton* deleteBtn;
UIButton* addBtn;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, self.view.frame.size.height - 50)];
_table.delegate = self;
_table.dataSource = self;
[self.view addSubview:_table];
addBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[addBtn setTitle:@"删除" forState:UIControlStateNormal];
addBtn.frame = CGRectMake(0, 20, 60, 30);
[addBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:addBtn];
deleteBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[deleteBtn setTitle:@"添加" forState:UIControlStateNormal];
deleteBtn.frame = CGRectMake(self.view.frame.size.width - 60, 20, 60, 30);
[deleteBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:deleteBtn];
list = [NSMutableArray arrayWithObjects:@"孙悟空",@"猪八戒",@"牛魔王",@"蜘蛛精",@"白骨精",@"狐狸精", nil];
action = 0;
}
- (void)btnClicked:(UIButton *)btn{
//如果用户点击了删除按钮action设为0 否则action设为1
if ([btn.titleLabel.text isEqualToString:@"删除"]) {
action = 0;
}else{
action = 1;
}
//使用动画切换表格的编辑状态
[_table setEditing:!_table.editing animated:YES];
if (self.table.editing) {
//修改工具条上的两个按钮文本
[addBtn setTitle:@"完成" forState:UIControlStateNormal];
[deleteBtn setTitle:@"完成" forState:UIControlStateNormal];
}else{
[addBtn setTitle:@"添加" forState:UIControlStateNormal];
[deleteBtn setTitle:@"删除" forState:UIControlStateNormal];
}
}
#pragma mark - UITableViewDelegate
#pragma mark - UITableViewDataSource
//行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return list.count;
}
//行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
//自定义cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//为表格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//获取可重用的单元格
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
cell.textLabel.text = [list objectAtIndex:indexPath.row];
return cell;
}
//UITableViewDelegate协议中定义的方法。该方法的返回值决定单元格的编辑状态
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
//如果action的值为0,代表将要删除
return action == 0?UITableViewCellEditingStyleDelete:UITableViewCellEditingStyleInsert;
}
//UITableViewDelegate协议中定义的方法
//该方法的返回值作为删除指定表格行时确定按钮的文本
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return @"确认删除";
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定某行是否可编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
//如果该表格行的数据为孙悟空,返回NO——代表这行数据不能编辑
if ([[list objectAtIndex:indexPath.row] isEqualToString:@"孙悟空"]) {
return NO;
}
//除了第2个表格行的数据不能编辑
if (indexPath.row == 1) {
return NO;
}
return YES;
}
//UITableViewDataSource协议中定义的方法。移动完成时激发该方法
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
NSInteger sourceRowNo = [sourceIndexPath row];
NSInteger destRowNo = [destinationIndexPath row];
//获取要移动的数据
id targetObj = [list objectAtIndex:sourceRowNo];
//从底层数组中删除指定额数据项
[list removeObjectAtIndex:sourceRowNo];
//将移动的数据项插入到指定位置
[list insertObject:targetObj atIndex:destRowNo];
}
//UITableViewDataSource协议中定义的方法。编辑包括删除或插入完成时激发该方法
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
//如果正在提交删除操作
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSInteger rowNo = [indexPath row];
//从底层NSArray集合中删除指定的数据项
[list removeObjectAtIndex:rowNo];
//从UITable程序界面上删除指定的表格行
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
//如果正在提交插入操作
if (editingStyle == UITableViewCellEditingStyleInsert) {
//将当前的数据插入到底层NSArray集合中
[list insertObject:[list objectAtIndex:indexPath.row] atIndex:indexPath.row + 1];
//在UITableView程序界面上插入一行
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
@end
5、多分区表格以及分区索引
如果希望UITableView生成的表格控件包含更多的分区,则需要为表格的dataSource对象实现更多的方法。UITableViewDataSource协议为建立多分区表格和分区索引定义了如下方法:
- (1)、- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;该方法的返回值决定该表格包含多少个分区;
- (2)、- (NSArray )sectionIndexTitlesForTableView:(UITableView )tableView;该方法的返回值用于在表格右边建立一列浮动的索引;
- (3)、- (NSString )tableView:(UITableView )tableView titleForHeaderInSection:(NSInteger)section;该方法的返回值决定指定分区的页眉;
- (4)、- (NSString )tableView:(UITableView )tableView titleForFooterInSection:(NSInteger)section;该方法的返回值决定指定分区的页脚;
实例:多分区以及分区索引
@interface RootViewController ()
{
NSDictionary* tableData;
NSArray* stories;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, self.view.frame.size.height - 50)];
_table.delegate = self;
_table.dataSource = self;
[self.view addSubview:_table];
tableData = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObjects:@"孙悟空",@"猪八戒",@"牛魔王",@"蜘蛛精",@"唐僧",@"沙和尚", nil],@"西游记",[NSArray arrayWithObjects:@"宝玉",@"黛玉",@"元春",@"探春",@"惜春",@"可卿", nil],@"红楼梦",[NSArray arrayWithObjects:@"武松",@"林冲",@"鲁达",@"杨志",@"宋江",@"史进", nil],@"水浒", [NSArray arrayWithObjects:@"关羽",@"刘备",@"张飞",@"曹操",@"张辽",@"吕布", nil],@"三国演义",nil];
//获取tableData的所有key排序后组成的数组
stories = [[tableData allKeys]sortedArrayUsingSelector:@selector(compare:)];
//可以自定义索引
UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTitle:@"选择" forState:UIControlStateNormal];
btn.frame = CGRectMake(0, 20, 60, 30);
[btn addTarget:self action:@selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
//自定义索引的选择方法
- (void)btnClicked{
[_table scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:2] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
#pragma mark - UITableViewDelegate
#pragma mark - UITableViewDataSource
//UITableViewDataSource协议中定义的方法。该方法的返回值决定表格包含多少个分区
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return stories.count;
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区包含多少个元素
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//获取指定分区对应的stories集合中的元素
NSString* story = [stories objectAtIndex:section];
//该stories集合元素包含多少个人物,该分区就包含多少表格行
return [[tableData objectForKey:story] count];
}
//行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
//自定义cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//为表格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//获取可重用的单元格
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
//获取分无号
NSUInteger sectionNo = indexPath.section;
//获取表格行的行号
NSUInteger rowNo = indexPath.row;
NSString* story = [stories objectAtIndex:sectionNo];
//将单元格的边框设置为圆角
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = YES;
//为表格行的textLabel设置文本
cell.textLabel.text = [[tableData objectForKey:story] objectAtIndex:rowNo];
return cell;
}
//UITableViewDataSource协议中定义的方法。该方法的返回值用于在表格右边创建一列浮动的索引
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return stories;
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区的页眉
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [stories objectAtIndex:section];
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区的页脚
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
NSString* story = [stories objectAtIndex:section];
return [NSString stringWithFormat:@"一共有%ld个人物",[[tableData objectForKey:story]count]];
}
@end
6、直接使用UITableViewController
如果应用界面中只需要显示一个表格,让用户控制器直接继承UITableViewController即可,UITableViewController已经实现了UITableViewDelegate和UITableViewDataSource协议,因此用起来更加方便;
此处不再详细介绍
@interface RootTableViewController ()
{
NSDictionary* tableData;
NSArray* stories;
}
@end
@implementation RootTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
tableData = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObjects:@"孙悟空",@"猪八戒",@"牛魔王",@"蜘蛛精",@"唐僧",@"沙和尚", nil],@"西游记",[NSArray arrayWithObjects:@"宝玉",@"黛玉",@"元春",@"探春",@"惜春",@"可卿", nil],@"红楼梦",[NSArray arrayWithObjects:@"武松",@"林冲",@"鲁达",@"杨志",@"宋江",@"史进", nil],@"水浒", [NSArray arrayWithObjects:@"关羽",@"刘备",@"张飞",@"曹操",@"张辽",@"吕布", nil],@"三国演义",nil];
//获取tableData的所有key排序后组成的数组
stories = [[tableData allKeys]sortedArrayUsingSelector:@selector(compare:)];
}
#pragma mark - Table view data source
//UITableViewDataSource协议中定义的方法。该方法的返回值决定表格包含多少个分区
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return stories.count;
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区包含多少个元素
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//获取指定分区对应的stories集合中的元素
NSString* story = [stories objectAtIndex:section];
//该stories集合元素包含多少个人物,该分区就包含多少表格行
return [[tableData objectForKey:story] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//为表格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//获取可重用的单元格
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
//获取分无号
NSUInteger sectionNo = indexPath.section;
//获取表格行的行号
NSUInteger rowNo = indexPath.row;
NSString* story = [stories objectAtIndex:sectionNo];
//将单元格的边框设置为圆角
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = YES;
//为表格行的textLabel设置文本
cell.textLabel.text = [[tableData objectForKey:story] objectAtIndex:rowNo];
return cell;
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区的页眉
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [stories objectAtIndex:section];
}
//UITableViewDataSource协议中定义的方法。该方法的返回值决定指定分区的页脚
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
NSString* story = [stories objectAtIndex:section];
return [NSString stringWithFormat:@"一共有%ld个人物",[[tableData objectForKey:story]count]];
}
7、静态单元格
需要使用storyboard,此处不再介绍;
8、使用iOS6新增的UIRefreshController刷新表格
当程序使用UITableViewController创建表格时,该控制器类可指定一个refreshControl属性,该属性值应该是一个UIRefreshControl控件(刷新控件),该控件可用于刷新表格数据。当程序创建UIRefreshController控件时,可为该空间爱你的刷新事件指定事件处理方法,当用户通过该刷新控件进行数据刷新时,系统就会激发该事件处理方法,该方法用于从底层数据库、网络、远程应用等地方检索数据,并将这些数据添加、显示到表格中。
(1)、设置refreshControl属性,该属性值应该是UIRefreshControl控件
self.refreshControl = [[UIRefreshControl alloc]init];
(2)、设置UIRefreshControl控件的颜色
self.refreshControl.tintColor = [UIColor grayColor];
(3)、设置该控件的提示标题
self.refreshControl.attributedTitle = [[NSAttributedString alloc]initWithString:@"下拉刷新"];
(4)为UIRefreshControl控件的刷新事件设置处理方法;
[self.refreshControl addTarget:self action:@selector(refreshData) forControlEvents:UIControlEventValueChanged];
//刷新实现方法
- (void)refreshData{
[self performSelector:@selector(handleData) withObject:nil afterDelay:2];
}
- (void)handleData{
NSString* randStr = [NSString stringWithFormat:@"%d",arc4random()%10000];
[list addObject:randStr];
self.refreshControl.attributedTitle = [[NSAttributedString alloc]initWithString:@"正在刷新..."];
//停止刷新
[self.refreshControl endRefreshing];
//控制表格重新加载数据
[self.tableView reloadData];
}
提示:该刷新只使用于UITableViewController
十七、搜索条(UISearchBar)
搜索条(UISearchBar)由一个文本框和几个按钮组成,当用户在文本框内输入部分内容之后,程序即可按指定的规则执行搜索。该搜索条的属性如下:
首先介绍前面提到过的大部分的属性
(1)、Text:设置搜索文本框内默认的文本;
例如:searchBar.text = @"你好";
(2)、Placeholder:设置搜素搜文本框的提示文本;
例如:searchBar.placeholder = @"请输入搜索文本";
(3)、Prompt:设置搜索文本框上面的标题;
例如:searchBar.prompt = @"...";
(4)、Search Style(UISearchBarStyle):设置搜索条的风格;
例如:searchBar.searchBarStyle = UISearchBarStyleMinimal;
(5)、Bar Tint:设置搜索条的颜色;
例如:searchBar.barTintColor = [UIColor whiteColor];
(6)、Options:
①、Shows Search Results Button:勾选该复选框后,将会在搜索文本框的右端显示一个如“三”形状的图标按钮,用户可通过单击该按钮激发特定的事件;
例如:searchBar.showsSearchResultsButton = YES;
②、Shows Bookmarks Button:勾选该复选框后,将会在搜索文本框的右端显示一个类似图书的书签按钮,用户可通过单击该按钮激发特定的事件;
例如:searchBar.showsBookmarkButton = YES;
③、Shows Cancel Button:勾选该复选框后,将会在搜索文本框的右端显示一个“Cancel”取消按钮,用户可通过单击该按钮激发特定的事件;
例如:searchBar.showsCancelButton = YES;
(7)、Shows scope Bar 与 Scope Titles
如果勾选Shows scope Bar复选框,系统将会在搜索框下显示一个分段条,接下来的Scope Titles将用于设置各分段的标题,如果Scope Titles包含三个列表项:aaa、bbb、ccc,则表明搜索框下方显示一个分为三段的分段条;当用户点击分段条上指定的分段按钮时,系统将会激发一个方法,从而允许程序通过该方法控制只对指定范围的数据执行搜索。
例如:searchBar.showsScopeBar = YES; searchBar.scopeButtonTitles = [NSArray arrayWithObjects:@"111",@"222",@"333", nil];
(8)、UISearchBar控件的不同部分会触发不同的事件,而这些事件也由该控件对应的委托对象处理,UISearchBar的委托对象必须实现UISearchBarDelegate协议,该协议中包含如下常见的事件处理方法:
#pragma mark - UISearchBarDelegate
- ①、- (void)searchBar:(UISearchBar )searchBar textDidChange:(NSString )searchText;当搜索文本框内的文本发生改变时激发该方法;
- ②、- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar;当用户点击搜索条的书签按钮时激发该方法;
- ③、- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar;当用户单击搜索条的取消按钮时激发该方法;
- ④、- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar;当用户单击搜索文本框关联键盘上的”Search”按钮时激发该方法;
- ⑤、- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar;当用户点击搜索条上的查询结果按钮时激发该方法;
- ⑥、- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope;当用户点击分段条上的分段按钮时激发该方法;
1、使用搜索条
声明部分:
#import <UIKit/UIKit.h>
#import "MyScrollView.h"
@interface RootViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate]] >
@property (nonatomic,strong)UITableView* table;
@property (nonatomic,strong)UISearchBar* search;
@end
实现部分
@interface RootViewController ()
{
NSArray* tableData;
NSArray* searchData;
BOOL isSearch;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - 20)];
_table.delegate = self;
_table.dataSource = self;
[self.view addSubview:_table];
isSearch = NO;
tableData = [NSArray arrayWithObjects:@"疯狂Java讲义",@"轻量级Java EE企业应用实战",@"疯狂Android讲义",@"疯狂Ajax讲义",@"疯狂HTML5/CSS3/JavaScript讲义",@"疯狂iOS讲义",@"疯狂XML讲义",@"经典Java EE企业应用实战",@"Java入门与精髓",@"Java基础教程",@"学习Java",@"Objective-C基础",@"Ruby入门与精髓",@"iOS开发教程", nil];
self.search = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 40)];
self.search.delegate = self;
_search.showsCancelButton = YES;
_table.tableHeaderView = _search;
}
#pragma mark - UITableViewDelegate
#pragma mark - UITableViewDataSource
//行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//如果处于搜索状态
if (isSearch) {
//使用searchData作为表格显示的数据
return searchData.count;
}else{
//否则使用原始的tableData作为表格显示的数据
return tableData.count;
}
}
//行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
//自定义cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//为表格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//获取可重用的单元格
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
//获取当前正在处理的表格行的行号
NSInteger rowNo = indexPath.row;
//如果处于搜索状态
if (isSearch) {
//使用searchData作为表格显示的数据
cell.textLabel.text = [searchData objectAtIndex:rowNo];
}else{
//否则使用原始的tableData作为表格显示的数据
cell.textLabel.text = [tableData objectAtIndex:rowNo];
}
return cell;
}
//UISearchBarDelegate定义的方法,用户单击取消按钮时激发该方法
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
//取消搜索状态
isSearch = NO;
[self.table reloadData];
}
//UISearchBarDelegate定义的方法,当搜索文本框内的文本改变激发该方法
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
//调用filterBySubstring:方法执行搜索
[self filterBySubstring:searchBar.text];
}
//UISearchBarDelegate定义的方法,用户单击模拟键盘上的Search按键时激发该方法
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
//调用filterBySubstring:方法
[self filterBySubstring:searchBar.text];
//放弃作为第一响应者,关闭键盘
[searchBar resignFirstResponder];
}
- (void)filterBySubstring:(NSString *)subStr{
//设置为搜索状态
isSearch = YES;
//定义搜索谓词
NSPredicate* pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS[C]%@",subStr];
//使用谓词过滤NSArray
searchData = [tableData filteredArrayUsingPredicate:pred];
//让表格控件重新加载数据
[self.table reloadData];
}
@end
2、使用UISearchDisplayController
待续
十八、导航条(UINavigationBar)与导航条控制器(UINavigationController)
当iOS应用需要显示具有层次化的工作流时,采用UINaviigationController比较合适,这样用户可以从上一层界面进入下一层界面,当用户在下一层界面处理完之后,用户可以方便地返回上一层界面。UINavigationController是一个控制器,用户交互行为则主要靠UINavigationBar(导航条)来完成;
1、使用导航条
导航条(UINavigationBar)通常是位于屏幕顶端的控件,它继承了UIView控件,且通常只是作为多个UINavigationItem的容器。在同一时刻,UINavigationBar只能看到最上面的额UINavigationItem,UINavigationBar最低层的控件被称为rootUINavigationItem,其关系如下
rootUINavigationItem——>UINavigationItem——>UINavigationBar
系统提供如下方法和属性来管理UINavigationBar中的UINavigationItem
- (1)、- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated;该方法用于将一个UINavigationItem压入UINavigationBar的栈中;
- (2)、- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated;该方法用于将一个UINavigationBar定栈UINavigationItem弹出栈;
- (3)、- (void)setItems:(NSArray *)items animated:(BOOL)animated;同时为UINavigationBar设置多个UINavigationItem控件;
(4)、items:该属性用于设置或返回UINavigationBar所包含的多个UINavigationItem控件;
例如:navigationBar.items = items;
(5)、topItem:该只读属性用于返回UINavigationItem控件最顶层的UINavigationItem控件;
例如:UINavigationItem* topItem = navigationBar.topItem;
(6)、backItem:该只读属性用于返回UINavigationItem控件最顶层下面的UINavigationItem控件;
例如:UINavigationItem* backItem = navigationBar.backItem;
(7)、barStyle(UIBarStyle):导航条类型;
例如:navigationBar.barStyle = UIBarStyleBlack;
(8)、barTintColor:导航条的背景颜色;
例如:navigationBar.barTintColor = [UIColor redColor];
(9)、- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics;设置导航条的背影图片;
其中枚举值为:- ①、UIBarMetricsDefault:默认的图片,支持横竖屏;
②、UIBarMetricsLandscapePhonePrompt:横屏情况下的图片
例如:[navigationBar setBackgroundImage:[UIImage imageNamed:@"1.png"] forBarMetrics:UIBarMetricsDefault];
(10)、设置按钮颜色;
例如:[navigationBar setTintColor:[UIColor redColor]];
UINavigationItem也作为一个容器,它由标题、左边N个按钮、右边N个按钮组成,每个按钮都是一个UIBarButtonItem控件。它提供了如下属性和方法配置UINavigationItem:
- (1)、title:设置UINavigationItem的标题文本;
- (2)、hidesBackButton:该属用于设置或返回是否显示后退按钮。如果该属性设置为YES,就会隐藏后退按钮;
- (3)、titleView:该属性用于设置或返回UINavigationItem的标题控件。如果设置了该属性,UINavigationItem将会使用自定义的标题控件;
- (4)、leftBarButtonItems:该属性用于设置或返回UINavigationItem左边的多个按钮组成的数组;
- (5)、leftBarButtonItem:该属性用于设置或返回UINavigationItem左边的单个按钮;
- (6)、rightBarButtonItem:该属性用于设置或返回UINavigationItem右边的多个按钮组成的数字;
- (7)、rightBarButtonItem:该属性用于设置或返回UINavigationItem右边的单个按钮;
- (8)、- (void)setHidesBackButton:(BOOL)hidesBackButton animated:(BOOL)animated;该方法用于设置是否显示后退按钮;
- (9)、- (void)setLeftBarButtonItems:(NSArray *)items animated:(BOOL)animated;该方法用于同时设置UINavigationItem左边的多个按钮;
- (10)、- (void)setLeftBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;该方法用于设置UINavigationItem左边的单个按钮;
- (11)、- (void)setRightBarButtonItems:(NSArray *)items animated:(BOOL)animated;该方法用于设置UINavigationItem右边的多个按钮;
- (12)、- (void)setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;该方法用于设置UINavigationItem右边的单个按钮;
@interface RootViewController ()
{
NSInteger count;
UINavigationBar* navigationBar;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
count = 1;
//创建一个导航栏
navigationBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, 44)];
//把导航添加到视图中
[self.view addSubview:navigationBar];
//调用push方法添加一个UINavigationItem
[self push];
}
- (void)push{
//把导航栏集合添加到导航栏中,设置动画打开
[navigationBar pushNavigationItem:[self makeNavItem] animated:NO];
count ++;
}
- (void)pop{
//如果导航栏中还有超过两个UINavigationItem
if (count > 2) {
[navigationBar popNavigationItemAnimated:NO];
count -- ;
}else{
//使用UIAlertView提示用户
UIAlertView* alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"只剩下一个导航项,再出栈就没有了" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
- (UINavigationItem *)makeNavItem{
//创建一个导航项
UINavigationItem* navigationItem = [[UINavigationItem alloc]initWithTitle:nil];
//创建一个左边按钮
UIBarButtonItem* leftButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(push)];
//创建一个右边按钮
UIBarButtonItem* rightButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(pop)];
//设置导航栏内容
navigationItem.title = [NSString stringWithFormat:@"第【%ld】个导航项",count];
//把左右两个按钮添加到导航栏集合中
[navigationItem setLeftBarButtonItem:leftButton];
[navigationItem setRightBarButtonItem:rightButton];
return navigationItem;
}
2、使用UINavigationController
与UINavigationBar完全的类似是,UINavigationController使用栈的形式来管理多个UIViewController(每个控制器对应的一个界面),UINavigationController不仅封装了UINavigationBar,而且会自动为每个接受它管理的UIViewController自动添加UINavigationBar,接受UIViewController管理的UIViewController对应的UI控件实际上位于UIViewController的NavigationView容器中,除此之外,UIViewController底部还可以设置一个工具条(UIToolBar对象)。
(1)、UINavigationController导航控制器如何使用
下面的图显示了导航控制器的流程。最左侧的是根视图,当用户点击其中的General项时,General视图会划入屏幕;当用户继续点击Auto-Lock,Auto-Lock视图将滑入屏幕。相应地,在对象管理上,导航控制器使用导航堆栈。根视图控制器在堆栈最底层,接下来入栈的是General视图控制器和Auto-Lock视图控制器。可以调用pushViewControllerAnimated:方法将视图控制器推入栈顶,也可以调用popViewControllerAnimated:方法将视图控制器弹出堆栈;
(2)、UINavigationController的结构组成
UINavigationController有NavigationBar,NavigationView,NavigationToolbar等组成
UINavigationController提供了如下属性和方法来操作接受UINavigationController管理的多个UIViewController:
- (1)、topViewController:该只读属性返回栈顶得UIViewController;
- (2)、visibleViewController:该只读属性返回UINavigationController中当前可见的界面对应的UIViewController;
- (3)、viewControllers:该属性设置或返回UINavigationController管理的栈中所有的UIViewController
- (4)、- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;该属性同时为UINavigationController设置所有的UIViewController;
- (5)、- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;该方法用于将指定的UIViewController压入UINavigationController管理的栈中;
- (6)、- (UIViewController *)popViewControllerAnimated:(BOOL)animated;该方法用于弹出UINavigationController管理的栈顶得UIViewController;
- (7)、- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated;该方法将会弹出除了rootUIViewController以外的所有UIViewController;
- (8)、- (NSArray )popToViewController:(UIViewController )viewController animated:(BOOL)animated;该方法用于弹出到指定的UIViewController。
UINavigationController提供了如下属性和方法来配置导航条:
- (1)、navigationBar:该只读属性返回该UINavigationController管理的导航条;
- (2)、navigationBarHidden:该属性用于设置或者返回是否隐藏导航条;
- (3)、- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;该方法用于设置是否隐藏导航条;
(4)、用自定义的图片来替换返回按钮的V型;
例如:[self.navigationController.navigationBar setBackIndicatorImage:image]; [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:image];
UINavigationController提供如下属性来配置导航标题
(1)、title:设置导航条中间标题;
例如:self.title = @"好人"; self.navigationItem.title = @"好人”;
注意:self.title可以改变self.navigationItem.title,反之不可以;
(2)、改变title的字体属性;
例如:NSFontAttributeName 字体key; NSForegroundColorAttributeName NSTextAttributeTextColor 字体颜色key
例如:
[self.navigationController.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font,NSFontAttributeName,[UIColor redColor],NSForegroundColorAttributeName, nil]];
UINavigationController提供了如下属性来配置工具条:
- (1)、toolbar:该只读属性返回该UINavigationController管理的工具条;
- (2)、- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated;该方法用于设置是否隐藏工具条;
- (3)、toolbarHidden:该属性用于设置或者返回是否隐藏工具条;
实例:查看、编辑图书信息
3、使用segue控制过渡
4、使用segue控制导航
待续
十九、网格(UICollectionView)与网格控制器(UICollectionViewController)
UICollectionView继承了UIScrollView,它具有UIScrollView的功能,这个UIScrollView中主要封装了UITableViewCell单元格控件,因此,UICollectionView默认可以对单元格进行滚动。默认状态下,IUCollectionViewController实例被自动设为UIScrollView委托。
组件一个UICollectionView不仅需要内容相关的对象,如DataSource和Delegate,还需要布局相关的对象即UICollectionViewLayout。
- DataSource:提供相关的data和view;
- Delegate:实现点击/插入/删除等操作时需要的方法;
- Layout:提供布局view(如cell,supplementary,decoration view)需要的相关数据
- UICollectionViewLayout:是一个新类,作用控制所有view显示,Layout会为每个view(如果需要显示),提供LayoutAttribute,通过LayoutAttribute,CollectionView就知道如何去组织;
- UICollectionViewLayoutAttributes:提供frame和伪3D的信息和UIKit的动态信息。
上图是UICollectionViewFlowLayout的一个布局,我们一次进行介绍:
- Cell:如上每一个单元格就是一个cell,和UITableViewCell一样,你可以进行自定义,添加image,Label等等
- Supplementary view:图中的Header和Footer就是Supplementary view;
- Decoration view:图中没有显示,不过顾名思义可以理解为修饰的view,如背景之类。他和Supplementary的区别在于,后者往往是和数据相关联的。
UICollectionView的属性如下:
Layout:该属性用于指定UICollectionView所使用的布局对象,它可支持Flow,Custom两个属性,如果指定Flow属性值,表明使用UICollectionViewFlowLayout布局对象录入过指定Custom属性值,则表明将会使用自定义的UICollectionViewLayout布局对象;
对UICollectionView而言,它大致由页眉控件,单元格,装饰控件,页脚控件组成。1、如果选择Flow,在Xcode的dock面板中可以看到UICollectionView的下面包含一个CollectionViewFlowLayout对象,该对象布局采用“流”的方式管理UICollectionView中的所有单元格,这些单元格要么横向排列,要么纵向排列,其效果就像一个网格。
UICollectionViewFlowLayout的属性如下
①、Cell Size:设置每个单元格的宽和高;itemSize:该属性用于设置单元格的宽度和高度;
例如:flowLayout.itemSize = CGSizeMake(120, 160);
②、Header Size:设置各分区的页眉控件的宽和高;
例如:flowLayout.headerReferenceSize = CGSizeMake(120, 40);
③、Footer Size:设置各分区的页脚控件的宽和高;
例如:flowLayout.footerReferenceSize = CGSizeMake(120, 40);
④、Min Spacing:设置各单元格之间的最小行间距和最小列间距;
minimumLineSpacing:用于控制单元格之间的最小行间距;
例如:flowLayout.minimumLineSpacing = 12;
⑤、minimumInteritem Spacing:用于控制单元格之间的最小列间距;
例如:flowLayout.minimumInteritemSpacing = 12;
⑥、Section Insets:设置各分区上、下、左、右空白区的大小;
例如:lowLayout.sectionInset = UIEdgeInsetsMake(0, 2, 0, 0);
⑦、scrollDirection:用于控制UICollectionView的滚动方向;
例如:flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
- 2、如果该属性选择Custom,UICollection对象的属性检查器面板则只会显示如下界面;
- (2)、Scroll Direction:该属性实际上来自UICollectionViewFlowLayout布局对象,如果将Layout属性设为Custom属性值,该下拉属性选择器就会消失。该属性用于设置该控件的滚动方向,他支持Vertical和Horizontal两个属性值,分别代表垂直滚动和水平滚动。
- (3)、Accessories:该属性是否显示UICollectionView分区的页眉和页脚。
与UITableView控件类似的是,UICollectionView同样采用分区(section)来管理过个单元格(cell),同样适用NSIndexPath来封装单元格的位置信息,包括该单元格所在的分区号、行号等信息;
1、UICollectionView的功能和用法
声明部分
#import <UIKit/UIKit.h>
@interface MyRootViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource]] >
@property (nonatomic ,strong) UICollectionView* collextionView;
@end
实现部分
@interface MyRootViewController ()
{
NSArray* books;
NSArray* covers;
}
@end
@implementation MyRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建并初始化NSArray对象
books = [NSArray arrayWithObjects:@"疯狂Ajax讲义",@"疯狂Android",@"疯狂HTML5/CSS3/JavaScripts讲义",@"疯狂Java讲义",@"疯狂Java程序员基本修养",@"轻量级Java EE企业应用实战",@"经典Java EE企业应用实战",@"疯狂XML讲义", nil];
//创建并初始化NSArray
covers = [NSArray arrayWithObjects:@"1.png",@"2.pmg",@"3.png",@"4.png",@"5.png",@"6.png",@"7.png",@"8.png", nil];
//为当前导航项设置标题
self.navigationItem.title = @"图书列表";
//创建UICollectionViewFlowLayout布局对象
UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
// flowLayout.footerReferenceSize = CGSizeMake(120, 40);
// flowLayout.headerReferenceSize = CGSizeMake(120, 40);
// flowLayout.minimumInteritemSpacing = 12;
// flowLayout.minimumLineSpacing = 12;
//设置UIVollectionView中单元格的大小
flowLayout.itemSize = CGSizeMake(self.view.frame.size.width/2 - 20, 160);
//设置该UICollectionView只支持水平移动
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
//设置各分区上、下、左、右空白的大小
flowLayout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
//为UICollectionView设置dataSource和delegate
self.collextionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowLayout];
_collextionView.dataSource = self;
_collextionView.delegate = self;
//为UICollectionView设置布局对象
[_collextionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId"];
_collextionView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_collextionView];
}
#pragma mark --UICollectionViewDataSource
//该方法的返回值决定个单元格的控件
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//为单元格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//从可重用单元格的队列中取出一个单元格
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
//设置圆角
cell.layer.cornerRadius = 8;
cell.layer.masksToBounds = YES;
cell.backgroundColor = [ UIColor colorWithRed :(( arc4random ()% 255 )/ 255.0 ) green :(( arc4random ()% 255 )/ 255.0 ) blue :(( arc4random ()% 255 )/ 255.0 ) alpha : 1.0f ];
return cell;
}
//该方法的返回值决定UICollectionView包含多少个单元格
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return books.count;
}
2、使用UICollectionViewDelegateFlowLayout定制布局
如果直接使用UICollectionViewFlowLayout布局对象来管理UICollectionView的所有单元格,那么这些单元格的大小、单元格之间的间距和行距都是相同的。当UICollectionView端丽的所有单元格控件的大小本来就是相同时,直接使用UICollectionViewFlowLayout,即可实现非常整齐的网络效果。
但是在某些时候,UICollectionView控件中个单元格的大小是参差不齐的,如果强行将这些控件缩放到同一大小,势必会影响现实效果。如果程序需要让UICollectionView中各控件各自显示不同的大小,则可借助UICollectionViewDelagateFlowLayout协议来实现。
UICollectionViewDelegateFlowLayout协议继承了UICollectionViewDelegate协议,因此实现该协议的对象可以当成UICollectionView的委托对象使用。UICollectionViewDelegateFlowLayout一些额外定义了如下常用方法:
#pragma mark --UICollectionViewDelegateFlowLayout
- (1)、- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;该方法返回的CGSize对象将控制指定NSIndexPath对应的单元格大小;
- (2)、- (UIEdgeInsets)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;该方法返回的UIEdgeInsets对象将控制指定分区上、下、左、右空白区域的大小;
- (3)、- (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;该方法返回的长度值将控制指定分区内最小的行间距;
- (4)、- (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;该方法返回的长度值将控制指定分区内最小的列间距;
- (5)、- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;该方法返回的CGSize将控制指定分区的页眉控件的大小;
- (6)、- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;该方法返回的CGSize将控制指定分区的页脚控制的大小;
实例:单元格大小不同的网格
不在举例
3、扩展UICollectionViewLayout定制布局
如果采用UICollectionViewFlowLayout管理UICollectionView中单元格的布局,所有的单元格总会分布成网格形式。如果希望UICollectionView以更复杂,更灵活的方式对单元格进行布局,可以通过集成UICollectionViewLayout,实现自己的布局管理器来实现,通过这种方式,开发者激活而已任意控制UICollectionView中单元格的布局。
——继承UICollectionFlowLayout时,通常会重写如下常用的方法:
- (1)、- (void)prepareLayout;开始布局时调用该方法执行准备工作;
(2)、- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;该方法返回值控制只大牛股NSRect区域内所有单元格的大小和位置等布局信息;
- ①、返回rect中所有的元素的布局属性;
- ②、返回的是包含UICollectionViewLayoutAttributes的NSArray
③、UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法得到不同类型的UICollectionViewLayoutAttributes:
①、- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath; ②、- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath; ③、- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath;
- (3)、- (UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath;该方法返回值控制指定NSIndexPath对应的单元格的大小和位置等布局信息;
- (4)、- (UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)indexPath;该方法返回值控制指定分区的页眉控件、页脚控件的大小和位置等布局信息;返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载;
- (5)、- (UICollectionViewLayoutAttributes )layoutAttributesForDecorationViewOfKind:(NSString)elementKind atIndexPath:(NSIndexPath *)indexPath;该方法的返回值控制指定分区的装饰控件的大小和位置等布局信息;返回对应于indexPath的位置的装饰视图的布局属性,如果没有装饰视图可不重载;
——如果程序希望控制UICollectionView的单元格显示、隐藏时的动画效果,还可以重写如下方法:
- (1)、- (UICollectionViewLayoutAttributes )initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath )itemIndexPath;每当单元格动态增加时,自动调用该方法;
- (2)、- (UICollectionViewLayoutAttributes )initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)elementIndexPath;每当指定分区的页眉控件或页脚控件动态增加时,自动调用该方法;
- (3)、- (UICollectionViewLayoutAttributes )initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;每当指定分区的装饰控件动态增加时,自动调用该方法;
- (4)、- (UICollectionViewLayoutAttributes )finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath )itemIndexPath;每当单元格动态消失时自动调用该方法;
- (5)、- (UICollectionViewLayoutAttributes )finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)elementIndexPath;每当指定分区的页眉控件或页脚控件动态消失时自动调用该方法;
(6)、- (UICollectionViewLayoutAttributes )finalLayoutAttributesForDisappearingDecorationElementOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)decorationIndexPath;每当指定分区的装饰控件动态消失时自动调用该方法;
提示: 初始化一个UICollectionViewFlowLayout实例后,会有一系列准备方法被自动调用,以保证layout实例的争取: 首先,-(void)prepareLayout将被调用,默认下该方法什么没做,但是在自己的子类实现中,一般在该方法中设定一些必要的layout的结构和初始需要的参数等。 之后,-(CGSize) collectionViewContentSize将被调用,以确定collection应该占据的尺寸。注意这里的尺寸不是指可视部分的尺寸,而应该是所有内容所占的尺寸。collectionView的本质是一个scrollView,因此需要这个尺寸来配置滚动行为。 接下来-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect被调用,这个没什么值得多说的。初始的layout的外观将由该方法返回的UICollectionViewLayoutAttributes来决定。
另外,在需要更新layout时,需要给当前layout发送 -invalidateLayout,该消息会立即返回,并且预约在下一个loop的时候刷新当前layout,这一点和UIView的setNeedsLayout方法十分类似。在-invalidateLayout后的下一个collectionView的刷新loop中,又会从prepareLayout开始,依次再调用-collectionViewContentSize和-layoutAttributesForElementsInRect来生成更新后的布局。
实例:环形布局的UICollectionView
MyRootViewController.h声明部分
#import <UIKit/UIKit.h>
@interface MyRootViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource]] >
@property (nonatomic ,strong) UICollectionView* collextionView;
@end
MyRootViewController.m实现部分
#import "MyRootViewController.h"
#import "FKCircleLayout.h"
@interface MyRootViewController ()
{
NSInteger cellCount;
}
@end
@implementation MyRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
cellCount = 16;
//创建自定义的FKCircleLayout布局对象
FKCircleLayout* circleLayout = [[FKCircleLayout alloc]init];
//设置自定义布局对象
self.collextionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:circleLayout];
_collextionView.backgroundColor = [UIColor purpleColor];
//为UICollectionView设置dataSource和delegate
_collextionView.dataSource = self;
_collextionView.delegate = self;
//为UICollectionView设置布局对象
[_collextionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId"];
// _collextionView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_collextionView];
//创建一个处理点击的手势处理器
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
[_collextionView addGestureRecognizer:tapRecognizer];
//为当前导航项设置标题
self.navigationItem.title = @"圆形";
}
#pragma mark --UICollectionViewDataSource
//该方法的返回值决定UICollectionView包含多少个单元格
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return cellCount;
}
//该方法的返回值决定个单元格的控件
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//为单元格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//从可重用单元格的队列中取出一个单元格
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
//定义处理点击手势的方法
- (void)handleTap:(UITapGestureRecognizer *)sender{
if (sender.state == UIGestureRecognizerStateEnded) {
//获取点击的位置
CGPoint initoalPinchPoint = [sender locationInView:_collextionView];
//获取电机电所在的NSIndexPath(可用于获取被点击的单元格)
NSIndexPath* tappedCellPath = [_collextionView indexPathForItemAtPoint:initoalPinchPoint];
//如果被点击的单元格存在
if (tappedCellPath) {
cellCount --;//减少一个单元格
//删除被点击的单元格
[_collextionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:tappedCellPath]];
}else{
cellCount++;//增加一个单元格
//在UICollectionView的开始处添加一个单元格
[_collextionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:0 inSection:0]]];
}
}
}
FKCircleLayout.h声明部分
#import <UIKit/UIKit.h>
@interface FKCircleLayout : UICollectionViewLayout
@property (nonatomic,assign)CGPoint center;
@property (nonatomic,assign)CGFloat radius;
@property (nonatomic,assign)NSInteger cellCount;
@end
FKCircleLayout.m实现部分
#import "FKCircleLayout.h"
#define ITEM_SIZE 72
@implementation FKCircleLayout
//开始执行的方法
- (void)prepareLayout{
[super prepareLayout];
CGSize size = self.collectionView.frame.size;
//计算需要包含多少个单元格
_cellCount = [[self collectionView] numberOfItemsInSection:0];
//计算环的圆心
_center = CGPointMake(size.width/2.0, size.height/2.0);
//计算环的半径(以宽、高中较小值的2.5分之一作为半径)
_radius = MIN(size.width, size.height)/2.5;
}
//该方法的返回值决定UICollectionView所包含控件的大小
- (CGSize)collectionViewContentSize{
return [self collectionView].frame.size;
}
//该方法返回的UICollectionViewLayoutAttributes控制指定单元格的大小和位置
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
//创建一个UICollectionViewLayoutAttributes控制指定单元格的大小和位置
UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//设置各单元格的大小
attributes.size = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
//设置单元格的中心点坐标
//由于程序需要控制各单元格绕成一个圆圈,因此此处使用了三角函数进行计算
attributes.center = CGPointMake(_center.x + _radius * cosf(2 * M_PI * indexPath.item/_cellCount), _center.y + _radius * sinf(2 * M_PI * indexPath.item/_cellCount));
return attributes;
}
//该方法的返回值控制UICollectionViewLayoutAttributes集合依次控制
//指定CGRect范围内各单元格大小和位置
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray* attributes = [NSMutableArray array];
//将控制每个单元格大小和位置的UIVollectionViewLayoutAttributes
//添加到NSArray中
for (NSInteger i = 0; i < _cellCount; i ++) {
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
return attributes;
}
//每当单元格动态显示时自动调用该方法
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath{
UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
attributes.alpha = 0.0;
attributes.center = CGPointMake(_center.x, _center.y);
return attributes;
}
//每当单元格动态消失时自动调用该方法
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath{
UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
attributes.alpha = 0.0;
attributes.center = CGPointMake(_center.x, _center.y);
attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
return attributes;
}
4、多分区网格
与UITableView类似的是,UICollectionView同样支持多分区,如果需要实现多分区UICollectionView控件,则需要重写UICollectionViewDataSource协议的numberOfSectionInCollectionView:方法,该方法的返回值控制该UICollectionView可以包含多少个分区;
如果程序需要为各分区添加页眉控件和页脚控件,还需要重写UICollectionViewDataSource协议中的-collectionView:viewForSupplementaryElementOfKind:atIndexPath:方法,该方法返回的控件将作为各分区的页眉、页脚控件。
实例:带页眉、页脚的多分区网格
MyRootViewController.h的声明部分
#import <UIKit/UIKit.h>
@interface MyRootViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource]] >
@property (nonatomic ,strong) UICollectionView* collextionView;
@end
MyRootViewController.m的实现部分
@interface MyRootViewController ()
{
NSDictionary* books;//定义保存所有图书信息的NSDictionary对象
NSArray* authors;//定义保存所有作者的NSArray对象
NSDictionary* covers;//定义所有图书封面的NSDictionary对象
NSDictionary* header;//定义所有作者头像的NSDictionary对象
}
@end
@implementation MyRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置导航的标题
self.navigationItem.title = @"图书列表";
//创建并开始初始化NSDictionary对象
books = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObjects:@"疯狂Ajax讲义",@"疯狂Android",@"疯狂HTML5/CSS3/JavaScripts讲义",@"疯狂Java讲义",@"疯狂Java程序员基本修养",@"轻量级Java EE企业应用实战",@"经典Java EE企业应用实战",@"疯狂XML讲义", nil],@"李刚",[NSArray arrayWithObjects:@"醒世恒言",@"喻世明言",@"警世通言", nil],@"冯梦龙", nil];
//authors保存books的所有key
authors = [[books allKeys] sortedArrayUsingSelector:@selector(compare:)];
//为所有作者保存头像
header = [NSDictionary dictionaryWithObjectsAndKeys:@"1.png",@"李刚",@"2.png",@"冯梦龙", nil];
//创建并初始化NSArray对象
covers = [NSDictionary dictionaryWithObjectsAndKeys:@"1.png",@"疯狂Ajax讲义",@"2.png",@"疯狂Android",@"3.png",@"疯狂HTML5/CSS3/JavaScripts讲义",@"4.png",@"疯狂Java讲义",@"5.png",@"疯狂Java程序员基本修养",@"6.png",@"轻量级Java EE企业应用实战",@"7.png",@"经典Java EE企业应用实战",@"8.png",@"疯狂XML讲义", @"11.png",@"醒世恒言",@"12.png",@"喻世明言",@"13.png",@"警世通言",nil];
//创建UICollectionViewLayout对象
UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
//设置单元格的大小
flowLayout.itemSize = CGSizeMake(160, 200);
//设置flowLayout的滚动方向
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flowLayout.sectionInset = UIEdgeInsetsMake(0, 2, 0, 0);
flowLayout.headerReferenceSize = CGSizeMake(80, 80);
flowLayout.footerReferenceSize = CGSizeMake(50, 240);
//为UICollectionView设置布局管理器具
self.collextionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:flowLayout];
_collextionView.backgroundColor = [UIColor purpleColor];
//为UICollectionView设置dataSource和delegate
_collextionView.dataSource = self;
_collextionView.delegate = self;
//为UICollectionView设置布局对象
[_collextionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellId”];
//为页眉设置标识符
[_collextionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"headerId”];
//为页脚设置标识符
[_collextionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"supplyId"];
[self.view addSubview:_collextionView];
}
#pragma mark --UICollectionViewDataSource
//该方法的返回值控制该UICollectionView包含多少个分区
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return authors.count;
}
//该方法的返回值决定UICollectionView包含多少个单元格
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
//获取该分区对象的作者
NSString* author = [authors objectAtIndex:section];
//返回该作者对象的图书的数量
return [[books objectForKey:author] count];
}
//该方法返回值将左前卫指定分区的页眉控件和页脚控件
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
//为表格行定义一个静态字符串作为标识符
static NSString* headerId = @"headerId";
static NSString* supplyId = @"supplyId";
UICollectionReusableView* view;
if (kind == UICollectionElementKindSectionHeader) {
//从可重用队列中取出一个UICollectionReusableView
view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerId forIndexPath:indexPath];
//取出页眉控件中
view.backgroundColor = [UIColor redColor];
}
//如果正在处理页脚控件
if (kind == UICollectionElementKindSectionFooter) {
//从可重用队列中取出一个UICollectionResuableView
view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:supplyId forIndexPath:indexPath];
view.backgroundColor = [UIColor yellowColor];
}
return view;
}
//该方法的返回值决定个单元格的控件
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//为单元格定义一个静态字符串作为标识符
static NSString* cellId = @"cellId";
//从可重用单元格的队列中取出一个单元格
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
cell.backgroundColor = [ UIColor colorWithRed :(( arc4random ()% 255 )/ 255.0 ) green :(( arc4random ()% 255 )/ 255.0 ) blue :(( arc4random ()% 255 )/ 255.0 ) alpha : 1.0f ];
return cell;
}
5、UICollectionViewDataSource代理方法
#pragma mark --UICollectionViewDataSource
- (1)、- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;返回UICollectionView区(section)的个数,如果没有该方法,默认返回1;
- (2)、- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;返回指定区(section)包含的数据源条目数(number of items),该方法必须是实现;
- (3)、- (UICollectionViewCell )collectionView:(UICollectionView )collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;返回否个indexPath对应的cell,该方法必须实现;
(4)、- (UICollectionReusableView )collectionView:(UICollectionView )collectionView viewForSupplementaryElementOfKind:(NSString )kind atIndexPath:(NSIndexPath )indexPath;为UICollectionView添加一个补充视图(页眉或页脚控件);
特别注意:在添加页眉或者页脚之前需要注册类和标识; - (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
6、直接使用UICollectionViewController
待续。
二十、标签条(UITabBar)与标签页控制器
1、使用UITabBar
UITabBar属性如下:
- (1)、Tint:该属性对应UITabBar的tintColor属性,它用于设置UITabBar控件的背景图片;
例如:tabBar.tintColor = [UIColor yellowColor];//貌似没有用 - (2)、ImageTint:该属性对应UITabBar的selectedImageTintColor属性,它用于设置UITabBar控件选中项上标题的高亮颜色;
例如:tabBar.selectedImageTintColor = [UIColor blackColor]; (3)、Bar Tint:该属性对应UITabBar的TintColor属性,它用于设置UITabBar控件的颜色;
例如:tabBar.barTintColor = [UIColor purpleColor];
UITabBar代表一个标签条,它是UITabBarItem的容器,可用于组合多个UITabBarItem对象,每个UITabBarItem对象代表一个标签项。UITabBar提供了如下属性和方法来访问它所包含的标签项;
(1)、items:通过该属性即可返回该UITabBar所包含的多个UITabBarItem对象;
例如:tabBar.items = [NSArray arrayWithObjects:tabBarItem1,tabBarItem2, nil];
(2)、selectedItem:该属性用于返回该UITabBar当前被选中的标签项;
例如:tabBar.selectedItem = tabBarItem1;
- (3)、- (void)setItems:(NSArray *)items animated:(BOOL)animated;该属性用于设置该UITabBar所包含的多个UITabBarItem对象;
UITabBarItem代表一个标签项,通常由一个图标和一个标签标题组成,因此程序可通过如下方法来创建UITabBarItem:
- (1)、- (instancetype)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag;使用指定的系统图标和指定标签创建UITabBarItem;
- (2)、- (instancetype)initWithTitle:(NSString )title image:(UIImage )image tag:(NSInteger)tag;使用自定义标题、自定义图标和指定标签创建UITabBarItem;
(3)、badgeValue:用于设置一个徽标,该徽标将会以红色圆圈显示在标签项的右上角;
例如:tabBarItem1.badgeValue = @"热";
如果程序想要监听用户点击了那个标签项,只要为UITabBar设置一个delegate属性即可,该属性值必须是一个实现UITabBarDelegate协议的对象。当用户选中某个标签项时,将会激发UITabBarDelegate协议中的-tabBar:didSelectItem:方法;
#pragma mark - UITabBarDelegate
- (1)、- (void)tabBar:(UITabBar )tabBar didSelectItem:(UITabBarItem )item;在点击UITabBarItem时调用该方法;
- (2)、- (void)tabBar:(UITabBar )tabBar willBeginCustomizingItems:(NSArray )items;在UITabBar的item将要开始改动的时候调用该方法;
- (3)、- (void)tabBar:(UITabBar )tabBar didBeginCustomizingItems:(NSArray )items;在UITabBar的item已经开始改动的时候调用该方法;
- (4)、- (void)tabBar:(UITabBar )tabBar willEndCustomizingItems:(NSArray )items changed:(BOOL)changed;在UITabBar的item将要结束改动的时候调用该方法;
- (5)、- (void)tabBar:(UITabBar )tabBar didEndCustomizingItems:(NSArray )items changed:(BOOL)changed;在UITabBar的item改动的时候调用该方法;
2、使用UITabBarController
NSMutableArray* controllers = [NSMutableArray array];
UITabBarController* tabBarController = [[UITabBarController alloc]init];
tabBarController.tabBar.barTintColor = [UIColor purpleColor];
tabBarController.tabBar.selectedImageTintColor = [UIColor yellowColor];
for (int i = 0; i < 2 ; i ++) {
UIViewController* vc;
if (i == 0) {
vc = [[FirstViewController alloc]init];
vc.tabBarItem.badgeValue = @"热";
}else{
vc = [[SecondViewController alloc]init];
}
UINavigationController* nc = [[UINavigationController alloc]initWithRootViewController:vc];
vc.title = [NSString stringWithFormat:@"%d页面",i];
vc.tabBarItem.image = [[UIImage imageNamed:[NSString stringWithFormat:@"frum%d.png",i + 1]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc.tabBarItem.selectedImage = [[UIImage imageNamed:[NSString stringWithFormat:@"infoicon%d.png",i + 1]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[controllers addObject:nc];
}
tabBarController.viewControllers = controllers;
tabBarController.selectedIndex = 1;
self.window.rootViewController = tabBarController;
UITabBar上最多可以显示5个Tab,当我们往UITabBarController中添加超过的viewController超过5个时候,最后一个就会自动变成,按照设置的viewControlles的顺序,显示前四个viewController的tabBarItem,后面的tabBarItem将不再显示。当点击more时候将会弹出一个标准的navigationViewController,里面放有其它未显示的的viewController,并且带有一个edit按钮,通过点击该按钮可以进入类似与ipod程序中设置tabBar的编辑界面。编辑界面中默认所有的viewController都是可以编辑的,我们可以通过设置UITabBarController的customizableViewControllers属性来指定viewControllers的一个子集,即只允许一部分viewController是可以放到tabBar中显示的。但是这块儿要注意一个问题就是每当UITabBarController的viewControllers属性发生变化的时候,customizableViewControllers就会自动设置成跟viewControllers一致,即默认的所有的viewController都是可以编辑的,如果我们要始终限制只是某一部分可编辑的话,记得在每次viewControlles发生改变的时候,重新设置一次customizableViewControllers。
#pragma mark - UITabBarControllerDelegate
- (1)、- (BOOL)tabBarController:(UITabBarController )tabBarController shouldSelectViewController:(UIViewController )viewController;该代理方法的返回值设置该UITabBarItem是否可选择,返回YES代表可选择;返回NO代表不可选择;
- (2)、- (void)tabBarController:(UITabBarController )tabBarController didSelectViewController:(UIViewController )viewController;当选中UITabBarItem时调用该方法;
- (3)、- (void)tabBarController:(UITabBarController )tabBarController willBeginCustomizingViewControllers:(NSArray )viewControllers;在将要开始编辑的时候调用带方法;
- (4)、- (void)tabBarController:(UITabBarController )tabBarController willEndCustomizingViewControllers:(NSArray )viewControllers changed:(BOOL)changed;在将要结束编辑的时候调用该方法;
- (5)、- (void)tabBarController:(UITabBarController )tabBarController didEndCustomizingViewControllers:(NSArray )viewControllers changed:(BOOL)changed;在已经结束编辑的时候调用该方法;
3、在StoryBoard中使用UITabBarController
待续。
二十一、页控件(UIPageControl)与页控制器(UIPageViewController)
页控件(UIPageControl)是一个比较简单的控件,该控件由N各小圆点组成,每个圆点代表一个页面,当前页面以高亮的圆点显示。而页控制器(UIPageViewController)则可用于方便地实现“翻页”效果;
1、UIPageControl与UIScrollView结合使用
UIPageControl继承了UIControl基类,默认属于活动控件,它可以与用户交互,并激发Value Changed事件处理方法;UIPageControl的属性如下:
(1)、Page:设置总页数和当前第几页;
例如:pc.numberOfPages = 5;
(2)、Behavior:该包括两个复选框
①、Hides for Single Page:当只有一个隐藏该控件;
例如:pc.hidesForSinglePage = YES;
②、Defers Page Display:延迟显示当前页;
例如:pc.defersCurrentPageDisplay = YES;
(3)、Tint Color:设置小圆点的颜色;
例如:pc.pageIndicatorTintColor = [UIColor blackColor];
(4)、Current Page:设置高亮圆点的颜色;
例如:pc.currentPage = 1; pc.currentPageIndicatorTintColor = [UIColor purpleColor];
例如:
MyRootViewController.m的实现部分
#import "MyRootViewController.h"
#import "FKPageViewController.h"
@interface MyRootViewController (){
UIScrollView* _scrollView;
NSMutableArray* viewControllers;
UIPageControl* pageControl;
NSArray* contentList;
NSArray* coverList;
}
@end
@implementation MyRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
contentList = [NSArray arrayWithObjects:@"疯狂Android讲义",@"疯狂Ajax讲义",@"疯狂XML讲义",@"疯狂HTML5/CSS3/JavaScript讲义", nil];
coverList = [NSArray arrayWithObjects:@"1.png",@"2.png",@"3.png",@"4.png", nil];
NSUInteger numberPages = contentList.count;
//程序将会采用延迟加载的方式来创建FKPageController控制器
//因此此处只向数组中添加一些null作为占位符
//等到程序需要时才真正创建FKPageController控制器
viewControllers = [[NSMutableArray alloc]init];
for (NSUInteger i = 0; i < numberPages; i ++) {
[viewControllers addObject:[NSNull null]];
}
//创建UIScrollView对象
_scrollView = [[UIScrollView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
//设置背景
_scrollView.backgroundColor = [UIColor grayColor];
_scrollView.pagingEnabled = YES;
//设置UIScrollView的contentSize——就是它的可滚动区域的大小
_scrollView.contentSize = CGSizeMake(CGRectGetWidth(_scrollView.frame)*numberPages, CGRectGetHeight(_scrollView.frame));
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
//设置该控制器作为UIScrollView的委托对象
_scrollView.delegate = self;
[self.view addSubview:_scrollView];
//创建UIPageControl控件
pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(0, CGRectGetWidth(_scrollView.frame) - 80, CGRectGetWidth(_scrollView.frame), 80)];
//设置UIPageControl的圆点的颜色
pageControl.pageIndicatorTintColor = [UIColor grayColor];
//设置UIPageControl的高亮圆点的颜色
pageControl.currentPageIndicatorTintColor = [UIColor redColor];
//设置UIPageControl控件当前显示第几页
pageControl.currentPage = 0;
//设置UIPageControl控件总共包含多少页
pageControl.numberOfPages = numberPages;
pageControl.hidesForSinglePage = YES;
//为pageControl的Value Changed事件绑定事件处理方法
[pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:pageControl];
//初始化时默认只需加载、显示第一页的View
[self loadScrollViewWithPage:0];
//为了避免“翻页”时才加载下一页导致删除,同时把下一页的view也加载出来
[self loadScrollViewWithPage:1];
}
//自定义方法,用于加载UIScrollPage的指定页对应的控制器
- (void)loadScrollViewWithPage:(NSUInteger)page{
//如果超出总页数,方法直接返回
if (page >= contentList.count) {
return;
}
//获取page索引处的控制器
FKPageViewController* controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
//创建FKPaheViewController对象
controller = [[FKPageViewController alloc]initWithPageNumber:page];
//用FKPaheViewController对象替换page索引处原来的对象
[viewControllers replaceObjectAtIndex:page withObject:controller];
}
//将controller控制器对应的view添加到UIScrollView中
if (controller.view.superview == nil) {
CGRect frame = _scrollView.frame;
frame.origin.x = CGRectGetWidth(frame)*page;
frame.origin.y = 0;
//设置该控制器对应的View的大小和位置
controller.view.frame = frame;
//设置controller控制器的bookLabel控件的文本
controller.bookLabel.text = [contentList objectAtIndex:page];
controller.bookImage.image = [UIImage imageNamed:[coverList objectAtIndex:page]];
//将controller控制器添加为当前控制器的子控制器
[self addChildViewController:controller];
//将controller控制器对应的View添加到UIScrollView中
[_scrollView addSubview:controller.view];
}
}
//来自UIScrollViewDelegate的方法,当用户滚动的UIScrollView后激发该方法
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
//获取UIScrollView控件的宽度,也就是页面的宽度
CGFloat pageWidth = CGRectGetWidth(scrollView.frame);
//用UIScrollView水平滚动的距离减去页面宽度的一半,除以页面宽度的结果再加1,即可得到当前处于第几页
NSUInteger page = floor((scrollView.contentOffset.x -pageWidth/2)/pageWidth) + 1;
//控制UIPageController显示当前处于第page页
pageControl.currentPage = page;
//为了避免“翻页”时才加载下一页导致删除,同时把上一页、下一页的view也加载出来
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
}
- (void)changePage:(UIPageControl *)sender{
NSInteger page = [sender currentPage];
//创建一个CGRect对象,该CGRect区域代表该UIScrollView将要显示的页
CGRect bounds = _scrollView.bounds;
bounds.origin.x = CGRectGetWidth(bounds) * page;
bounds.origin.y = 1;
//控制UIScrollView滚动到指定区域
[_scrollView scrollRectToVisible:bounds animated:YES];
//为了避免“翻页时才加载上一页 下一页导致闪烁
//因此加载当前页的view时,也把上一页,下一页的View加载出来
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
}
@end
FKPageViewController.h的声明部分
#import <UIKit/UIKit.h>
@interface FKPageViewController : UIViewController
@property (nonatomic, strong)UILabel* label;
@property (nonatomic, strong)UILabel* bookLabel;
@property (nonatomic, strong)UIImageView* bookImage;
- (id)initWithPageNumber:(NSInteger)pageNumber;
@end
FKPageViewController.m的实现部分
#import "FKPageViewController.h"
@interface FKPageViewController ()
@end
@implementation FKPageViewController
- (id)initWithPageNumber:(NSInteger)pageNumber{
self = [super init];
if (self) {
self.label = [[UILabel alloc]initWithFrame:CGRectMake(240, 10, 80, 30)];
_label.backgroundColor = [UIColor clearColor];
_label.textColor = [UIColor redColor];
_label.text = [NSString stringWithFormat:@"第【%ld】页",pageNumber + 1];
[self.view addSubview:_label];
self.bookLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 30, CGRectGetWidth(self.view.frame), 60)];
_bookLabel.textAlignment = NSTextAlignmentCenter;
_bookLabel.numberOfLines = 2;
_bookLabel.font = [UIFont systemFontOfSize:24];
_bookLabel.backgroundColor = [UIColor clearColor];
_bookLabel.textColor = [UIColor blueColor];
[self.view addSubview:_bookLabel];
self.bookImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 90, CGRectGetWidth(self.view.frame), 320)];
_bookImage.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:_bookImage];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
2、使用UIPageViewController
UIPageViewController可以开发出类似于图书分页的效果,该控件允许配置的选项并不多,只要为该控件指定翻页方向、翻页方式,是否支持双面等属性即可。
程序如果使用UIPageViewController控件,最关键在于配置dataSource属性,该属性必须指定一个为实现UIPageViewControllerDelegate协议的对象,该对象必须实现如下方法:
#pragma mark - UIPageViewControllerDataSource
- (1)、- (UIViewController )pageViewController:(UIPageViewController )pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;当用户通过UIPageViewController向前翻页时,程序将会调用该方法返回UIViewController作为前一个页面的视图控制器;
- (2)、- (UIViewController )pageViewController:(UIPageViewController )pageViewController viewControllerAfterViewController:(UIViewController *)viewController;当用户通过UIPageViewController向后翻页时,程序将会调用该方法返回UIViewController作为后一个页面的视图控制器;
例如:
在AppDelegate中设置
FKPageController* pageZero = [[FKPageController alloc]initWithPageNumber:0];
//创建一个NSDictionary对象,作为创建UIPageViewController的选项
//该选项只支持两个key;
//UIPageViewControllerOptionSpineLocationKey:指定翻页效果中“书脊”的位置
//UIPageViewControllerOptionInterPageSpacingKey:指定两个页面之间的间距
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:UIPageViewControllerSpineLocationMid],@"UIPageViewControllerSpineLocationKey",[NSNumber numberWithFloat:0],@"UIPageViewControllerOptionInterPageSpacingKey", nil];
//创建UIPageViewController
//1.设置页面过度效果:此处使用书页卷动的翻页效果
//2.设置页面的翻页方向:此处使用水平翻页
UIPageViewController* pageViewController = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:options];
//设置使用支持双面
pageViewController.doubleSided = NO;
//为UIPageViewController设置delegate
pageViewController.dataSource = self;
//设置UIPageViewController管理的视图控制器
//指向向前翻页
[pageViewController setViewControllers:@[pageZero] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
//设置程序窗口的跟视图控制器为pageViewController
self.window.rootViewController = pageViewController;
#pragma mark - UIPageViewControllerDataSource
- (FKPageController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(FKPageController *)viewController{
//如果当前pageIndex大于0,将pageIndex-1作为参数创建FKPageViewController
if (viewController.pageNumber > 0) {
NSUInteger index = viewController.pageNumber;
return [[FKPageController alloc]initWithPageNumber:index - 1];
}
return nil;
}
//当用户控制UIPageViewController向后翻页时调用该方法
- (FKPageController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(FKPageController *)viewController{
//将pageNumber+1作为参数创建FKPageController
NSUInteger index = viewController.pageNumber;
return [[FKPageController alloc]initWithPageNumber:index + 1];
}
FKPageController.h的声明部分
#import <UIKit/UIKit.h>
@interface FKPageController : UIViewController
@property (nonatomic, strong)UILabel* label;
@property (nonatomic, strong)UILabel* bookLabel;
@property (nonatomic, strong)UIImageView* bookImage;
@property (nonatomic ,assign)NSInteger pageNumber;
- (id)initWithPageNumber:(NSInteger)pageNumber;
@end
FKPageController.m的实现部分
@interface FKPageController (){
NSArray* contentList;
NSArray* coverList;
}
@end
@implementation FKPageController
- (id)initWithPageNumber:(NSInteger)pageNumber{
contentList = [NSArray arrayWithObjects:@"疯狂Android讲义",@"疯狂Ajax讲义",@"疯狂XML讲义",@"疯狂HTML5/CSS3/JavaScript讲义", nil];
coverList = [NSArray arrayWithObjects:@"1.png",@"2.png",@"3.png",@"4.png", nil];
self.pageNumber = pageNumber;
NSLog(@"pageNumber = %ld",pageNumber);
self = [super init];
if (self) {
//设置背景
self.view.backgroundColor = [UIColor grayColor];
//创建UILabel控件
self.label = [[UILabel alloc]initWithFrame:CGRectMake(220, 10, 100, 30)];
_label.backgroundColor = [UIColor clearColor];
_label.textColor = [UIColor redColor];
_label.text = [NSString stringWithFormat:@"第【%ld】页",pageNumber + 1];
[self.view addSubview:_label];
//创建UILabel控件
self.bookLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 30, CGRectGetWidth(self.view.frame), 60)];
_bookLabel.textAlignment = NSTextAlignmentCenter;
_bookLabel.numberOfLines = 2;
_bookLabel.font = [UIFont systemFontOfSize:24];
_bookLabel.backgroundColor = [UIColor clearColor];
_bookLabel.textColor = [UIColor blueColor];
_bookLabel.text = [contentList objectAtIndex:pageNumber%4];
[self.view addSubview:_bookLabel];
//创建UIImageView控件
self.bookImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 90, CGRectGetWidth(self.view.frame), 320)];
_bookImage.contentMode = UIViewContentModeScaleAspectFit;
_bookImage.image = [UIImage imageNamed:[coverList objectAtIndex:pageNumber%4]];
[self.view addSubview:_bookImage];
}
return self;
}
二十二、iPad应用开发
1、使用iPad专用控件:UISplitViewController
UISplitViewController是iPad的专用的视图控制器,当iPad处于横向模式时,UISplitViewController的左侧将会显示320点宽的侧栏,该侧栏通常用于显示页面的导航栏;而UISplitViewController的右侧通常显示导航栏对应的详情。
如果iPad切换为纵向模式,UISplitViewController的显示方式略有不同,原来位于左右的导航栏不在固定显示在左边,而是需要用户单击某个按钮来激活它,此时将会使用一个浮动窗口(popover)来显示导航栏。
UISplitViewController用于管理左右两个UIViewController。当iPad屏幕转为纵向,左侧导航栏隐藏时,以及iPad屏幕转为横向、左侧导航栏显示时,UISplitViewController会分别激发delegate的如下两个方法;
- (1)、- (void)splitViewController:(UISplitViewController )svc willHideViewController:(UIViewController )aViewController withBarButtonItem:(UIBarButtonItem )barButtonItem forPopoverController:(UIPopoverController )pc NS_DEPRECATED_IOS(2_0, 8_0, “Use splitViewController:willChangeToDisplayMode: and displayModeButtonItem instead”);当左侧导航栏将要隐藏时激发该方法;
- (2)、- (void)splitViewController:(UISplitViewController )svc willShowViewController:(UIViewController )aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem NS_DEPRECATED_IOS(2_0, 8_0, “Use splitViewController:willChangeToDisplayMode: and displayModeButtonItem instead”);当左侧导航栏将要显示时激发该方法;
2、使用UIPopoverController实现浮动窗口
待续