iOS学习之UITextView问题一网打尽(占位文字、汉字输入字数计算、自动高度改变)

在iOS开发中,UITextView是一个使用还算比较多的控件。但是用过的人都知道,UITextView有很多存在的问题,今天就来一一说它一说。

一、设置textView的placeHolder

首先需要解决的就是占位文字placeHolder的问题,与UITextField相比,UITextView并没有相应的placeholder属性设置占位文字,但是可以通过category的方式给textView添加placeHolder属性,这样就可以在任何需要的使用直接使用了,我写好了一个category UITextView+PlaceHolder,大概如下:

.h中:
#import

@interface UITextView (PlaceHolder)

@property (nonatomic, copy) NSString *placeHolder;

@end
.m中:
#import "UITextView+PlaceHolder.h"

#import

#define kScreenW [UIScreen mainScreen].bounds.size.width

static const void *textView_key = @"placeHolder";

@interface UITextView ()

@end

@implementation UITextView (PlaceHolder)

- (void)setPlaceHolder:(NSString *)placeHolder{

    if (placeHolder != self.placeHolder) {

        objc_setAssociatedObject(self, textView_key, placeHolder, OBJC_ASSOCIATION_COPY_NONATOMIC);

        UILabel *placeHolderLb = [[UILabel alloc] initWithFrame:CGRectMake(2, 7, kScreenW-2*16, 21)];

        placeHolderLb.tag = 1000;

        placeHolderLb.contentMode = UIViewContentModeTop;

        placeHolderLb.numberOfLines = 0;

        placeHolderLb.textColor = [UIColor redColor];

        placeHolderLb.font = [UIFont systemFontOfSize:16];

        placeHolderLb.alpha = 1;

        placeHolderLb.text = placeHolder;

        [self addSubview:placeHolderLb];

        //之所以使用通知形式是为了不影响textView的delegate方法,否则别的地方- (void)textViewDidChange:(UITextView *)textView这个代理不会再执行

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
}
- (NSString *)placeHolder{
    return objc_getAssociatedObject(self, textView_key);
}

- (void)textViewChanged:(NSNotification *)noti{
    UILabel *label = [self viewWithTag:1000];
    if (self.text.length == 0) {
        label.alpha = 1;
    } else {
        label.alpha = 0;
    }
}

如需修改placeHolder的字体大小或者颜色之类的,可以直接在.m中修改,也可以自己再给textView添加相应的属性,这里就不再叙述。

二、输入汉字时字数统计

开发中这样的需求也不少见,需要实时统计textView中输入的字数,如下页面


1.png

常规的做法就是设置textView的delegate,实现delegate中的- (void)textViewDidChange:(UITextView *)textView,然后统计输入文字的个数,当然这对于统计英文和数字来说,一般都是没有问题的,但是到统计中文的时候就出现了问题。当用户连续输入拼音,还未选择内容时,其实上面的方法已经执行了,也就是说每次输入拼音都会走上面的代理,这就很尴尬了,实时显示的字数,就会一直跳来跳去,这怎么办呢?
实现(void)textViewDidChange:(UITextView *)textView这个代理,但是在里面需要做点处理

- (void)textViewDidChange:(UITextView *)textView

{

    NSInteger maxFontNum = 200;//最大输入限制

    NSInteger length = self.textView.text.length;

    NSString *toBeString = textView.text;

    // 获取键盘输入模式

    NSString *lang = [[UIApplication sharedApplication] textInputMode].primaryLanguage;

    if ([lang isEqualToString:@"zh-Hans"]) { // zh-Hans代表简体中文输入,包括简体拼音,健体五笔,简体手写

        UITextRange *selectedRange = [textView markedTextRange];

        //获取高亮部分

        UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];

        // 没有高亮选择的字,则对已输入的文字进行字数统计和限制

        if (!position) {

            if (toBeString.length > maxFontNum) {

                textView.text = [toBeString substringToIndex:maxFontNum];//超出限制则截取最大限制的文本

                self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",maxFontNum];

            } else {

                self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",toBeString.length];

            }

        }

    } else {// 中文输入法以外的直接统计

        if (toBeString.length > maxFontNum) {

            textView.text = [toBeString substringToIndex:maxFontNum];

            self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",maxFontNum];

        } else {

            self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",toBeString.length];

        }

    }

}

根据键盘类型进行判断,如果输入的是中文,则判断是否为高亮文字即连续输入的拼音,如果不是高亮的则直接进行字数统计,否则不作处理,这样就解决了字数统计的问题。

三、tableViewCell中textView的高度自适应

cell中有textView,想实现的效果是当textView中输入文字的时候,textView和cell的高度都随着输入文字的高度进行自适应,对cell高度自适应还没有概念的可以看看[这篇文章],这里就不多讲了。

要做到高度自适应,还是要在- (void)textViewDidChange:(UITextView *)textView中实现,接着上面获取输入字数的实现继续:

- (void)textViewDidChange:(UITextView *)textView

{

    NSInteger maxFontNum = 200;//最大输入限制

    NSInteger length = self.textView.text.length;

    NSString *toBeString = textView.text;

    // 获取键盘输入模式

    NSString *lang = [[UIApplication sharedApplication] textInputMode].primaryLanguage;

    if ([lang isEqualToString:@"zh-Hans"]) { // zh-Hans代表简体中文输入,包括简体拼音,健体五笔,简体手写

        UITextRange *selectedRange = [textView markedTextRange];

        //获取高亮部分

        UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];

        // 没有高亮选择的字,则对已输入的文字进行字数统计和限制

        if (!position) {

            if (toBeString.length > maxFontNum) {

                textView.text = [toBeString substringToIndex:maxFontNum];//超出限制则截取最大限制的文本

                self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",maxFontNum];

            } else {

                self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",toBeString.length];

            }

        }

    } else {// 中文输入法以外的直接统计

        if (toBeString.length > maxFontNum) {

            textView.text = [toBeString substringToIndex:maxFontNum];

            self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",maxFontNum];

        } else {

            self.textCountLabel.text = [NSString stringWithFormat:@"%ld/200",toBeString.length];

        }

    }

    //高度自适应

    CGFloat height = [textView.text boundingRectWithSize:CGSizeMake(self.textView.width, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.height;

    if (height >= 80) {

        self.textViewHeightConstant.constant = height;

    } else {

        self.textViewHeightConstant.constant = 80;

    }

    [self.tableView beginUpdates];

    [self.tableView endUpdates];

}

这里有几个重点:

1.最重要的一点,设置tableView的scrollEnabled=NO,如果不正确设置此值,不会实现高度自适应的效果。

2.给textView添加约束时,要设置textView的height为>=某个值,比如我这里的>=80,接着拖出这个约束,上面的textViewHeightConstant就是textView高度的约束。然后根据计算出的文字高度判断是否需要cell和textView伸缩

3.要实时更新tableView中cell的frame,通过[self.tableView beginUpdates]; [self.tableView endUpdates];来更改。这里的self.tableView是我在cell中添加的tableView这个属性,也可以通过self.superView获取当前的tableView。

感谢:
https://www.jianshu.com/p/b72908329ee7
详细的demo已经放在github上了,有需要的随时取用哈> https://github.com/coolLeee/TextViewHelper

你可能感兴趣的:(iOS学习之UITextView问题一网打尽(占位文字、汉字输入字数计算、自动高度改变))