刚才看了一篇textView实现placeholder的文章,有兴趣的同学们可以看下:点击打开链接
最近工作做了一个项目,有许多地方都需要显示文本,并且需要动态计算文本高度.使用过UILabel,UITextField,UITextView,而各有各的缺点....
之前使用无框textfield的时候不能设置文本垂直方向的位置,后来想想只要先计算好文本高度再设置textfield高度其实就可以了.
当时没有想开,于是使用了UITextView,但是吧,这个东西- -跟textfield相比代理函数较少,出现了各种各样蛋疼的问题,其中不仅仅是textView的问题,让我一一道来.
1.我想在键盘栏上面自定义一行控件,怎么做?
textView以及textField有个属性是accessoryView,设置一个你想设置的view
[[self textView] setInputAccessoryView:floatView];
这样便可解决该问题.
2.因为不同尺寸iPhone以及不同输入法的设备键盘高度不同,如何得到键盘高度?
需要在ViewWillAppear:中加入对键盘弹出以及收回事件的监听
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHidden:) name:UIKeyboardDidHideNotification object:nil];
在Notification的参数中有个属性UIKeyboardFrameBeginUserInfoKey ,于是便可获得键盘高度.
# pragma mark - 键盘监听事件(隐藏/显示placeholder,设置textViewNull)
- (void)keyboardShown:(NSNotification *)notification {
[self setConstraintHeight:(<span style="color:#ff6666;">[[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey]</span> CGRectValue].size.height)];
[[self bottomConstrain] setConstant:([self constraintHeight])];
}
一开始想用把NSString转成UTF-8格式,然后使用Char *取每一个字符判断asc码,结果app crash证明了这个方法的不可行.
原因是:一个char *可以存一个英文字符,而中文字符需要两个char *,并且emoji表情也是两个char *,单取一个会导致crash.
想用正则表达式,但是同时还需要判断中文符号和英文符号,本来正则表达式用的就不太熟练,于是放弃了这个念头,
终于找到一个解决方法.NSString 有个方法componentsSeparatedByCharactersInset:
而NSCharacterSet这个集合正好可以设置为符号集.问题得以解决,截取字符串再拼接检测长度就可以了.
- (BOOL)checkString:(NSString *)value {
NSMutableCharacterSet *separateSet = [NSMutableCharacterSet whitespaceAndNewlineCharacterSet];
[separateSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
NSArray *words = [value componentsSeparatedByCharactersInSet:separateSet];
NSString *str = [NSString new];
for (NSString *x in words) {
str = [str stringByAppendingString:x];
}
if ([str length] > 4) {
return YES;
}
return NO;
}
4.textView光标切换
这个页面的textView是一个回复页面,也就是说有的时候我需要在用户进入该页面的时候生成模板文字,然后让用户点击textView时候从模板中间空缺的地方开始编写
- (void)textViewDidChangeSelection:(UITextView *)textView {
if ([[[self textView] text] isEqualToString:[[self fixedAnswer] objectAtIndex:[self currentStyle]]]) {
NSRange range = NSMakeRange(4, 0);
textView.selectedRange = range;
}
}
这里[self fixedAnswer]是我设置好的模板数组,在判断用户如果是在没有输入文字情况下点击的textView,那么就在textView中的第4个字符后插入光标.
5.没有placeHolder?...
正是看到了开篇的那篇文章让我想起来了要整理一下在做textView遇到的这些问题,textView是没有placeHolder的,那我们就需要自己设置placeHolder.
我的做法不是文章中讲的那种,我是在textview开始编辑的位置设置一个UILabel,样式尽量做成placeHolder的样子,然后在textView代理函数
textViewShouldBeginEditing:中将placeHolder隐藏.
在textViewShouldEndEditing:中判断textView是否有文字来决定是否显示placeHolder;
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
[[self placeHolderLabel] setHidden:YES];
return YES;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
if (![[[self textView] text] length]) {
[[self placeHolderLabel] setHidden:NO];
}
return YES;
}
如果是在textField 中那么想这么做就简单多了,实现代理函数textFieldShouldReturn:,想干嘛干嘛就好啦.
但是...textView并不是textField.
不过也有解决方案.
textView 也有个代理函数shouldChangeTextInRange: replacementText:
在这里只要判断replacementText的值是\n,那么就确定用户点击了右下角的确定键.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:@"\n"]) {
//
}
return YES;
}
难得清闲了几晚,最近遇到的textView的问题今天就写到这里了,有空的话会陆续写出遇到的其他问题.
谢谢大家,再见咯~