iOS中,在UIAcitionSheet中添加UIPickerView范例
iOS中,在UIAcitionSheet中添加UIPickerView实例
写在之前,有些事情我们无法左右,但是至少我们可以努力去让它变得更好。我曾说过这样一句话,我可能不是最好的,但我给你的绝对是最好的。找到自己想要的东西,想过的生活,即使再艰难,也别回头看。一个人至少拥有一个梦想,有一个理由去坚强,心若没有栖息的地方,到哪里都是在流浪。
——J!nl!n
写在之前,有些事情我们无法左右,但是至少我们可以努力去让它变得更好。我曾说过这样一句话,我可能不是最好的,但我给你的绝对是最好的。找到自己想要的东西,想过的生活,即使再艰难,也别回头看。一个人至少拥有一个梦想,有一个理由去坚强,心若没有栖息的地方,到哪里都是在流浪。
——J!nl!n
佛祖镇楼,希望每个人开心快乐幸福。
因项目需要,涉及到日期选择器和地区联动选择器。考虑到使用开源库的资源不是特别划算,于是决定自己重写一下iOS系统自身的控件。真正意义上本质也并不是重写,只是在UIAcitionSheet添加部分布局使用UIPickerFView填充。代码比较精简,但是有些地方显得很臃肿,后续随着时间的推移和技术的积累,进一步对其进行优化。此次日志只做记录,博客也会更新收集。
首先来看下一下效果图,如下:
在这里,使用到了系统自带的UIActionSheet,熟悉iOS开发的人应该都知道。UIActionSheet是一个底部弹出的选择按钮项控件,可以添加多项,并为每项添加点击事件。它的初始化代码为:
NSString *title = UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? @"\n\n\n\n\n\n\n\n\n" : @"\n\n\n\n\n\n\n\n\n\n\n\n" ; UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"确定",nil];我们可以看到这里初始化了一个NSString,然后根据屏幕的横竖屏选择使用三目运算符指定填充字符串。这里只用字符\n换行符作为字符使得UIActionSheet的顶部出现一段空的布局以提供UIDatePicker和UIPickerView使用。
actionSheet.userInteractionEnabled = YES; actionSheet.backgroundColor = [UIColor clearColor]; datePicker = [[UIDatePicker alloc] init]; datePicker.tag = 1000; datePicker.datePickerMode = UIDatePickerModeDate; [actionSheet addSubview:datePicker]; [actionSheet showInView:self.view]; actionSheet.tag = 100;上述代码设置UIActionSheet可交互,背景为白色,必须设置背景色,否则可能部分机型会出现\n显示字符。然后初始化UIDatePicker并绑定tag以提供后面方法调用。紧接着设置日期格式,当然也可以是指日期时间格式。最好通过UIActionSheet的addSubView方法添加到之前我们用换行符占位的布局上,并且使用showInView显示在最上面,同样给UIActionSheet设置一个tag值标记。
以上是添加日期选择器的实现。
同理 ,地区联动也是一样的实现。不过相对比较复杂。这里不做详细介绍了。直接贴出实现部分。
plist文件就是普通的国内各省市,直辖市区县的信息,目前并不是很完善,本人地理知识有限,需要不断优化添加。
#pragma mark - 调用地区联动方法 - (void)showAreaPickerView{ // 加载plist文件,初始化三个NSArray对象,然后做一些非法的事情,你懂的 provinces = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"area.plist" ofType:nil]]; cities = [[provinces objectAtIndex:0] objectForKey:@"cities"]; state = [[provinces objectAtIndex:0] objectForKey:@"state"]; NSString *title = UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? @"\n\n\n\n\n\n\n\n\n" : @"\n\n\n\n\n\n\n\n\n\n\n\n" ; UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"确定",nil]; actionSheet.userInteractionEnabled = YES; actionSheet.backgroundColor = [UIColor clearColor]; areaPicker = [[UIPickerView alloc] init]; areaPicker.dataSource = self; areaPicker.delegate = self; [actionSheet addSubview:areaPicker]; [actionSheet showInView:self.view]; actionSheet.tag = 200; }接下来是UIPickerViewDataSource数据源方法和UIPickerViewDelegate代理方法。部分地方仍然可以精简。
// UIPickerViewDataSource中定义的方法,该方法的返回值决定改控件包含多少列 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; // 返回3 表明什么呢?这个如果你不知道,你就别干了、、、表明该控件只包含3列,3列也就够了啊 } // UIPickerViewDataSource中定义的方法,该方法的返回值决定该控件指定列包含多少哥列表项 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { // 如果是第一列,返回provinces的个数 // 也就是provinces包含多少个元素,大天朝有多少个省份里面就有多少个 if (component == 0) { return provinces.count; } else if(component == 1){ // 如果是第二列,返回cities的个数 return cities.count; } else { return areas.count; } } // UIPickerViewDelegate中定义的方法,该方法返回NSString将作为UIPickerView中指定列和列表项上显示的标题 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { // 如果是第一列,返回provinces中row索引出得元素 switch (component) { case 0: return [[provinces objectAtIndex:row] objectForKey:@"state"]; break; case 1: return [[cities objectAtIndex:row] objectForKey:@"city"]; break; case 2: return [areas objectAtIndex:row]; break; default: return @""; break; } } // 当用户选中UIPickerViewDataSource中指定列和列表项时激发该方法 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { switch (component) { case 0: cities = [[provinces objectAtIndex:row] objectForKey:@"cities"]; [self.areaPicker selectRow:0 inComponent:1 animated:YES]; [self.areaPicker reloadComponent:1]; areas = [[cities objectAtIndex:0] objectForKey:@"areas"]; [self.areaPicker selectRow:0 inComponent:2 animated:YES]; [self.areaPicker reloadComponent:2]; state = [[provinces objectAtIndex:row] objectForKey:@"state"]; city = [[cities objectAtIndex:0] objectForKey:@"city"]; if ([areas count] > 0) { district = [areas objectAtIndex:0]; } else{ district = @""; } break; case 1: areas = [[cities objectAtIndex:row] objectForKey:@"areas"]; [self.areaPicker selectRow:0 inComponent:2 animated:YES]; [self.areaPicker reloadComponent:2]; city = [[cities objectAtIndex:row] objectForKey:@"city"]; if ([areas count] > 0) { district = [areas objectAtIndex:0]; } else{ district = @""; } break; case 2: if ([areas count] > 0) { district = [areas objectAtIndex:row]; } else{ district = @""; } break; } }具体逻辑实现可能有一些小细节处理的不好,但实际使用还是很棒的。这里就不贴动态gif图了。
本篇到此为止。