先从最基本的研究起,用一个例子来说明,如何创建一个UIScrollView。
在xcode新建一个基于视图的工程,然后打开项目里viewController的xib文件,在view里添加一个uiscrollview,然后安一定间距拖几个button、textfield之类的到scrollview
里,这样ui基本的框架就完成了。
下面就是代码部分了:
UIScrollViewDemoViewController.h
#import <UIKit/UIKit.h>
@interface UIScrollViewDemoViewController : UIViewController<UITextFieldDelegate,UIScrollViewDelegate> {
IBOutlet UIScrollView * myScrollView;
UITextField * activeField;
CGFloat oldContentOffsetValue;
IBOutlet UITextField * textFieldOne;
IBOutlet UITextField * textFieldTwo;
IBOutlet UITextField * textFieldThree;
IBOutlet UITextField * textFieldFour;
BOOL keyboardShown;
BOOL isNeedSetOffset;
}
@property (nonatomic,retain) UITextField * activeField;
@end
上面代码里,我xib文件创建了五个iboutlet变量,分别是四个textfield和一个scrollview,然后就可以到xib文件里,把它们和对应的ui相连接赶来。
其它的变量在实现文件里会用到。
UIScrollViewDemoViewController.m
#import "UIScrollViewDemoViewController.h"
@implementation UIScrollViewDemoViewController
@synthesize activeField;
- (void)dealloc
{
[myScrollView release];
[activeField release];
[textFieldOne release];
[textFieldTwo release];
[textFieldThree release];
[textFieldFour release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
textFieldOne.delegate = self;
textFieldTwo.delegate = self;
textFieldThree.delegate = self;
textFieldFour.delegate = self;
myScrollView.contentSize = CGSizeMake(myScrollView.frame.size.width, 1400.0f);
myScrollView.scrollEnabled = YES;
myScrollView.delegate = self;
keyboardShown = NO;
[self performSelector:@selector(registerForKeyboardNotifications)];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - UITextField Delegate
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
#pragma mark -Keyboard Helper Method
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSLog(@"-------");
if (keyboardShown)
return;
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Resize the scroll view (which is the root view of the window)
CGRect viewFrame = [myScrollView frame];
viewFrame.size.height -= keyboardSize.height;
myScrollView.frame = viewFrame;
// Scroll the active text field into view.
CGRect textFieldRect = [activeField frame];
[myScrollView scrollRectToVisible:textFieldRect animated:YES];
oldContentOffsetValue = [myScrollView contentOffset].y;
CGFloat value = (activeField.frame.origin.y+myScrollView.frame.origin.y+activeField.frame.size.height - self.view.frame.size.height + keyboardSize.height)+2.0f;
if (value > 0) {
[myScrollView setContentOffset:CGPointMake(0, value) animated:YES];
isNeedSetOffset = YES;
}
keyboardShown = YES;
}
// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Reset the height of the scroll view to its original value
CGRect viewFrame = [myScrollView frame];
viewFrame.size.height += keyboardSize.height;
myScrollView.frame = viewFrame;
if (isNeedSetOffset) {
[myScrollView setContentOffset:CGPointMake(0, oldContentOffsetValue) animated:YES];
}
isNeedSetOffset = NO;
keyboardShown = NO;
}
@end
代码有点长,一步步解析吧。
首先是viewDidLoad方法里进行一些初始化处理:
- (void)viewDidLoad
{
[super viewDidLoad];
textFieldOne.delegate = self;//设置textField的delegate,主要是为了显示和隐藏弹出的键盘用的
textFieldTwo.delegate = self;
textFieldThree.delegate = self;
textFieldFour.delegate = self;
//使用scrollView很关键的地方,设置contentSize,一般是安你的scrollView的size来设置,后面的height可以适当多个300~400
myScrollView.contentSize = CGSizeMake(myScrollView.frame.size.width, 1400.0f);
myScrollView.scrollEnabled = YES;//这个默认就是YES,这里多余了。
myScrollView.delegate = self;//设置scrollView的delegate,需要监听滚动事件的可以实现它的delegate方法
keyboardShown = NO;//一个状态标志,主要用来标识键盘的显隐状态
[self performSelector:@selector(registerForKeyboardNotifications)];//这个方法用来处理当textField被自己弹出的键盘挡住时,把它滚动到适当位置
}
接着就是相应的
registerForKeyboardNotifications方法,用来把textField滚动到适当的位置。
- (void)registerForKeyboardNotifications
{
//添加自己做为观察者,以获取键盘显示时的通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
//添加自己做为观察者,以获取键盘隐藏时的通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}
// 键盘出现时调用此方法
- (void)keyboardWasShown:(NSNotification*)aNotification
{
//如果键盘是显示状态,不用做重复的操作
if (keyboardShown)
return;
//获得键盘通知的用户信息字典
NSDictionary* info = [aNotification userInfo];
// 取得键盘尺寸.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// 重新设置scrollView的size
CGRect viewFrame = [myScrollView frame];
viewFrame.size.height -= keyboardSize.height;
myScrollView.frame = viewFrame;
// 把当前被挡住的text field滚动到view中适当的可见位置.
CGRect textFieldRect = [activeField frame];
[myScrollView scrollRectToVisible:textFieldRect animated:YES];
//记录当前textField的偏移量,方便隐藏键盘时,恢复textField到原来位置
oldContentOffsetValue = [myScrollView contentOffset].y;
//计算textField滚动到的适当位置
CGFloat value = (activeField.frame.origin.y+myScrollView.frame.origin.y+activeField.frame.size.height - self.view.frame.size.height + keyboardSize.height)+2.0f;
//value>0则表示需要滚动,小于0表示当前textField没有被挡住,不需要滚动
if (value > 0) {
//使textField滚动到适当位置
[myScrollView setContentOffset:CGPointMake(0, value) animated:YES];
isNeedSetOffset = YES;//更改状态标志为需要滚动
}
//更改键盘状态标志为已显示
keyboardShown = YES;
}
// 键盘隐藏时调用此方法
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Reset the height of the scroll view to its original value
CGRect viewFrame = [myScrollView frame];
viewFrame.size.height += keyboardSize.height;
myScrollView.frame = viewFrame;
//如果状态标志为需要滚动,则要执行textFiled复位操作
if (isNeedSetOffset) {
//oldContentOffsetValue记录了textField原来的位置,复位即可
[myScrollView setContentOffset:CGPointMake(0, oldContentOffsetValue) animated:YES];
}
//复位状态标志
isNeedSetOffset = NO;
keyboardShown = NO;
}
这样一个简单的scrollView就做好了,滚动被挡住的内容到适当位置也是很常用的功能。