前言
最近新的项目为一个类似钉钉的工具类App,其中有很多的内容填写,以及各种控件展示及选择,例如 UIPickerView 、UIDatePicker 以及点击地图选点等功能。
IOS 的内容输入控件,常用的就是 UITextField 和 UITextView 了,很早之前在项目中也这样使用过,但是没有这个项目中使用的地方这么多,索性就实现一个自定义的 UITextField,省得再每个使用的地方一堆代码来处理,封装了各种操作事件及效果,都在这个内部处理,结果传出去。
本篇主要记录一下 UITextField 封装的控件 UIPickerView 和 UIDatePicker 在 使用过程中的一些问题。
封装思路
像自定义其它控件一样,自定义一个继承于 UITextField 的 QCTextField,实现其各状态监听方法,并处理其结果。
在其内部实现 UIPickerView 和 UIDatePicker 以及代理方法,并处理其结果,或者创建一个 UITextField 的 Category,自定义 UITextField 的
InputAccessoryView & InputView,在外部实现其结果处理,可能没有自定义 UITextField 使用起来方便。
小结
这些选择器,基本都是结合输入框来使用的,即取代原本的键盘。所以我们的设置主要是用到了输入框的inputView属性。
注意:
inputView就是显示键盘的view,如果重写这个view则不再弹出键盘,而是弹出自己的view.如果想实现当某一控件变为第一响应者时不弹出键盘而是弹出我们自定义的界面,那么我们就可以通过修改这个inputView来实现,比如弹出一个日期选择器。
inputView不会随着键盘出现而出现,设置了InputView只会当UITextField或者UITextView变为第一相应者时显示出来,不会显示键盘了。设置了InputAccessoryView,它会随着键盘一起出现并且会显示在键盘的顶端。InutAccessoryView默认为nil.
苹果API说明:
// Presented when object becomes first responder. If set to nil, reverts to following responder chain. If
// set while first responder, will not take effect until reloadInputViews is called.
@property (nullable, readwrite, strong) UIView *inputView;
@property (nullable, readwrite, strong) UIView *inputAccessoryView;
另外一点 关于 inputAccessoryView 的:
-
这些弹出的选择器一般上面会有一个确定或取消的一块区域,这里用到的是inputAccessoryView属性。
- 使用 UIToolBar 来实现
这个UIToolBar里面放的都是UIBarButtonItem元素,我们可以自定义也可以使用默认的,最重要的是UIBarButtonSystemItemFlexibleSpace用来对齐布局的。
类似如下:
- 使用 UIToolBar 来实现
// 取消
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelClick)];
// 完成
UIBarButtonItem *hiddenButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleBordered target:self action:@selector(finishClick)];
// 自定义的
// UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.dateCancelBtn];
// //
// UIBarButtonItem *hiddenButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.makeSureBtn];
UIBarButtonItem *spaceButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIToolbar *accessoryView = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, ScreenW, 44)];
accessoryView.barStyle = UIBarStyleBlackTranslucent;
accessoryView.items = [NSArray arrayWithObjects:cancelButtonItem,spaceButtonItem,hiddenButtonItem,nil];
self.inputAccessoryView = accessoryView;
- 使用 自己创建的 UIView,可以随意设置,用起来更方便,系统 UIToolBar 那么多条条框框,个性化定制,自己发挥。
问题来了:主要的问题
在使用 UIPickerView 的时候倒还好,没有啥问题,毕竟这些都是一些基本控件的使用,况且在项目找那个也会经常遇到,另外基本上用的UIPickerView只是显示字符串,而有的则需要显示更高级的东西,所以就需要用到view,而不是title。
文档说明:
// these methods return either a plain NSString, a NSAttributedString, or a view (e.g UILabel) to display the row for the component.
// for the view versions, we cache any hidden and thus unused views and pass them back for reuse.
// If you return back a different object, the old one will be released. the view will be centered in the row rect
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED;
- (nullable NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED; // attributed title is favored if both methods are implemented
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view __TVOS_PROHIBITED;
但在使用 UIDatePicker 的时候就没有那么顺利了,同时设置了 UITextField 的
InputAccessoryView & InputView 属性,但是日期选择器 上方的完成取消区域始终不显示,比对了 UIPickerView 的创建及处理,因为使用 UIPickerView 是没有问题的,一直没有找到问题的关键所在,直到今晚也就是刚才才发现了真正的原因:
- (UIDatePicker *)datePicker
{
if (!_datePicker) {
_datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, topView_view_height, ScreenW, picker_view_height)];
_datePicker.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
_datePicker.backgroundColor = [UIColor whiteColor];
// _datePicker.minimumDate = [NSDate date];
}
return _datePicker;
}
乍一看,是没有问题的,但是问题始终是存在的,看看视图层次,就会发现其中的原因:
image.png image.png因为设置了 UIDatePicker 的 frame ,刚好把顶部的取消确认区域遮挡了,一种方法是初始化,不设置 frame,系统会自己设置处理的,6s 上是 216,而我设置了 260。
- 解决方法一,使用系统默认的 frame
_datePicker = [[UIDatePicker alloc] init];
- 解决方法二:重新更改 frame,调整上下区域的高度即可。
完美解决,知道问题的原因就好解决了,怕的是找不到问题的根本原因,值得记录一下。
网友评论