• ios开发之自定义textView


    自定义textView,从理论上讲很简单,根据需求自定义,比如我在开发中的需求就是现实一个字数的限制以及根据输入的文字改变提示剩余字数,那么开始我的基本思路就是自定义一个View,而里面包含一个子控件textView以及占位label和剩余字数现实label,看似很简单但是实际上会遇到很多坑!那么我就首先呢从创建这个自定义textView开始,然后在深入讲讲我在这之中遇到的问题和坑。。

      在头文件中我是这样申明的:

      

    /**

     *  占位符

     */

    @property (nonatomic, copy)NSString *placeholder;

    @property (nonatomic, strong)UILabel *placehoderLabel;

    /**

     *  限制的文字

     */

    @property (nonatomic, copy)NSString *limitStr;

    /**

     *  剩余字数

     */

    @property (nonatomic, assign)NSInteger count;

    @property (nonatomic, strong)UILabel *countLabel;

    @property (nonatomic, weak)id<UITextViewDelegate> textViewDelegate;

    @property (nonatomic, strong)UITextView *textView;

     在头文件中我公开了很多属性,比如placehoderLabel, textView,countLabel等等,在这我想说明一件事情,这件事情也是我在公司和一位同事意见不合的问题,我认为一切有变化的因子,都应该留出接口让别人能够改变,意思也就是说,在我们自定义一个控件的时候,为了可以让更多的人使用以及复用性,我们一定要留出变化的接口,这样在别人复用的时候,就不用再去内部改变,而只是根据接口去改变这些需要改变的内容即可。

     下面贴上我的整个实现代码:

    @implementation YHTextView

    - (NSString *)placeholder {

        if (_placeholder == nil) {

            _placeholder = @"请输入文字";

        }

        return _placeholder;

    }

    - (instancetype)initWithFrame:(CGRect)frame {

        if (self = [super initWithFrame:frame]) {

            self.layer.borderColor = [UIColor lightGrayColor].CGColor;

            self.layer.borderWidth = 1.f;

            _count = 50;

            self.countLabel.text = @"剩余50字";

            self.textView.height = self.height - 25;

            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewCharacterChanged:) name:UITextViewTextDidChangeNotification object:nil];

        }

        return self;

    }

    - (UITextView *)textView {

        if (_textView == nil) {

            _textView = [[UITextView alloc] init];

            _textView.frame = CGRectMake(0, 0, self.width, self.height);

            _textView.delegate = self.textViewDelegate;

            _textView.font = TK_FONTSYS(14);

            [self addSubview:_textView];

        }

        return _textView;

    }

    - (UILabel *)placehoderLabel {

        if (_placehoderLabel == nil) {

            _placehoderLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, 20, 20)];

            _placehoderLabel.text = self.placeholder;

            _placehoderLabel.textAlignment = NSTextAlignmentLeft;

            _placehoderLabel.font = [UIFont systemFontOfSize:14];

            _placehoderLabel.textColor = [UIColor lightGrayColor];

            [self.textView addSubview:_placehoderLabel];

        }

        [self sendSubviewToBack:_placehoderLabel];

        return _placehoderLabel;

    }

    - (UILabel *)countLabel {

        if (_countLabel == nil) {

            _countLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.width-5-100, self.height-5-20, 100, 20)];

            _countLabel.textAlignment = NSTextAlignmentRight;

            _countLabel.font = [UIFont systemFontOfSize:13];

            _countLabel.textColor = [UIColor lightGrayColor];

            [self addSubview:_countLabel];

        }

        return _countLabel;

    }

    - (void)layoutSubviews {

        self.placehoderLabel.frame = CGRectMake(8, 8, self.width, 20);

        if (self.textView.text.length>0) {

            self.placehoderLabel.hidden = YES;

            self.countLabel.text = [NSString stringWithFormat:@"剩余%ld字", self.count - self.textView.text.length];

            self.placehoderLabel.hidden = YES;

        }

    }

    - (void)textViewCharacterChanged:(NSNotification *)not {

        NSInteger length = self.textView.text.length;

        self.placehoderLabel.hidden = YES;

        // 获取键盘类型

        UITextInputMode *mode = (UITextInputMode *)[UITextInputMode activeInputModes][0];

        // 获取当前的键盘语言

        NSString *lang = mode.primaryLanguage;

        if ([lang isEqualToString:@"zh-Hans"]) {

            UITextRange *selectedRange = [self.textView markedTextRange];

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

            if (!position) {

                if ([self beyondLimitCount:length]) return ;

                if (length == 0) {

                    self.countLabel.text = @"剩余50字";

                    self.placehoderLabel.hidden = NO;

                }

                else {

                    self.countLabel.text = [NSString stringWithFormat:@"剩余%ld字", self.count - length];

                    self.placehoderLabel.hidden = YES;

                }

            }

        }

        else {

            if ([self beyondLimitCount:length]) return ;

            if (length == 0) {

                self.countLabel.text = @"剩余50字";

                self.placehoderLabel.hidden = NO;

            }

            else {

                self.countLabel.text = [NSString stringWithFormat:@"剩余%ld字", self.count - length];

                self.placehoderLabel.hidden = YES;

            }

        }

    }

    - (BOOL)beyondLimitCount:(NSInteger)length {

        if (length <= self.count) {

            self.textView.editable = YES;

            return NO;

        }

        else {

            self.textView.text = [self.textView.text substringToIndex:self.count];

            self.countLabel.text = @"剩余0字";

            return YES;

        }

    }

    - (void)dealloc {

        [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

     1>第一点需要注意的是,添加通知和移除通知是必须配对的,我们一般在dealloc方法里移除通知

     2>在我的代码中很多控件都是懒加载的方式初始化的,这也是苹果比较推荐的一种方式,懒加载即是控件需要显示的时候加载

    3>核心代码都在通知方法里,首先我们需要获取键盘类型,从而获得当前的语言,注意是汉字的话要进行特殊处理,因为汉字在输入的时候有一个高亮状态如果,不作处理,如果说剩余2个字,你想在输入“行”拼音是“xing”,就会只输入xi,无法得到汉字,这也是我遇到比较坑的一个地方。

    至于其他部分都是一些比较简单的逻辑处理,在这里就不再做说明了。

  • 相关阅读:
    超简单的博弈算法题,一行代码解决!
    图解「剑指Offer」之用前序和中序遍历序列构建二叉树
    GitHub 标星 2.4w!最火正则表达式课程学起来!
    经典面试题:最长公共子序列
    记一道字节跳动的算法面试题
    LeetCode 实战:「图解」二叉树中的最大路径和
    你离攻克数据结构与算法,只差这一步
    在《我的世界》里从零打造一台计算机有多难?复旦本科生大神花费了一年心血...
    三分钟理解字符串经典考题:有效的字母异位词
    【算法之美】改变世界的十位算法大师
  • 原文地址:https://www.cnblogs.com/wannaGoBoy/p/5761180.html
Copyright © 2020-2023  润新知