来源:http://blog.csdn.net/htttw/article/details/7891396
iPhone开发之UIScrollView初步
今天我们初步介绍以一下iPhone开发中的UIScrollView。顾名思义,UIScrollView就是可以滚动的视图,常常用在图片显示(缩放,滚动等),文本显示等,是一个非常有用的控件。今天我们的例子很简单:在顶部有一个文本框和一个按钮,在文本框中输入数字,点击按钮,就会在下方的UIScrollView中出现相应数目的按钮,超出一屏的部分用垂直滚动条显示。这个例子我们用两种方法实现。并且我们都不使用Interface Builder来画界面,完全手工写代码完成。下面开始吧:
方法1:
1.
新建一个View-based Application,名称是Scroll
2.
修改 ScrollViewController.h 如下:
- //
- // ScrollViewController.h
- // Scroll
- //
- // Created by HuTao on 8/21/12.
- // Copyright __MyCompanyName__ 2012. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- @interface ScrollViewController : UIViewController<UIScrollViewDelegate>
- {
- UITextField * textFieldNumber;
- UIButton * btnStart;
- UIScrollView * scrollView;
- NSMutableArray * btnArray;
- }
- @property (retain, nonatomic) UITextField * textFieldNumber;
- @property (retain, nonatomic) UIButton * btnStart;
- @property (retain, nonatomic) UIScrollView * scrollView;
- @property (retain, nonatomic) NSMutableArray * btnArray;;
- -(IBAction)btnStartAction:(id)sender;
- -(IBAction)btnAlert:(id)sender;
- @end
修改 ScrollViewController.m 如下:
- //
- // ScrollViewController.m
- // Scroll
- //
- // Created by HuTao on 8/21/12.
- // Copyright __MyCompanyName__ 2012. All rights reserved.
- //
- #import "ScrollViewController.h"
- @implementation ScrollViewController
- @synthesize textFieldNumber;
- @synthesize btnStart;
- @synthesize scrollView;
- @synthesize btnArray;
- // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.view.backgroundColor = [UIColor yellowColor];
- int widthOut = self.view.frame.size.width;
- int widthIn = widthOut - 20;
- btnArray = [[NSMutableArray alloc] init];
- //声明一个 UITextField
- textFieldNumber = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, widthIn - 70, 30)];
- textFieldNumber.backgroundColor = [UIColor whiteColor];
- textFieldNumber.borderStyle = UITextBorderStyleRoundedRect;
- [self.view addSubview:textFieldNumber];
- //声明一个 UIButton
- btnStart = [UIButton buttonWithType:UIButtonTypeRoundedRect];
- [btnStart setTitle:@"开始" forState:UIControlStateNormal];
- btnStart.frame = CGRectMake(widthIn - 50, 10, 60, 30);
- [btnStart addTarget:self action:@selector(btnStartAction:) forControlEvents:UIControlEventTouchUpInside];
- [self.view addSubview:btnStart];
- //声明一个 UIScrollView
- scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 50, widthOut, self.view.frame.size.height - 50)];
- scrollView.backgroundColor = [UIColor redColor];
- //任意划动
- scrollView.pagingEnabled = NO;
- //划动过程中显示水平滚动条(如果有)
- scrollView.showsHorizontalScrollIndicator = YES;
- //划动过程中显示垂直滚动条(如果有)
- scrollView.showsVerticalScrollIndicator = YES;
- //点击顶部的状态栏滚动到首
- scrollView.scrollsToTop = YES;
- scrollView.delegate = self;
- [self.view addSubview:scrollView];
- }
- -(IBAction)btnStartAction:(id)sender
- {
- [textFieldNumber resignFirstResponder];
- int i;
- UIButton * button;
- for(i=0; i<[btnArray count]; ++i)
- {
- button = (UIButton *)[btnArray objectAtIndex:i];
- //先删除所有按钮(删除后按钮自然不可见)
- [button removeFromSuperview];
- }
- [btnArray removeAllObjects];
- int number = [textFieldNumber.text intValue];
- for(i=0; i<number; ++i)
- {
- button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
- [button setTitle:[NSString stringWithFormat:@"%d", i] forState:UIControlStateNormal];
- button.frame = CGRectMake(10, 10 + i * 40, self.view.frame.size.width - 20, 30);
- [button addTarget:self action:@selector(btnAlert:) forControlEvents:UIControlEventTouchUpInside];
- [btnArray addObject:button];
- [scrollView addSubview:button];
- }
- //设置UIScrollView中要滚动的窗口大小(很重要)
- scrollView.contentSize = CGSizeMake(self.view.frame.size.width, number * 40 + 10);
- }
- -(IBAction)btnAlert:(id)sender
- {
- UIButton * btn = (UIButton *)sender;
- NSString * str = [NSString stringWithFormat:@"您按下了 %@ 键", btn.currentTitle];
- UIAlertView * alterview = [[UIAlertView alloc] initWithTitle:@"" message:str delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
- [alterview show];
- [alterview release];
- }
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidScroll");
- }
- - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewWillBeginDragging");
- }
- - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- {
- NSLog(@"scrollViewDidEndDragging");
- }
- - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewWillBeginDecelerating");
- }
- - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidEndDecelerating");
- }
- - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewShouldScrollToTop");
- return YES;
- }
- - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidScrollToTop");
- }
- - (void)viewDidUnload
- {
- textFieldNumber = nil;
- btnStart = nil;
- scrollView = nil;
- btnArray = nil;
- }
- - (void)dealloc
- {
- [super dealloc];
- [textFieldNumber release];
- [btnStart release];
- [scrollView release];
- [btnArray release];
- }
- @end
说明:
1.
在 Interface Builder 中,我们使用连线来关联控件与IBAction,用代码完成的话则是:
- addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
其中action是@selector(actionFunction:),一定不要忘记最后的冒号!
2.
要使用 UIScrollView,则必须实现 UIScrollViewDelegate,该Delegate定义如下:
- @protocol UIScrollViewDelegate<NSObject>
- @optional
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView; // any offset changes
- - (void)scrollViewDidZoom:(UIScrollView *)scrollView __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2); // any zoom scale changes
- - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; // called on start of dragging (may require some time and or distance to move)
- - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; // called on finger up if user dragged. decelerate is true if it will continue moving afterwards
- - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView; // called on finger up as we are moving
- - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; // called when scroll view grinds to a halt
- - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView; // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; // return a view that will be scaled. if delegate returns nil, nothing happens
- - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2); // called before the scroll view begins zooming its content
- - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale; // scale between minimum and maximum. called after any 'bounce' animations
- - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView; // return a yes if you want to scroll to the top. if not defined, assumes YES
- - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView; // called when scrolling animation finished. may be called immediately if already at top
- @end
有几个是比较重要的:
scrollViewDidScroll:scrollView只要在滚动就会触发该方法(无论是被用户拖动还是在拖动后scrollView由于惯性继续滚动一点距离)
scrollViewWillBeginDragging:scrollView被用户拖动前就会触发该方法
scrollViewDidEndDragging:scrollView被用户拖动结束后就会触发该方法
scrollViewWillBeginDecelerating:scrollView在拖动后继续滚动前就会触发该方法
scrollViewDidEndDecelerating:scrollView在拖动后继续滚动后停止就会触发该方法
scrollViewShouldScrollToTop:返回YES或NO,表示是否支持用户点击屏幕顶端的状态条后scrollView滚动到顶端(默认YES)
scrollViewDidScrollToTop:用户点击屏幕顶端的状态条后scrollView滚动到顶端后会触发该方法(scrollViewShouldScrollToTop如果返回NO,则该方法不会被触发)
UIScrollView的常用属性如下:
- scrollView.pagingEnabled = NO;
- //划动过程中显示水平滚动条(如果有)
- scrollView.showsHorizontalScrollIndicator = YES;
- //划动过程中显示垂直滚动条(如果有)
- scrollView.showsVerticalScrollIndicator = YES;
- //点击顶部的状态栏滚动到首
- scrollView.scrollsToTop = YES;
- scrollView.delegate = self;
- scrollView.contentSize = CGRect
pagingEnabled:是否以整数倍的UIScrollView大小滚动(如果是用于图片类的UIScrollView,该值应该设置为YES,如果是用于显示文本类的UIScrollView或者类似与本例的允许用户滚动到任意位置的情况时应该设置为NO)
contentOffset:UIScrollView中content的左上角坐标
contentSize:UIScrollView中content的大小,该值与UIScrollView的大小决定滚动条的长短
decelerating:UIScrollView在拖动放手后是否仍在由于惯性继续滚动中
dragging:UIScrollView是否正在被用户拖动
showsHorizontalScrollIndicator:是否显示水平滚动条
showsVerticalScrollIndicator:是否显示垂直滚动条
另外例子中还介绍了如何用代码(而不是Interface Builder)创建GUI控件,可以看看。
运行结果:
初始界面:
输入20,按开始键,生成了20个UIButton:
划动屏幕,出现滚动条:
点击任意一个按钮:
输入小一点的数字:
Console输出结果如下:
下面介绍方法2:
1.
和方法1类似,不过新建一个 Window-based Application,名称是Scroll2:
2.
新建一个基于UIView的子类,名称是ScrollView
3.
修改 Scroll2AppDelegate.m 如下:
- //
- // Scroll2AppDelegate.m
- // Scroll2
- //
- // Created by HuTao on 8/21/12.
- // Copyright __MyCompanyName__ 2012. All rights reserved.
- //
- #import "Scroll2AppDelegate.h"
- #import "ScrollView.h"
- @implementation Scroll2AppDelegate
- @synthesize window;
- #pragma mark -
- #pragma mark Application lifecycle
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- //注意这里的坐标,是除去了顶部的状态栏之后的剩余部分
- ScrollView * view = [[ScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
- [window addSubview:view];
- [window makeKeyAndVisible];
- return YES;
- }
- - (void)dealloc
- {
- [window release];
- [super dealloc];
- }
- @end
方法1我们用的是UIViewController,方法2我们直接用了UIView,都是可以的。
修改 ScrollView.h
如下:
- //
- // ScrollView.h
- // Scroll2
- //
- // Created by HuTao on 8/21/12.
- // Copyright 2012 __MyCompanyName__. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- @interface ScrollView : UIView<UIScrollViewDelegate>
- {
- UITextField * textFieldNumber;
- UIButton * btnStart;
- UIScrollView * scrollView;
- NSMutableArray * btnArray;
- }
- @property (retain, nonatomic) UITextField * textFieldNumber;
- @property (retain, nonatomic) UIButton * btnStart;
- @property (retain, nonatomic) UIScrollView * scrollView;
- @property (retain, nonatomic) NSMutableArray * btnArray;;
- -(IBAction)btnStartAction:(id)sender;
- -(IBAction)btnAlert:(id)sender;
- @end
方法2实现了UIScrollViewDelegate的是UIView,而不是方法1中的UIViewController,都是可以的
修改 ScrollView.m
如下:
- //
- // ScrollView.m
- // Scroll2
- //
- // Created by HuTao on 8/21/12.
- // Copyright 2012 __MyCompanyName__. All rights reserved.
- //
- #import "ScrollView.h"
- @implementation ScrollView
- @synthesize textFieldNumber;
- @synthesize btnStart;
- @synthesize scrollView;
- @synthesize btnArray;
- - (id)initWithFrame:(CGRect)frame
- {
- if ((self = [super initWithFrame:frame]))
- {
- self.backgroundColor = [UIColor yellowColor];
- int widthOut = self.frame.size.width;
- int widthIn = widthOut - 20;
- btnArray = [[NSMutableArray alloc] init];
- //声明一个 UITextField
- textFieldNumber = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, widthIn - 70, 30)];
- textFieldNumber.backgroundColor = [UIColor whiteColor];
- textFieldNumber.borderStyle = UITextBorderStyleRoundedRect;
- [self addSubview:textFieldNumber];
- //声明一个 UIButton
- btnStart = [UIButton buttonWithType:UIButtonTypeRoundedRect];
- [btnStart setTitle:@"开始" forState:UIControlStateNormal];
- btnStart.frame = CGRectMake(widthIn - 50, 10, 60, 30);
- [btnStart addTarget:self action:@selector(btnStartAction:) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:btnStart];
- //声明一个 UIScrollView
- scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 50, widthOut, self.frame.size.height - 50)];
- scrollView.backgroundColor = [UIColor redColor];
- //任意划动
- scrollView.pagingEnabled = NO;
- //划动过程中显示水平滚动条(如果有)
- scrollView.showsHorizontalScrollIndicator = YES;
- //划动过程中显示垂直滚动条(如果有)
- scrollView.showsVerticalScrollIndicator = YES;
- //点击顶部的状态栏滚动到首
- scrollView.scrollsToTop = YES;
- scrollView.delegate = self;
- [self addSubview:scrollView];
- }
- return self;
- }
- -(IBAction)btnStartAction:(id)sender
- {
- [textFieldNumber resignFirstResponder];
- int i;
- UIButton * button;
- for(i=0; i<[btnArray count]; ++i)
- {
- button = (UIButton *)[btnArray objectAtIndex:i];
- //先删除所有按钮(删除后按钮自然不可见)
- [button removeFromSuperview];
- }
- [btnArray removeAllObjects];
- int number = [textFieldNumber.text intValue];
- for(i=0; i<number; ++i)
- {
- button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
- [button setTitle:[NSString stringWithFormat:@"%d", i] forState:UIControlStateNormal];
- button.frame = CGRectMake(10, 10 + i * 40, self.frame.size.width - 20, 30);
- [button addTarget:self action:@selector(btnAlert:) forControlEvents:UIControlEventTouchUpInside];
- [btnArray addObject:button];
- [scrollView addSubview:button];
- }
- //设置UIScrollView中要滚动的窗口大小(很重要)
- scrollView.contentSize = CGSizeMake(self.frame.size.width, number * 40 + 10);
- }
- -(IBAction)btnAlert:(id)sender
- {
- UIButton * btn = (UIButton *)sender;
- NSString * str = [NSString stringWithFormat:@"您按下了 %@ 键", btn.currentTitle];
- UIAlertView * alterview = [[UIAlertView alloc] initWithTitle:@"" message:str delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
- [alterview show];
- [alterview release];
- }
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidScroll");
- }
- - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewWillBeginDragging");
- }
- - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- {
- NSLog(@"scrollViewDidEndDragging");
- }
- - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewWillBeginDecelerating");
- }
- - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidEndDecelerating");
- }
- - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewShouldScrollToTop");
- return YES;
- }
- - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
- {
- NSLog(@"scrollViewDidScrollToTop");
- }
- - (void)dealloc
- {
- [super dealloc];
- [textFieldNumber release];
- [btnStart release];
- [scrollView release];
- [btnArray release];
- }
- @end
我们将初始化代码放在了[UIView initWithFrame]中,注意到我们在Scroll2AppDelegate.m中调用了initWithFrame方法,传入了一个CGRect的窗口大小。总的来说,方法1中的self.view.xxx只要改成方法2中的self.xxx就可以了。由此可见iPhone开发的灵活性。对于一个界面,即可以使用UIViewController(内包含一个UIView,就像方法1),也可以直接使用UIView(方法2),很方便。
运行结果与方法1完全一样,故不在赘述。
最后我把两种方法的完整代码一起打包上传上来了:
http://download.csdn.net/detail/htttw/4516528
完成!