从零开始学ios开发(十一):Tab Bars和Pickers

时间:2022-11-09 08:58:35

不好意思各位,本人休息了一个礼拜,所以这次的进度延后了,而且这次的学习的内容比较多,时间用的也比较长,文章发布的时间间隔有些长了,望各位谅解,下面继续我们的ios之旅。

这次我们主要学习的内容有2个,一个是Tab Bar,如下图 从零开始学ios开发(十一):Tab Bars和Pickers 很熟悉的界面(iphone中的phone),另一个Picker,如下图

从零开始学ios开发(十一):Tab Bars和Pickers

在正是开始学习项目之前,先首先简单介绍一下这次的例子的一个结构,当然一个root controller肯定是有的,用来控制其他subController的切换,在root controller中会放置一个tab bar,这个tab bar中有5个item,分别对应5个不同的view,每个view中有一个picker,所以在这个例子中,会有5个功能不同的picker,基本上涵盖了日常可能会用到的常规情况。OK,下面开始这次的学习。

1)创建一个工程,选择Empty Application,并命名为Pickers 这个过程和前一篇是一样的,在这里就不再叙述了。

2)添加需要的文件 之前我们说过,这个项目会有5个subcontrollers,因此我们需要添加5个view,选中Project navigator中的Pickers文件夹,单击鼠标右键,选择“New File...”,或者使用快捷键command+N,或者使用菜单栏File>New>New File... 从零开始学ios开发(十一):Tab Bars和Pickers 从零开始学ios开发(十一):Tab Bars和Pickers

在弹出的窗口中,左边选择Cocoa Touch,右边选择UIViewController subclass,点击Next按钮。

在下一个窗口中,填写类名BIDDatePickerViewController,并确认“With XIB for user interface” checkbox被选中(在前一篇的学习中,我们没有选中这个checkbox,而是在之后手动的连接controller和xib文件,在这里系统将帮我们连接这2个文件),点击Next 从零开始学ios开发(十一):Tab Bars和Pickers

选择保持的位置,保存在“Pickers”目录下,完成创建。创建完成后的Project navigator如下 从零开始学ios开发(十一):Tab Bars和Pickers 一共有3个文件被创建,分别是.h、.m和.xib。

使用相同的方法再创建其他4个subcontroller,分别命名为BIDSingleComponentPickerViewController、BIDDoubleComponentPickerViewController、BIDDependentComponentPickerViewController、BIDCustomPickerViewController。创建完成后的Project navigator如下: 从零开始学ios开发(十一):Tab Bars和Pickers 其中: BIDDatePickerViewController:包含一个Date Picker BIDSingleComponentPickerViewController:包含一个Picker View,并有一个滚轴1一个component) BIDDoubleComponentPickerViewController:包含一个Picker View,并有两个滚轴(2个component),且这2个滚轴是独立的 BIDDependentComponentPickerViewController:包含一个Picker View,并有两个滚轴(2个component),且这2个滚轴是联动的 BIDCustomPickerViewController:包含一个Picker View,并有五个滚轴(5个component),这5个滚轴中的内容是图片

(温馨提示:每一步做完后,你可以先build一下你的code,看看有没有错误,有的话可以及时修改,有一些警告应该是正常的,我们并没有完全完成项目的创建,但是不应该报错。)

3)添加Root View Controller(就是前面的提到的root controller) 添加root controller选择的模板和前面的有些不同,选中Project navigator中的Pickers文件夹,使用快捷键command+N创建一个新文件,在弹出的选中模板对话框中,左边选择User Interface,右边选择Empty模板,单击Next 从零开始学ios开发(十一):Tab Bars和Pickers Device Family保持默认的iPhone,点击Next,将新建的模板命名为TabBarController.xib,点击Create,创建完成。然后一个单独的TabBarController.xib文件会出现在Project navigator中。(Empty模板不会帮我们创建任何.h.m文件,我们会将TabBarController.xib关联到BIDAppDelegate,因此我们不需要和前面的文件一样创建.h.m文件,其次Empty模板不会帮我们创建一个默认的View,点击TabBarController.xib,你会发现xib的窗口中什么东西也没有,我们需要在之后自己添加)

打开BIDAppDelegate.h文件,添加以下内容

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h>

@interface BIDAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) IBOutlet UITabBarController *rootController; @end
从零开始学ios开发(十一):Tab Bars和Pickers

打开BIDAppDelegate.m文件,添加以下内容

从零开始学ios开发(十一):Tab Bars和Pickers
#import "BIDAppDelegate.h"

@implementation BIDAppDelegate

@synthesize window = _window;
@synthesize rootController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.

[[NSBundle mainBundle] loadNibNamed:@"TabBarController"
owner:self options:nil];
[self.window addSubview:rootController.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
} ...
从零开始学ios开发(十一):Tab Bars和Pickers

这些方法应该比较熟悉了,和之前几篇的例子很相似。

在此打开TabBarControll.xib,在Object library中找到Tab Bar Controller 从零开始学ios开发(十一):Tab Bars和Pickers 并拖动到xib窗口 从零开始学ios开发(十一):Tab Bars和Pickers

下面的一步是将TabBarControll.xib关联到BIDAppDelegate,选中TabBarControll.xib,然后选择File's Owner,打开identity inspector,Class中选择BIDAppDelegate 从零开始学ios开发(十一):Tab Bars和Pickers 接着打开connections inspector,在Outlets中会出现我们刚在定义在BIDAppDelegate.h中的rootController,鼠标放到rootController右边的圆圈上,圆圈中会出现加号,然后点击鼠标拖动到xib窗口中的Tab Bar Controller上,将2者关联起来,之后在rootController边上就会显示Tab Bar Controller了。 从零开始学ios开发(十一):Tab Bars和Pickers

4)添加Tab Bar Item 首先可以看一下Tab Bar Controller的结构 从零开始学ios开发(十一):Tab Bars和Pickers 一个Tab Bar Controller下面有一个Tab Bar,然后这个Tab Bar下有很多Item(每个Tab Bar Controller默认会有2个tab bar item),每个Item有一个View Controller,每个View Controller下又有一个Tab Bar Item,好了这个就是一个Tab Bar Controller的基本结构,因为我们需要5个tab bar item,下面就添加其他的3个。

在Object Library中找到Tab Bar Item 从零开始学ios开发(十一):Tab Bars和Pickers 然后拖动到Tab Bar上,一共拖3个,位置无所谓,添加完tab bar item的结构如下 从零开始学ios开发(十一):Tab Bars和Pickers 从零开始学ios开发(十一):Tab Bars和Pickers 这2者是一一对应的。

5个tab bar item分别对应5个view,因此我们需要制定2者的对应关系,选中最左边的一个tab bar item,打开attribute inspector,在NIB Name的下拉列表中选择BIDDatePickerViewController,然后打开identity inspcetor,在Class中选择BIDDatePickerViewController(在NIB Name中选择BIDDatePickerViewController是指定tab bar item对应的view是哪个,在Class中选中BIDDatePickerViewController是指定view的delegate是哪个类),对其他的4个tab bar item都执行上面的操作,分别对应各自的controller。从左到右的顺序为: BIDDatePickerViewController BIDSingleComponentPickerViewController BIDDoubleComponentPickerViewController BIDDependentComponentPickerViewController BIDCustomPickerViewController

5)为Tab Bar Item添加icon 下载TabBarIcons,并其解压后连同文件夹一同拖入到Project navigator中,在弹出的“Choose options for adding these files”框中保持默认选项即可,添加完后的Project navigator如下 从零开始学ios开发(十一):Tab Bars和Pickers 一般来说,app中图片基本上都是使用png格式,然后Tab Bar Item的图片大小为24px * 24px。(感觉xcode还是很只能的,它能够自己搜索所有的在项目中的图片文件,然后供用户进行选择,无论你图片放在那个文件夹下,xcode都可以找到)

图片拖动到项目中后,接下来就是为tab bar item添加图片了,首先选中最左边的一个Tab Bar Item,选中的方法是在视图中点击2次最左边的item图标,第一次我们选中的是view controller,第二次才是真正的tab bar item 从零开始学ios开发(十一):Tab Bars和Pickers 从零开始学ios开发(十一):Tab Bars和Pickers 第二次选中后,打开Attributes inspector,在Bar Item的Image中找到clockicon.png,这样icon就设好了,然后将Title命名为Date即可。从零开始学ios开发(十一):Tab Bars和Pickers

其他的四个item都是相同的操作,对应关系如下 BIDDatePickerViewController(clockicon.png,Title:Date) BIDSingleComponentPickerViewController(singleicon.png,Title:Single) BIDDoubleComponentPickerViewController(doubleicon.png,Title:Double) BIDDependentComponentPickerViewController(dependenticon.png,Title:Dependent) BIDCustomPickerViewController(toolicon.png,Title:Custom) 完成后的样子 从零开始学ios开发(十一):Tab Bars和Pickers

至此,我们对于root controller的所有设置都完成了,编译运行一下程序,看看效果,之后在进行每个subcontroller的实现。

6)Date Picker 第一个实现的是Date Picker,首先打开BIDDatePickerViewController.h,添加如下代码

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h>

@interface BIDDatePickerViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIDatePicker *datePicker;
- (IBAction)buttonPressed;
@end
从零开始学ios开发(十一):Tab Bars和Pickers

声明一个UIDatePicker的Outlet,用于等会和DatePicker控件连接,然后声明一个Action事件,我们会添加一个button,会触发该事件。

接着打开BIDDatePickerViewController.xib,然后在Graphical Layout Area(简称GLA)中选中View,再打开Attributes inspector,在Simulated Metrics中找到Bottom Bar,并选择“Tab Bar”,如下 从零开始学ios开发(十一):Tab Bars和Pickers 设置完成后,在GLA中会出现一条黑色区域,表示Tab Bar area,这样这个View的实际大小会把Tab Bar area给去掉,实际的高度变成411px 从零开始学ios开发(十一):Tab Bars和Pickers

在Object library中找到Date Picker 从零开始学ios开发(十一):Tab Bars和Pickers 并拖动到View的顶部,接着拖一个button放在DatePicker的下方,并命名为Select,完成后的效果如下 从零开始学ios开发(十一):Tab Bars和Pickers

我们还需要一个设置,设置DatePicker的最大日期和最小日期,选中View上的DatePicker,然后打开Attributs inspector,在Date Picker栏找到Constraints,将2个checkbox勾上 从零开始学ios开发(十一):Tab Bars和Pickers (其他的设置选项你自己也可以随便玩玩,看看DatePicker有什么变化)

7)连接Outlet和Action,写code 选中View上的button,打开connections inspector,在Sent Events中找到Touch Up Inside,将其连接到File's Owner下的buttonPressed action 选中File's Owner,control-drag到View中的DatePicker上,选择Outlet:datePicker 从零开始学ios开发(十一):Tab Bars和Pickers

好了,所有的连接都完成了,下面就可以写code了

打开BIDDatePickerViewController.m,添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
@implementation BIDDatePickerViewController
@synthesize datePicker; ...... - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSDate *now = [NSDate date];
[datePicker setDate:now animated:NO];

} - (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.datePicker = nil;
} ...... - (IBAction)buttonPressed
{
NSDate *selected = [datePicker date];
NSString *message = [[NSString alloc] initWithFormat:@"The date and time you selectd is: %@", selected];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Date and Time Selected"
message:message
delegate:self
cancelButtonTitle:@"Yes, I do"
otherButtonTitles:nil];
[alert show];
}
从零开始学ios开发(十一):Tab Bars和Pickers

这些code应该比较容易理解,在viewDidLoad中初始化datePicker显示的日期,在viewDidUnload中释放datePicker,在buttonPressed方法中,首先获取datePicker当前选中的时间对象NSDate,然后赋给一个string,最后alert显示出来,非常简单。

编译运行code 从零开始学ios开发(十一):Tab Bars和Pickers

点击Select按钮,一个alert框弹出

从零开始学ios开发(十一):Tab Bars和Pickers

一切正常唯有时间不对,iphone上方显示的是11:13 AM,但是alert中显示的时间是03:11:13 +0000,这是它显示的是格林尼治时间,和中国的时差有8个小时,要解决这个问题,改写buttonPressed如下

从零开始学ios开发(十一):Tab Bars和Pickers
- (IBAction)buttonPressed
{
NSDate *selected = [datePicker date]; NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSInteger interval = [zone secondsFromGMTForDate: selected];
NSDate *localeDate = [selected dateByAddingTimeInterval: interval];
NSString *message = [[NSString alloc] initWithFormat:@"The date and time you selectd is: %@", loaclDate];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Date and Time Selected"
message:message
delegate:self
cancelButtonTitle:@"Yes, I do"
otherButtonTitles:nil];
[alert show];
}
从零开始学ios开发(十一):Tab Bars和Pickers

NSTimeZone *zone = [NSTimeZonesystemTimeZone]; // 获得当前设备的时区,即iphone的时区

NSInteger interval = [zone secondsFromGMTForDate: selected]; // 算出当前时区和GMT的时差是多少

NSDate *localeDate = [selected  dateByAddingTimeInterval: interval]; // 在GMT的基础上加上加上相应的时差

好了,在此编译运行,点击button后,显示的时间和iphone上的一致了 从零开始学ios开发(十一):Tab Bars和Pickers

8)Single-Component Picker DatePicker是一个特殊的picker,专门用于对日期进行选择,但是在很多时候,我们需要选择的内容都是需要我们自己制定的,在这个例子中,我们就将制定自己内容。 在这里例子中,我们会添加一个Picker View 从零开始学ios开发(十一):Tab Bars和Pickers 在Picker中,每一个滚轴就是一个component,我们将使用delegate来定义Picker View中component的数量和数据的来源。

9)创建Outlet和Action 打开BIDSingleComponentPickerViewController.h,添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h>

@interface BIDSingleComponentPickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>

@property (strong, nonatomic) IBOutlet UIPickerView *singlePicker;
@property (strong, nonatomic) NSArray *pickerData;
- (IBAction)buttonPressed; @end
从零开始学ios开发(十一):Tab Bars和Pickers

首先添加了2个protocols,这2个protocols是必须的,PickerView的delegate和datasource都是源于它,然后声明了一个指向PickerView的对象,再声明一个保存PickerView数据的数列,最后声明了一个action,代码很简单。

10)添加Picker View,绑定Outlet和Action 选中BIDSingleComponentPickerViewController.xib,空出底部的Tab bar位置(Attributes inspector>Simulated Metrics>Bottom Bar>Tab Bar。在Object library中,找到Picker View,拖动到View的顶部,在拖一个button放在Picker View的下面,命名为Select,所有控件添加完毕 从零开始学ios开发(十一):Tab Bars和Pickers

选中File's Owner,control-drag到Picker View上,选中singlePicker。 选中Picker View,打开connections inspector,拖动dataSource和delegate边上的圆圈到File's Owner上进行绑定,这样就告诉这个Picker View,它的dataSource和delegate都是BIDSingleComponentPickerViewController类 从零开始学ios开发(十一):Tab Bars和Pickers 绑定Select按钮的Touch Up Inside的action为buttonPressed(方法和之前的一个例子一样)

ok,至此所有的控件和连接操作都已经完成,下面开始code部分。

11)写code 打开BIDSingleComponentPickerViewController.m,添加如下代码

从零开始学ios开发(十一):Tab Bars和Pickers
#import "BIDSingleComponentPickerViewController.h"

@implementation BIDSingleComponentPickerViewController
@synthesize singlePicker;
@synthesize
pickerData; ...... - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSArray *array = [[NSArray alloc] initWithObjects:@"Luke", @"Leia",
@"Han", @"Chewbacca", @"Artoo", @"Threepio", @"Lando", nil];
self.pickerData =
array;
} - (void)viewDidUnload
{
[self setSinglePicker:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.singlePicker = nil;
self.pickerData =
nil;
} ...... - (IBAction)buttonPressed
{
NSInteger row = [singlePicker selectedRowInComponent:0];
NSString *selected = [pickerData objectAtIndex:row];
NSString *title = [[NSString alloc] initWithFormat:@"You selected %@!", selected];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:@"Thank you for choosing."
delegate:nil
cancelButtonTitle:@"You're Welcome"
otherButtonTitles:nil];
[alert show];
}
从零开始学ios开发(十一):Tab Bars和Pickers

一些必要的解释,在viewDidLoad中,声明一个数组,存放在PickerView的componnent中显示的数据。 buttonPressed方法中: NSInteger row = [singlePicker selectedRowInComponent:0]; // selectedRowInComponent方法返回当前component滚到哪一行,后面的0表示最左边的一个component NSString *selected = [pickerData objectAtIndex:row]; // objectAtIndex:row返回component中当前行的对象,这个例子中是NSString

其他的代码都比较简单,下面继续添加code,这次添加dataSource和delegate需要使用到的方法,这也是每个Picker View(不包括Date Picker)都需要实现的方法

从零开始学ios开发(十一):Tab Bars和Pickers
#pragma mark -
#pragma mark Picker Data Source Methods - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
} - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [pickerData count];
} #pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [pickerData objectAtIndex:row];
}
从零开始学ios开发(十一):Tab Bars和Pickers

numberOfComponentsInPickerView告诉picker一共有几个component(滚轴),我们这个例子是SingleComponent,只有一个滚轴,因此返回1。这个方法有一个参数是传一个pickerview进来,如果一个view中有2个或2个以上的Picker View,就需要使用这个参数,告诉系统到底是在设置哪个Picker View的component的数量,如果只有1个Picker View就可以忽略该参数,我们这个例子就忽略了这个参数。

pickerView方法是返回dataSource的数量,告诉pick你有多少个数据需要显示。参数pickerView指明是哪个picker在调用,只有一个的话可以忽略该参数,参数component是picker中的第几个滚轴,如果只有一个滚轴,也可以忽略该参数。

以上是的2个方法都是属于dataSource,最后的一个方法是属于delegate的,Picker View的dataSource方法是必须实现的,而delegate方法是可选的,但必须要实现其中的一个,在这个例子中我们实现的是pickerView方法 pickerView方法在指定的picker和component中返回第row行数据,这个例子中的数据都来自NSArray,就返回array中的第row个数据即可。在这个方法中,只用到了参数row,其他2个参数不需要,因为我们只有1个pickerview和1个component。

至此,所有的Single component的所有code都写完了,编译运行,选择Tab Bar上的第二个item 从零开始学ios开发(十一):Tab Bars和Pickers 单击Select按钮,警告框弹出,显示哪一行的内容被选中了 从零开始学ios开发(十一):Tab Bars和Pickers

13)Multicomponent Picker 在这个例子中,将会有2个component,它们各自独立(没有关联),实现起来也很简单,只要准备2个NSArray,在返回component的数量的方法中返回2就可以了,下面进行具体的实现。

14)创建Outlet和Action 打开BIDDoubleComponentPickerViewController.h,添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h>

#define kfillingComponent 0
#define kBreadComponent 1
@interface BIDDoubleComponentPickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> @property (strong, nonatomic) IBOutlet UIPickerView *doublePicker;
@property (strong, nonatomic) NSArray *fillingTypes;
@property (strong, nonatomic) NSArray *breadTypes; - (IBAction)buttonPressed;
@end
从零开始学ios开发(十一):Tab Bars和Pickers

上面的code应该很容易理解,定义了2个宏变量来区分左右2个component,这是一个很好的习惯,而且使代码更易读,然后添加了2个protocols,声明了一个指向PickerView的outlet,声明2个数组,分别保存左右2个component的数据,最后定义一个action,很简单。

15)添加Picker View,绑定Outlet和Action 打开BIDDoubleComponentPickerViewController.xib,设置view的Bottom Bar为Tab Bar,拖一个Picker View放到view的顶部,拖一个按钮放到Picker View的下面,并命名为Select,完成后的界面 从零开始学ios开发(十一):Tab Bars和Pickers

选中File's Owner,control-drag到Picker View上,选中doublePicker。 选中Picker View,打开connections inspector,拖动dataSource和delegate边上的圆圈到File's Owner上进行绑定,这样就告诉这个Picker View,它的dataSource和delegate都是BIDDoubleComponentPickerViewController类 绑定Select按钮的Touch Up Inside的action为buttonPressed

16)写code 打开BIDDoubleComponentPickerViewController.m文件,添加如下代码

从零开始学ios开发(十一):Tab Bars和Pickers
@implementation BIDDoubleComponentPickerViewController
@synthesize doublePicker;
@synthesize fillingTypes;
@synthesize breadTypes;
- (IBAction)buttonPressed
{
NSInteger fillingRow = [doublePicker selectedRowInComponent:kfillingComponent];
NSInteger breadRow = [doublePicker selectedRowInComponent:kBreadComponent]; NSString *filling = [fillingTypes objectAtIndex:fillingRow];
NSString *bread = [breadTypes objectAtIndex:breadRow]; NSString *message = [[NSString alloc] initWithFormat:@"Your %@ on %@ bread will be right up.", filling,bread]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Thank you for your order"
message:message
delegate:nil
cancelButtonTitle:@"Great!"

otherButtonTitles:nil];
[alert show];
}
...... - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSArray *fillingArray = [[NSArray alloc] initWithObjects:@"Ham",
@"Turkey", @"Peanut Butter", @"Tuna Salad",
@"Nutella", @"Roast Beef", @"Vegemite", nil];
self.fillingTypes = fillingArray; NSArray *breadArray = [[NSArray alloc] initWithObjects:@"White",
@"Whole Wheat", @"Rye", @"Sourdough", @"Seven Grain",nil];
self.breadTypes =
breadArray; } - (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.doublePicker = nil;
self.fillingTypes = nil;
self.breadTypes =
nil;
} ...... #pragma mark -
#pragma mark Picker Data Source Methods - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
} - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if(component == kBreadComponent)
return [self.breadTypes count]; return [self.fillingTypes count];
} #pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component == kBreadComponent)
return [self.breadTypes objectAtIndex:row]; return [self.fillingTypes objectAtIndex:row];
}
从零开始学ios开发(十一):Tab Bars和Pickers

上面的code和在singlepicker中的基本一样,由于有2个component,因此在viewDidLoad中创建了2个数组,在numberOfComponentsInPickerView中返回2,这样PickerView就会创建2个component(滚轴),在DataSource的pickerView方法中,根据component来返回数组,在delegate的pickerView中根据component返回数据。很简单,然后编译运行程序,载入app后,选择Tab Bar上的第三个tab item,出现如下界面 从零开始学ios开发(十一):Tab Bars和Pickers

随便滚动2个component,他们是独立的,不会相互影响 从零开始学ios开发(十一):Tab Bars和Pickers

点击Select按钮,一个警告框弹出,告知你选择了哪些数据 从零开始学ios开发(十一):Tab Bars和Pickers

17)Dependnet Components 前面的2个例子分别实现了1个componet和2个component,在这个例子中,也将实现2个component,但是这2个componet是联动的,当左边的component存放美国的各个洲(state),右边的component存放每个洲的邮政编码(zip),当左边的洲发生时,右边的邮政编码也会随之变化。另外在之前的例子中,显示在component中的数据都是写在code中的,这个不利于数据的更新,且如果数据量巨大,我们也不可能都写在code里面,在这个例子中,数据将存入一个property list(plist)文件,component的数据将从该文件中获取。

打开BIDDependentComponentPickerViewController.h文件,添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h> #define kStateComponent 0 #define kZipComponent 1

@interface BIDDependentComponentPickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>

@property (strong, nonatomic) IBOutlet UIPickerView *picker;
@property (strong, nonatomic) NSDictionary *stateZips;
@property (strong, nonatomic) NSArray *states;
@property (strong, nonatomic) NSArray *zips; - (IBAction)buttonPressed;
@end
从零开始学ios开发(十一):Tab Bars和Pickers

唯一不同的是,多了一个NSDictionary对象,这个对象是用来存放关联数据的,存放之前提到的plist。

和前面2个例子一样,拖动一个Picker View和button到View上,并连接Outlet和Action 从零开始学ios开发(十一):Tab Bars和Pickers

18)NSDictionary:statedictionary.plist 下载statedictionary.plist压缩包,并解压出里面的文件statedictionary.plist,将statedictionary.plist拖入到Project navigator中,放到Pickers目录下,点击statedictionary.plist文件,你会发现有茫茫多的数据 从零开始学ios开发(十一):Tab Bars和Pickers

其实statedictionary.plist是一个xml文件,理解有序的将这些数据组织起来,供程序使用 从零开始学ios开发(十一):Tab Bars和Pickers

19)写code 由于这次的code稍微有些不同,主要是在读取plist上面,因此我们分开写,打开BIDDependentComponentPickerViewController.m文件,首先添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
#import "BIDDependentComponentPickerViewController.h"

@implementation BIDDependentComponentPickerViewController
@synthesize picker;
@synthesize stateZips;
@synthesize states;
@synthesize zips;
- (IBAction)buttonPressed
{
NSInteger stateRow = [picker selectedRowInComponent:kStateComponent];
NSInteger zipRow = [picker selectedRowInComponent:kZipComponent]; NSString *state = [states objectAtIndex:stateRow];
NSString *zip = [zips objectAtIndex:zipRow]; NSString *title = [[NSString alloc] initWithFormat:@"You select zip code %@.", zip]; NSString *message = [[NSString alloc] initWithFormat:@"%@ is in %@", zip, state]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
从零开始学ios开发(十一):Tab Bars和Pickers

上面的code应该不需要过多的解释了吧,很简单,应该都可以看懂,接着添加viewDidLoad

从零开始学ios开发(十一):Tab Bars和Pickers
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSBundle *boundle = [NSBundle mainBundle];
NSURL *plistURL = [boundle URLForResource:@"statedictionary" withExtension:@"plist"]; NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL]; self.stateZips = dictionary; NSArray *components = [self.stateZips allKeys];
NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
self.states = sorted;
NSString *selectedState = [self.states objectAtIndex:0];
NSArray *array = [stateZips objectForKey:selectedState];
self.zips =
array;
}
从零开始学ios开发(十一):Tab Bars和Pickers

这里面的变化比较大,首先声明了一个NSBundle对象,这个对象在前几篇的例子中已经出现过(load一个xib),这里做一个比较详细的解释:bundle是一个特殊的文件夹,其中包含了程序会使用到的资源,这些资源包含了如图像、声音、编译好的代码、xib文件。对应bundle,cocoa提供了类NSBundle。

下面逐个对语句进行解释 NSBundle *bundle = [NSBundle mainBundle]; //这里的作用就是获取应用程序的主目录,然后在主目录中寻找需要的资源

NSURL *plistURL = [boundle URLForResource:@"statedictionary" withExtension:@"plist"]; //通过主目录来获取资源的路径(URL),这里寻找的资源是statedictionary.plist,有了资源的路径,就可以找到该资源

NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL]; //NSDictionary就是通过资源的路径来获取资源,并读取里面的数据

self.stateZips = dictionary; //将dictionary赋stateZips

NSArray *components = [self.stateZips allKeys]; //获取statedictionary.plist中所有的<key>

NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)]; //将获取的所有<key>按字母序进行排列(这里我只知道是排序的意思,后面的方法我还没有深究,先这样子用着)

self.states = sorted; //将排完序的数组赋给states(左边的component)

NSString *selectedState = [self.states objectAtIndex:0]; // 当启动程序的时候,左边的component默认是选择第一个值的,这里获得第一个值,然后根据这个值找到对应的zips,然后显示在右边的component中

NSArray *array = [stateZips objectForKey:selectedState]; // 根据<key>来获得对应的zips

self.zips = array; //然后将数组赋给zips

继续写code

从零开始学ios开发(十一):Tab Bars和Pickers
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.picker = nil;
self.stateZips = nil;
self.states = nil;
self.zips =
nil;
}
从零开始学ios开发(十一):Tab Bars和Pickers

不多解释了

从零开始学ios开发(十一):Tab Bars和Pickers
#pragma mark -
#pragma mark Picker Data Source Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
} - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if(component == kStateComponent)
return [self.states count]; return [self.zips count];
}
从零开始学ios开发(十一):Tab Bars和Pickers

Picker的DataSource方法,第一个方法返回2,说明有2个component,第二个方法返回component中数据的个数,这里以component做为区分,如果是kStateComponent,返回左边component数据的格式,否则返回右边component数据的个数。

从零开始学ios开发(十一):Tab Bars和Pickers
#pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component == kStateComponent)
return [self.states objectAtIndex:row];
return [self.zips objectAtIndex:row];
} - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(component == kStateComponent)
{
NSString *selectedState = [self.states objectAtIndex:row];
NSArray *array = [stateZips objectForKey:selectedState];
self.zips = array;
[picker selectRow:0 inComponent:kZipComponent animated:YES];
[picker reloadComponent:kZipComponent];
}
}
从零开始学ios开发(十一):Tab Bars和Pickers

Picker的delegate方法,第一个方法还是和以前一样的,第二个方法是重点,用来更新右边component的数据,更新的方法和viewDidLoad中的方法是一样的,首先判断是不是左边的component发生了变化,如果是,得到左边component的当前值,根据这个值获取相应的zips,然后将zips赋值给右边的component,接着选中右边component的第一个值,并以动画的形式选中,滚动到第一个值,最后重新载入右边的component。

好了,以编译运行程序了,程序运行后,选择第四个tabitem 从零开始学ios开发(十一):Tab Bars和Pickers

试着改变左边component的选项,右边的zips会跟着改变 从零开始学ios开发(十一):Tab Bars和Pickers

程序似乎是做完了,但是并不完美,稍微往下滚动左边的component,会发现一些state的名字太长,没有完全显示出来,但是又发现右边的component有很多空白的地方被浪费了,因此最后能够拉长左边的component,缩短右边的component,方法很简单,在BIDDependentComponentPickerViewController.m中添加下面的方法 从零开始学ios开发(十一):Tab Bars和Pickers

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
if(component == kZipComponent)
return 90;
return 200;
}

该方法也是一个delegate,它用来设置pickerview中各个component的宽度,再次编译运行程序,这次程序界面完美了 从零开始学ios开发(十一):Tab Bars和Pickers

点击button,一个警告框弹出,告知你选择的内容 从零开始学ios开发(十一):Tab Bars和Pickers

20)Custom Picker Picker View中component所包含的对象不仅仅是string,也可以是其他,比如图片,在这个例子中,我们将做一个简单的游戏,类似于赌博机中的摇连续的“777”,一共会有5个component,每个component中包含5张不同的图片,然后根据随机数进行滚动,如果恰巧有连续3个component选中的图片一样,则获得胜利。

打开BIDCustomPickerViewController.h文件,添加如下code

从零开始学ios开发(十一):Tab Bars和Pickers
#import <UIKit/UIKit.h>

@interface BIDCustomPickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>

@property (strong, nonatomic) IBOutlet UIPickerView *picker;
@property (strong, nonatomic) IBOutlet UILabel *winLabel;
@property (strong, nonatomic) NSArray *column1;
@property (strong, nonatomic) NSArray *column2;
@property (strong, nonatomic) NSArray *column3;
@property (strong, nonatomic) NSArray *column4;
@property (strong, nonatomic) NSArray *column5;
- (IBAction)spin; @end
从零开始学ios开发(十一):Tab Bars和Pickers

这里多声明了一个UILabel的outlet,当我们赢得一局后,label会显示“WIN”,否则label不显示,因此我们需要一个outlet来指向label。然后声明了5个NSArray,因为有5个component,所以需要5个NSArray与之对应。

打开BIDCustomPickerViewController.xib,拖一个Picker View放在view的顶部,选中Picker View,在Attributes inspector中找到Interaction,将User Interaction Enabled前的勾去掉,这样就不能用手指去滚动component了。 从零开始学ios开发(十一):Tab Bars和Pickers

然后拖一个Label放在Picker View下面,将Label的边框拉长到左右两边出现辅助线的位置,并在Attributes inspector中将Label的字体大小设置为48,颜色设为你喜欢的颜色即可,Label文字居中,在选中Label的状态下,使用快捷键command + =使Label边框的大小根据Label字体的大小进行改动。再拖一个button放在Label下面,并命名为Spin。 从零开始学ios开发(十一):Tab Bars和Pickers

接着就是连接outlet和action了,PickerView连接到picker outlet,Label连接到winLabel outlet,button连接到spin action,PickerView的dataSource和delegate连接到File's Owner。这些应该都很简单了,和之前的一样。

21)添加图片资源,继续写code 首先下载图片资源:CustomPickerImages,解压缩后拖入当Project navigator的Pickers目录下 从零开始学ios开发(十一):Tab Bars和Pickers 里面一共有6张png图片

打开BIDCustomPickerViewController.m文件,添加如下代码

从零开始学ios开发(十一):Tab Bars和Pickers
#import "BIDCustomPickerViewController.h"

@implementation BIDCustomPickerViewController
@synthesize picker;
@synthesize winLabel;
@synthesize column1;
@synthesize column2;
@synthesize column3;
@synthesize column4;
@synthesize column5;
- (IBAction)spin
{
BOOL win = NO;
int numInRow = 1;
int lastVal = -1;
for (int i = 0; i < 5; i++) {
int newValue = random() % [self.column1 count]; if(newValue == lastVal)
numInRow++;
else
numInRow = 1; lastVal = newValue;
[picker selectRow:newValue inComponent:i animated:YES];
[picker reloadComponent:i];
if (numInRow >= 3) {
win = YES;
}
} if (win)
winLabel.text = @"WIN";
else
winLabel.text = @"";
}
从零开始学ios开发(十一):Tab Bars和Pickers

就解释一下spin方法中的for循环中

for (int i = 0; i < 5; i++) {

int newValue = random() % [self.column1 count]; //通过产生随机数,来确定component滚动到哪个位置,要对产生的随机数进行取余操作,否则很容易就超出component对象的个数,导致内存溢出报错。这里的余数表示component滚动到第几个位置

if(newValue == lastVal) //相等时,说明随机数的余数和前一次的余数相等

numInRow++; //计数器加1

else

numInRow = 1; //计数器重新置1,从新开始计数,最开始的时候计数器赋的值是-1,它不可能和任何余数相等,第一个component也不可能和任何其他的component进行对比,因此第一次执行for循环总是会跳到这里

lastVal = newValue; //记录最近一次的余数,用于下次比较

[picker selectRow:newValue inComponent:i animated:YES]; //设置picker中当前的component滚动到哪个位置

[picker reloadComponent:i]; //重新载入当前的component

if (numInRow >= 3) { //如果numInRow的值大于等于3,说明有连续3个相同的图标出现了

win = YES; //连续出现3个相同的图标,赢得本局

}

}

继续添加viewDidLoad和viewDidUnload

从零开始学ios开发(十一):Tab Bars和Pickers
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

winLabel.text = @""; UIImage *seven = [UIImage imageNamed:@"seven.png"];
UIImage *bar = [UIImage imageNamed:@"bar.png"];
UIImage *crown = [UIImage imageNamed:@"crown.png"];
UIImage *cherry = [UIImage imageNamed:@"cherry.png"];
UIImage *lemon = [UIImage imageNamed:@"lemon.png"];
UIImage *apple = [UIImage imageNamed:@"apple.png"]; for (int i = 1; i <= 5; i++) {
UIImageView *sevenView = [[UIImageView alloc] initWithImage:seven];
UIImageView *barView = [[UIImageView alloc] initWithImage:bar];
UIImageView *crownView = [[UIImageView alloc] initWithImage:crown];
UIImageView *cherryView = [[UIImageView alloc] initWithImage:cherry];
UIImageView *lemonView = [[UIImageView alloc] initWithImage:lemon];
UIImageView *appleView = [[UIImageView alloc] initWithImage:apple]; NSArray *imageViewArray = [[NSArray alloc] initWithObjects:sevenView, barView, crownView, cherryView, lemonView, appleView, nil]; NSString *fieldName = [[NSString alloc] initWithFormat:@"column%d"
, i];
[self setValue:imageViewArray forKey:fieldName];
} srandom(time(NULL));
} - (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.picker = nil;
self.winLabel = nil;
self.column1 = nil;
self.column2 = nil;
self.column3 = nil;
self.column4 = nil;
self.column5 =
nil;
}
从零开始学ios开发(十一):Tab Bars和Pickers

就解释一下viewDidLoad中某些语句(viewDidUnload很简单,就不做说明了):

UIImage *seven = [UIImage imageNamed:@"seven.png"]; //imageNamed方法是根据图片的名称去寻找图片并载入

UIImageView *sevenView = [[UIImageView alloc] initWithImage:seven]; //在for循环中根据UIImage对象创建6个UIImageView

NSArray *imageViewArray = [[NSArray alloc] initWithObjects:sevenView, barView, crownView, cherryView, lemonView, appleView, nil]; //创建一个Array,大家应该可以猜到,这个数组会赋给component,NSArray保存的对象是object,因此不论是string还是UIImageView,都可以保持在里面

NSString *fieldName = [[NSString alloc] initWithFormat:@"column%d", i]; //之前声明了5个NSArray,它们的名字都是有规律的column*

[self setValue:imageViewArray forKey:fieldName]; //setValue:forKey:是根据属性(property)的名字来为其赋值,我们使用这个方法,来为5个column*赋值

srandom(time(NULL)); //设置随机数的因子,可以是每次产生的随机数不同

最后添加dataSource和delegate方法

从零开始学ios开发(十一):Tab Bars和Pickers
#pragma mark -
#pragma mark Picker Data Source Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 5;
} - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [self.column1 count];
} #pragma mark Picker Delegate Methods
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
NSString *arrayName = [[NSString alloc] initWithFormat:@"column%d", component + 1];
NSArray *array = [self valueForKey:arrayName];
return [array objectAtIndex:row];
}
从零开始学ios开发(十一):Tab Bars和Pickers

DataSource方法和之前的并无两样,就不解释了,而delegate方法则稍稍有些不同,之前返回的董事NSString,这里返回的UIView,因为component中的对象是UIImageView

NSString *arrayName = [[NSString alloc] initWithFormat:@"column%d", component + 1]; //参数component传过来的值是0~4,所以必须要加1,才能对应到column1~column5

NSArray *array = [self valueForKey:arrayName]; //valueForKey根据property的名字得到对象

return [array objectAtIndex:row]; //根据得到的array返回第row个对象

22)编译运行 选择第五个tabitem,程序的初始界面 从零开始学ios开发(十一):Tab Bars和Pickers

点击多次Spin后,终于获胜 从零开始学ios开发(十一):Tab Bars和Pickers

23)总结 这篇文章主要讲解了TabBar和PickerView的使用,TabBar作为root controller,控制了5个subview的切换,PickerView有2种,一种是DatePicker,另一种是PickerView,DatePicker专门处理日期,比较简单。PickerView相对复杂一些,需要引入<UIPickerViewDelegate, UIPickerViewDataSource>,并使用其中的方法告知PickerView中有多少个component和每个component中有多少个对象,还要绑定NSArray,并自己写返回对象的方法。

24)一个小问题 如果你和我使用的是同一个版本的xcode 从零开始学ios开发(十一):Tab Bars和Pickers

那在编译项目的时候,始终会有一个感叹号存在 从零开始学ios开发(十一):Tab Bars和Pickers

TabBarController.xib: warning: Attribute Unavailable: Defines Presentation Context is not available prior to Xcode 4.2.

我也不太清楚是什么意思,但是查了一下网,选中TabBarController.xib,在Attributes inspector中,把Defines Context前的勾去掉就可以,然后编译就没有感叹号了。 从零开始学ios开发(十一):Tab Bars和Pickers

Pickers

从零开始学ios开发(十一):Tab Bars和Pickers的更多相关文章

  1. 从零开始学 iOS 开发的15条建议

    事情困难是事实,再困难的事还是要每天努力去做是更大的事实. 因为我是一路自学过来的,并且公认没什么天赋的前提下,进步得不算太慢,所以有很多打算从零开始的朋友会问我,该怎么学iOS开发.跟粉丝群的朋友交 ...

  2. 从零开始学IOS开发

    从今天开始开一个坑,由于业务变动,要开始学习IOS开发进行IOS app开发,其实鄙人本身就是一只菜鸟加大学狗,有过两年的C#,ASP.NET MVC,微信公众平台开发经验,一只在继续努力着,从大三下 ...

  3. 从零开始学ios开发(三):第一个有交互的app

    感谢大家的关注,也给我一份动力,让我继续前进.有了自己的家庭有了孩子,过着上有老下有小的生活,能够挤出点时间学习真的很难,每天弄好孩子睡觉已经是晚上10点左右了,然后再弄自己的事情,一转眼很快就到12 ...

  4. 从零开始学ios开发(一):准备起航

    首先介绍一下自己的背景,本人09年研究生毕业,大学就不介绍了,反正是上海的一所211大学,学的是计算机科学与技术专业,学生时代,从事过ACM,没有什么太大的成就,中国的牛人是在太多,我的水平,估计连高 ...

  5. 从零开始学ios开发(八):Autorotation and Autosizing

    不好意思,这一篇间隔的时间有点长,最近实在是事情太多,耽搁了,好了,长话短说,下面继续学习ios. 这次学习的内容是Autorotation和Autosizing,Autorotation就是屏幕内容 ...

  6. 从零开始学ios开发(十九):Application Settings and User Defaults(上)

    在iphone和ipad中,有一个东西大家一定很熟悉,那个东西就是Settings. 这次要学习的东西说白了很简单,就是学习如何在Settings中对一个app的某些属性进行设置,反过来,在app中更 ...

  7. 从零开始学ios开发(四):IOS控件(1),Image View、Text Field、Keyboard

    长话短说,谢谢大家的关注,这篇写了好长时间,下面继续学习ios.我将用2到3篇的篇幅来学习iphone上的一些常用控件,包括Image View.Text Field.Keyboard.Slider等 ...

  8. 从零开始学ios开发(十二):Table Views(上)

    这次学习的控件非常重要且非常强大,是ios应用中使用率非常高的一个控件,可以说几乎每个app都会使用到它,它就是功能异常强大的Table Views.可以打开你的iphone中的phone.Messa ...

  9. 从零开始学ios开发(十):Multiview Applications(多个xib之前的切换)

    这篇学习的主要内容是Multiview,在我们学习iphone旋转的时候,介绍过多个view的使用方法,不过这里的view和旋转屏幕中所指的多个view是不同的,旋转屏幕中涉及到的多个view是在一个 ...

随机推荐

  1. &lbrack;UWP&rsqb;创建自定义VisualState Trigger

    这篇博客将介绍在UWP程序中如何创建和使用自定义VisualState Trigger. 上一篇博客中介绍了如何使用AdaptiveTrigger.目前UWP内置的StateTrigger只有Adap ...

  2. python&lowbar;way &comma;day11 线程&comma;怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)

    python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...

  3. 使用GitHub进行协同项目开发和开源项目贡献

    本教程致力于摆脱git命令行快速的学习使用GitHub. 此次是GitHub课程的第三次课程,也是最后一次课程.推荐进行按照次序查看本次教程.上篇文章:程序员,一起玩转GitHub版本控制,超简单入门 ...

  4. terminal命令

    新建一个文件并写入内容:  echo hello world > a.txt (每次echo都会重写文件) 新建文件: touch a.txt 新建目录: mkdir work 用vim打开文件 ...

  5. koa2源码解读及实现一个简单的koa2框架

    阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...

  6. shell 中的单行注释和多行注释

    1. 单行注释 众所周知,#  比如想要注释:echo “ni” # echo "ni" 2. 多行注释: 法一: : << ! 语句1 语句2 语句3 语句4 ! 例 ...

  7. Maven依赖范围及传递

    .Maven因为执行一系列编译.测试和部署运行等操作,在不同的操作下使用的classpath不同,依赖范围就是用来控制依赖与三种 classpath(编译classpath.测试classpath.运 ...

  8. 用JQuery操作元素的style属性

    可以直接利用css()方法获取元素的样式属性,JQuery代码如下: 1 $("p").css("color");  //获取p元素的样式颜色 无论color属 ...

  9. springmvc aop 事务配置

    对应的中文: 任意公共方法的执行: execution(public * *(..)) 任何一个以“set”开始的方法的执行: execution(* set*(..)) AccountService ...

  10. 使用jQuery实现一个类似GridView的编辑,更新,取消和删除的功能

    先来看看下面实时效果演示: 用户点击编辑时,在点击行下动态产生一行.编辑铵钮变为disabled.新产生的一行有更新和取消的铵钮,点击“取消”铵钮,删除刚刚动态产生的行.编辑铵钮状态恢复. 更新与删除 ...