1.输入长度限制:
错误示范:
textfield输入限制长度的需求很普遍,你看到这个需求时也许觉得这个太简单了,只需要像下面这样写就可以了。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(@"-----%@",toBeString);
if(toBeString.length>5){
_textfield.text = [toBeString substringToIndex:5];
return NO;
}
return YES;
}
上面的写法对纯字符(英文和数字等)有效,但对中文无效。
这个代理方法触发的时机是每当在键盘上敲击了一个字符,导致了输入框中的蓝色高亮文本发生改变。string参数即为敲击的字符,也即为对高亮文本来说所发生的变化。乍看好像没什么问题:当输入的字符长度超过最大限制长度时,就从toBeString截取最大限制长度的子串。
但对于中文输入来说是存在问题的:输入框中高亮的文本并非最终显示在输入框的汉字,通过统计高亮文本的长度来限制输入汉字长度这明显是有问题的。这造成的结果是:当我想输入“喜剧之王”时,便最多只能输入"xijuz",因为这个长度统计的是高亮文本的长度,它此时已达到最大长度限制了,但实际上汉字还未超过最大限制长度,导致无法继续输入汉字,甚至一个汉字也输入不了。
怎么改善?
上面的问题在于对中文输入长度的统计方式不对,不能以高亮文本长度统计,应该以确确实实已选取,并已然显示在输入框的汉字统计。限制汉字的选取,但不限制高亮文本的变化。
但问题是,上面这个代理方法触发时机是高亮文本发生变动时,而在输入法选取汉字的动作并不会触发其执行。如此我们无法得知当前输入框已选的汉字们。
这就需要用到一个重要的通知了:UITextFieldTextDidChangeNotification
,注册该通知后不仅高亮文本发生变动时触发,选取汉字时也会触发。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textFeildEditChanged:) name:@"UITextFieldTextDidChangeNotification"
object:_textfield];
那我们来梳理一下限制控制的逻辑:
1.当输入纯字符时,只需比较toBeString的长度和最大限制长度,超出就截取toBeString的子串就行;
2.当输入汉字时,对高亮文本不做限制;对已然显示在输入框的汉字进行字数统计和限制,若超出最大限制长度就截取子串。
以上用代码实现就是:
- (void)textFeildEditChanged:(NSNotification *)notifition
{
// UITextField *tf = (UITextField *)notifition.object;
NSString *toBeString = _textfield.text;
NSString *lang = _textfield.textInputMode.primaryLanguage; // 键盘输入模式
if ([lang isEqualToString:@"zh-Hans"]) // 如果输入中文
{
UITextRange *selectedRange = [_textfield markedTextRange];
//获取高亮部分
UITextPosition *position = [_textfield positionFromPosition:selectedRange.start offset:0];
// 没有高亮选择的字,则对已输入的汉字进行字数统计和限制
if (!position)
{
if (toBeString.length > 5) {
_textfield.text = [toBeString substringToIndex:5];
}
}
// 对高亮文本不做限制,因为它不是最终显示在输入框的文本。
else
{
}
}
// 中文输入法以外的直接对其统计限制即可,不考虑其他语种情况
else
{
if (toBeString.length > 5) {
_textfield.text = [toBeString substringToIndex:5];
}
}
}
2.自定义placeholder:
textfield设置placeholder只需这样:_textfield.placeholder = @"请输入姓名,限制5个字";
但有时产品设计得需要个性化一点,可能需要对placeholder的字体、颜色等进行自定制。比如:
NSDictionary *attriDict = @{NSFontAttributeName:[UIFont systemFontOfSize:11],
NSForegroundColorAttributeName:[UIColor blackColor]};
_textfield.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入姓名,限制5个字"
attributes:attriDict];
我看到网上也有人说可以通过KVC给私有属性赋值的方式修改,但是我试过一次是无效的,也不知为什么。下来再研究研究。
遇到的问题:
屏幕快照 2016-06-15 22.09.16.png当placeholder字体大小发生变化后,placeholder的文本可能不再垂直居中显示了!
解决方案:
子类化UITextField,重写placeholderRectForBounds:
方法,对placeholder的偏移量进行调整。
#import "YWTextField.h"
@implementation YWTextField
//控制placeHolder的位置,左右缩20
-(CGRect)placeholderRectForBounds:(CGRect)bounds
{
CGRect inset = CGRectMake(2, 6, bounds.size.width -10, bounds.size.height);
return inset;
}
@end
3.键盘遮挡问题:
在有UITextField和UITextView的地方,就容易出现键盘遮挡问题。这里我要说的解决方案的思路是:通过系统提供的有关键盘的通知UIKeyboardWillShowNotification
,UIKeyboardWillHideNotification
进行全局注册观察。然后需要相应的类通过代理方法来处理键盘出现和消失时,界面上输入框上移和下移的动画。
既然是添加全局的观察,则在AppDelegate里注册通知:
#import <UIKit/UIKit.h>
typedef enum
{
KeyBoardWillShow, // 键盘弹出
KeyBoardWillHide, // 键盘退回
}KeyBoardChangeType;
@protocol YWKeyboardDelegate <NSObject>
- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType
beginFrame:(CGRect)beginFrame
endFrame:(CGRect)endFrame
duration:(CGFloat)duration
keyboardHeight:(CGFloat)kbHeight
userInfo:(NSDictionary *)info;
@end
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, weak)id<YWKeyboardDelegate> ywKeyboardDelegate; // 代理
@end
#import "AppDelegate.h"
#import "HomeViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HomeViewController *homeVC = [[HomeViewController alloc] init];
UINavigationController *homeNavC = [[UINavigationController alloc] initWithRootViewController:homeVC];
self.window.rootViewController = homeNavC;
[self.window makeKeyAndVisible];
[self registerKeyboardNotification]; // 注册键盘弹出和退回的通知
return YES;
}
- (void)registerKeyboardNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
[self ywKeyboardChangeStatus:KeyBoardWillShow userInfo:notification.userInfo];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[self ywKeyboardChangeStatus:KeyBoardWillHide userInfo:notification.userInfo];
}
// 得到动画时间、键盘高度等信息。并调用代理方法,在相应类里的代理方法里实现输入框上移下移动画等。
- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType userInfo:(NSDictionary *)info
{
CGFloat durationTime = [info[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGFloat keyboardHeight = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
CGRect beginFrame = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
if([self.ywKeyboardDelegate respondsToSelector:@selector(ywKeyboardChangeStatus:beginFrame:endFrame:duration:keyboardHeight:userInfo:)])
{
[self.ywKeyboardDelegate ywKeyboardChangeStatus:changeType beginFrame:beginFrame endFrame:endFrame duration:durationTime keyboardHeight:keyboardHeight userInfo:info];
}
}
// 一定要记得移除通知
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
比如在登录界面需要处理键盘遮挡问题,出现键盘时账号和密码输入框会上移,避免被键盘遮挡;当键盘消失时,输入框移回原位。
#import "HomeViewController.h"
#import "AppDelegate.h"
@interface HomeViewController ()<YWKeyboardDelegate>
@end
@implementation HomeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"登录";
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.ywKeyboardDelegate = self; // 记得实现YWKeyboardDelegate协议
}
#pragma mark ---- ywkeyboardDelegate
- (void)ywKeyboardChangeStatus:(KeyBoardChangeType)changeType beginFrame:(CGRect)beginFrame endFrame:(CGRect)endFrame duration:(CGFloat)duration keyboardHeight:(CGFloat)kbHeight userInfo:(NSDictionary *)info
{
if(changeType == KeyBoardWillShow){
[UIView animateWithDuration:duration animations:^{
self.view.transform = CGAffineTransformMakeTranslation(0, -kbHeight);
}];
}
else if(changeType == KeyBoardWillHide){
[UIView animateWithDuration:duration animations:^{
self.view.transform = CGAffineTransformIdentity;
}];
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
@end
网友评论