你真的了解UITextView吗?

一:首先查看一下关于UITextView的定义

NS_CLASS_AVAILABLE_IOS(2_0) @interface UITextView : UIScrollView <UITextInput>

@property(nullable,nonatomic,weak) id<UITextViewDelegate> delegate;
@property(null_resettable,nonatomic,copy) NSString *text;
@property(nullable,nonatomic,strong) UIFont *font;
@property(nullable,nonatomic,strong) UIColor *textColor;
@property(nonatomic) NSTextAlignment textAlignment;    
@property(nonatomic) NSRange selectedRange;  //选中范围

@property(nonatomic,getter=isEditable) BOOL editable; //    是否可以编辑

@property(nonatomic,getter=isSelectable) BOOL selectable NS_AVAILABLE_IOS(7_0); // 是否可以选中

@property(nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);  //属性可以设定使电话号码、网址、电子邮件和符合格式的日期等文字变为链接文字

@property(nonatomic) BOOL allowsEditingTextAttributes NS_AVAILABLE_IOS(6_0); // 默认值为NO 是否允许更改字符属性字典
@property(null_resettable,copy) NSAttributedString *attributedText NS_AVAILABLE_IOS(6_0); //富文本
@property(nonatomic,copy) NSDictionary<NSString *, id> *typingAttributes NS_AVAILABLE_IOS(6_0); 

//滚动到文本的某个段落
- (void)scrollRangeToVisible:(NSRange)range;


@property (nullable, readwrite, strong) UIView *inputView;             
@property (nullable, readwrite, strong) UIView *inputAccessoryView;

@property(nonatomic) BOOL clearsOnInsertion NS_AVAILABLE_IOS(6_0); // 设置是否允许再次编辑时在内容中间插入内容

- (instancetype)initWithFrame:(CGRect)frame textContainer:(nullable NSTextContainer *)textContainer NS_AVAILABLE_IOS(7_0) NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

//则定义了一个矩形区域用于存放已经进行了排版并设置好属性的文字
@property(nonatomic,readonly) NSTextContainer *textContainer NS_AVAILABLE_IOS(7_0);
@property(nonatomic, assign) UIEdgeInsets textContainerInset NS_AVAILABLE_IOS(7_0);
//用于管理NSTextStorage其中的文字内容的排版布局
@property(nonatomic,readonly) NSLayoutManager *layoutManager NS_AVAILABLE_IOS(7_0);
//NSTextStorage保存并管理UITextView要展示的文字内容,该类是NSMutableAttributedString的子类,由于可以灵活地往文字添加或修改属性
@property(nonatomic,readonly,strong) NSTextStorage *textStorage NS_AVAILABLE_IOS(7_0);

//链接文本的样式设置
@property(null_resettable, nonatomic, copy) NSDictionary<NSString *, id> *linkTextAttributes NS_AVAILABLE_IOS(7_0);

@end

UITextView是继承于UIScrollView,并且遵循UITextInput的协议;而UIScrollView是继承于UIView,并且遵循NSCoding协议;上面有些属性跟UITextField是一样的,就没有标注出来;关于UITextInput的协议也可以见关于UITextField里面的内容;包含一些键盘响应及相应的通知处理知识点;

知识点1:关于UIDataDetectorTypes此属性可以设定使电话号码、网址、电子邮件和符合格式的日期等文字变为链接文字

typedef NS_OPTIONS(NSUInteger, UIDataDetectorTypes) {
    UIDataDetectorTypePhoneNumber                              = 1 << 0,          // Phone number detection
    UIDataDetectorTypeLink                                     = 1 << 1,          // URL detection
    UIDataDetectorTypeAddress NS_ENUM_AVAILABLE_IOS(4_0)       = 1 << 2,          // Street address detection
    UIDataDetectorTypeCalendarEvent NS_ENUM_AVAILABLE_IOS(4_0) = 1 << 3,          // Event detection

    UIDataDetectorTypeNone          = 0,               // No detection at all
    UIDataDetectorTypeAll           = NSUIntegerMax    // All types
};
实例:

textView.dataDetectorTypes = UIDataDetectorTypeAll;

UIDataDetectorTypeAll可以检测检测电话、网址和邮箱。符合条件的文本中的内容就会高亮;

知识点2:设置链接样式的运用实例

UITextView * textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 100, 300, 50)];

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"这是一个链接:www.123456.com"];
[attributedString addAttribute:NSLinkAttributeName
                         value:@"url1://www.baidu.com"
                         range:NSMakeRange(7, 14)];


NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor],
                                  NSUnderlineColorAttributeName: [UIColor lightGrayColor],
                                  NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};


textView.linkTextAttributes = linkAttributes;
textView.attributedText     = attributedString;
textView.delegate           = self;
textView.editable           = NO; // 可编辑状态不能点击链接
[self.view addSubview:textView];
// 要实现代理
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
    if ([[URL scheme] isEqualToString:@"url1"]) {
        NSString * url = [URL host];

        NSLog(@"%@",url);

        // 在这里利用url做点什么事情......

        return NO;
    }
    return YES;
}

知识点3UITextView: 响应键盘的 return 事件

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]){ //判断输入的字是否是回车,即按下return
        //在这里做你响应return键的代码
        [textView resignFirstResponder];  
        return NO; //这里返回NO,就代表return键值失效,即页面上按下return,不会出现换行,如果为yes,则输入页面会换行
    }
    return YES;
}

知识点4:如何优雅的让UITextView根据输入文字实时改变高度

  // 初始化控件
  self.contentTextView = [[UITextView alloc]initWithFrame:CGRectMake((kMainBoundsWidth-250)/2, kMainBoundsHeight/2-50, 250, 39)];
  self.contentTextView .layer.cornerRadius = 4;
  self.contentTextView .layer.masksToBounds = YES;
  self.contentTextView .delegate = self;
  self.contentTextView .layer.borderWidth = 1;
  self.contentTextView .font = [UIFont systemFontOfSize:14];
  self.contentTextView .layer.borderColor = [[[UIColor lightGrayColor] colorWithAlphaComponent:0.4] CGColor];
  //加下面一句话的目的是,是为了调整光标的位置,让光标出现在UITextView的正中间
  self.contentTextView.textContainerInset = UIEdgeInsetsMake(10,0, 0, 0);
  [self.view addSubview:self.contentTextView ];
//计算输入文字高度的方法,之所以返回的高度值加22是因为UITextView有一个初始的高度值40,但是输入第一行文字的时候文字高度只有18,所以UITextView的高度会发生变化,效果不太好

  - (float) heightForTextView: (UITextView *)textView WithText: (NSString *) strText{
    CGSize constraint = CGSizeMake(textView.contentSize.width , CGFLOAT_MAX);
    CGRect size = [strText boundingRectWithSize:constraint
                                             options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                          attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]}
                                             context:nil];
    float textHeight = size.size.height + 22.0;
    return textHeight;
}
//每次输入文字后调用该方法,此时输入的文字并不在textView.text中,而在另一个参数text中,走完该方法后每次输入的文字才加入到textView.text中。解决方案是将textView.text和text文字拼接起来
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    CGRect frame = textView.frame;
    float height;
    if ([text isEqual:@""]) {

        if (![textView.text isEqualToString:@""]) {

            height = [ self heightForTextView:textView WithText:[textView.text substringToIndex:[textView.text length] - 1]];

        }else{

            height = [ self heightForTextView:textView WithText:textView.text];
        }
    }else{

            height = [self heightForTextView:textView WithText:[NSString stringWithFormat:@"%@%@",textView.text,text]];
    }

    frame.size.height = height;
    [UIView animateWithDuration:0.5 animations:^{

            textView.frame = frame;

        } completion:nil];

    return YES;
}

知识点5textView其实是没有PlaceHolder,如何设置PlaceHolder如下:

#import <UIKit/UIKit.h>

@interface UIPlaceHolderTextView : UITextView
@property (nonatomic, strong) NSString *placeholder;
@property (nonatomic, strong) UIColor *placeholderColor;

-(void)textChanged:(NSNotification*)notification;
@end
#import "UIPlaceHolderTextView.h"

@interface UIPlaceHolderTextView()
@property (nonatomic, strong) UILabel *placeHolderLabel;
@end

@implementation UIPlaceHolderTextView
CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
#if __has_feature(objc_arc)
#else
    [_placeHolderLabel release]; _placeHolderLabel = nil;
    [_placeholderColor release]; _placeholderColor = nil;
    [_placeholder release]; _placeholder = nil;
    [super dealloc];
#endif
}

- (void)awakeFromNib
{
    [super awakeFromNib];

    if (!self.placeholder) {
        _placeholder = @"";
    }
    
    if (!self.placeholderColor) {
        [self setPlaceholderColor:[UIColor lightGrayColor]];
    }
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}

- (id)initWithFrame:(CGRect)frame
{
    if( (self = [super initWithFrame:frame]) )
    {
        _placeholder = @"";
        [self setPlaceholderColor:[UIColor lightGrayColor]];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}

- (void)textChanged:(NSNotification *)notification
{
    if([[self placeholder] length] == 0)
    {
        return;
    }
    
    [UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
        if([[self text] length] == 0)
        {
            [[self viewWithTag:999] setAlpha:1];
        }
        else
        {
            [[self viewWithTag:999] setAlpha:0];
        }
    }];
}

- (void)setText:(NSString *)text {
    [super setText:text];
    [self textChanged:nil];
}

- (void)drawRect:(CGRect)rect
{
    if( [[self placeholder] length] > 0 )
    {
        UIEdgeInsets insets = self.textContainerInset;
        if (_placeHolderLabel == nil )
        {
            
            _placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),1.0)];
            _placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
            _placeHolderLabel.font = self.font;
            _placeHolderLabel.backgroundColor = [UIColor clearColor];
            _placeHolderLabel.textColor = self.placeholderColor;
            _placeHolderLabel.alpha = 0;
            _placeHolderLabel.tag = 999;
            [self addSubview:_placeHolderLabel];
        }
        _placeHolderLabel.text = self.placeholder;
        [_placeHolderLabel sizeToFit];
        [_placeHolderLabel setFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),CGRectGetHeight(_placeHolderLabel.frame))];
        [self sendSubviewToBack:_placeHolderLabel];
    }
    
    if( [[self text] length] == 0 && [[self placeholder] length] > 0 )
    {
        [[self viewWithTag:999] setAlpha:1];
    }
    
    [super drawRect:rect];
}
- (void)setPlaceholder:(NSString *)placeholder{
    if (_placeholder != placeholder) {
        _placeholder = placeholder;
        [self setNeedsDisplay];
    }
    
}

@end

二:代理方法的内容

@protocol UITextViewDelegate <NSObject, UIScrollViewDelegate>

@optional

// 将要开始编辑
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
// 将要结束编辑
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

// 开始编辑
- (void)textViewDidBeginEditing:(UITextView *)textView;
// 结束编辑
- (void)textViewDidEndEditing:(UITextView *)textView;

// 文本将要改变
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
// 文本发生改变
- (void)textViewDidChange:(UITextView *)textView;
// 焦点发生改变
- (void)textViewDidChangeSelection:(UITextView *)textView;

// 是否允许对文本中的URL进行操作
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange NS_AVAILABLE_IOS(7_0);
// 是否允许对文本中的富文本进行操作
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange NS_AVAILABLE_IOS(7_0);

 

 

最近有个妹子弄的一个关于扩大眼界跟内含的订阅号,每天都会更新一些深度内容,在这里如果你感兴趣也可以关注一下(嘿对美女跟知识感兴趣),当然可以关注后输入:github 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;

posted @ 2016-08-25 17:26  踏浪帅  阅读(7576)  评论(0编辑  收藏  举报