UITextView-使用集合

键盘弹出来时,改变工具栏的高度,
想要实现键盘和工具栏一起往上移动的效果,

添加动画,调用[self.view layoutIfNeeded];方法即可
UITextView-使用集合_第1张图片
image.png

注意:

    #UITextView的高度,一定要大于输入文字的高度,不然输入文字的时候会晃动,而且还会显示不全哦。所以富文本的时候高度是个大事。
    UITextView *titleView = [[UITextView alloc] initWithFrame:CGRectMake(15, 20, SCREEN_WIDTH-30, 30)];
    titleView.font = [UIFont systemFontOfSize:24];
    #系统Bug。(UITextView文字和占位文字偏移了10的间距)
    titleView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, -10);
    titleView.backgroundColor=[UIColor yellowColor];
    [self.view addSubview:titleView];
1,解决textView输入内容的时候,光标下沉。
//解决textView输入内容的时候,光标下沉。
    self.textField_t.textContainerInset = UIEdgeInsetsMake(5, 0, 0, 0);
2,输入了100行,然后输入第一行内容,那么会自动跑到底部。这句就是为了防止回到底部
    //输入了100行,然后输入第一行内容,那么会自动跑到底部。这句就是为了防止回到底部
    self.textView_c.layoutManager.allowsNonContiguousLayout = NO;
3,自定义view中textview滚动失效 iOS(自定义view放在了一个VC中)
#解决方法:
在VC中
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    //自定义view中的TextView的scrollEnabled需要在VC加载结束后手动打开一次,不然会把默认YES改为NO。
    self.detailView.textView_detail.scrollEnabled = YES;
}
4,添加图片附件
    //添加图片附件
    NSTextAttachment *attach = [[NSTextAttachment alloc] init];
    attach.image = [UIImage imageNamed:@"1.jpg"];
    attach.bounds = CGRectMake(0, 0, 100, 100);
    //附件是不可变属性字符串
    NSAttributedString *attributedString = [NSAttributedString attributedStringWithAttachment:attach];
    NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"点击分手克里斯丁建安费垃圾啊啥都离开房间撒的李开复"];
    [attributedStr insertAttributedString:attributedString atIndex:attributedStr.length];

    self.textView.attributedText = attributedStr;
5,获取光标位置
#注意:使用时候判断是否为空:
    NSRange rg = self.textView.selectedRange;
     if (rg.location != NSNotFound)
    {
        NSLog(@"光标位置:%d",rg.location);
    }

6,iOS中TextView显示HTML文本

7,输入时上下晃动

CGRect line = [textView caretRectForPosition:textView.selectedTextRange.start];
    CGFloat overflow = line.origin.y + line.size.height    - ( textView.contentOffset.y + textView.bounds.size.height - textView.contentInset.bottom - textView.contentInset.top );
    if ( overflow > 0 ) {
        // We are at the bottom of the visible text and introduced a line feed, scroll down (iOS 7 does not do it)
        // Scroll caret to visible area
        CGPoint offset = textView.contentOffset;
        offset.y += overflow + 7;
        // leave 7 pixels margin
        // Cannot animate with setContentOffset:animated: or caret will not appear
        [UIView animateWithDuration:.2 animations:^{
            [textView setContentOffset:offset];
        }];
    }
8,UITextView加载HTML数据(左间距没有调试成功,暂用wkwebView.)

- (void)viewDidLoad {
    [super viewDidLoad];

    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, [UIScreen mainScreen].bounds.size.width - 20, [UIScreen mainScreen].bounds.size.height - 20)];
    textView.delegate = self;
    textView.editable = NO; // 非编辑状态下才可以点击Url]
//    textView.fontFloat = 18.;
    NSString *textStr=@"

现在互联网,断章取义的东西大家最喜欢玩了,本来是个很严肃很励志的一句话,但是把头尾一截,就变得很有趣味了


先订一个能达到的小目标(严肃认真脸.jpg)

比方说我先挣它一个亿(严肃轻松脸.png)

首尾的强大反差给人一种无奈到好笑的感觉,跟比尔盖茨很有名的那张3秒赚辆兰博基尼有异曲同工之妙。


说的随便点吧,就是大家觉得这东西好玩搞笑,极具讽刺性,跟大家的生活现状形成强烈的对比,明明就是苦逼屌丝一辈子赚不到一千万的角儿,却要看着人家定个小目标随便弄他一个亿,我的妈呀,人与人之间的差别距离好几个爹呀。

互联网现在信息传递快,大家爱自嘲、爱起哄,像这种能够开名人玩笑,为生活补充点乐子的事,而且还能表达一下自己对生活的挖苦、讽刺,所以转了也就转了

"; // NSString *linkStr = [textView.text substringWithRange:range]; NSMutableAttributedString *attributedString = [self changeHtmlStringToAttributeString:textStr]; // [attributedString addAttribute:NSLinkAttributeName value:@"http://img.taopic.com/uploads/allimg/111231/6755-11123114022199.jpg" range:NSMakeRange(0, 6)]; textView.attributedText = attributedString; [self.view addSubview:textView]; #测试 ( self.jq_textView.delegate = self; self.jq_textView.editable = NO; // 非编辑状态下才可以点击Url] // textView.fontFloat = 18.; NSString *textStr=@"

会员权益简介 -----------------

会员专享价

权益说明

商品促销信息以商品详情页“促销”栏中的信息为准;商品的具体售价以订单结算页价格为准;如您发现活动商品售价或促销信息有异

权益等级

信息以商品详情页“促销”栏

其他说明

商品促销信息以商品详情页“促销”栏中的信息为准;商品的具体售价以订单结算页价格为准;如您发现活动商品售价或促销信息有异

"; // NSString *linkStr = [textView.text substringWithRange:range]; NSMutableAttributedString *attributedString = [self changeHtmlStringToAttributeString:textStr]; self.jq_textView.attributedText = attributedString; ) } -(NSMutableAttributedString *)changeHtmlStringToAttributeString:(NSString *)htmlString{ NSString *newString = htmlString; //图片自适应宽高,只限制图片的最大显示宽度,这样就能做到自适应 newString =[NSString stringWithFormat:@"" "" "" "" "" "%@" "",self.view.frame.size.width-30,newString]; NSData *data = [newString dataUsingEncoding:NSUnicodeStringEncoding]; NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; NSMutableAttributedString *htmlAttribute = [[NSMutableAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil]; NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init]; //设置文字的行间距 [paragraphStyle setLineSpacing:5]; [htmlAttribute addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [htmlAttribute length])]; //设置文字的颜色 [htmlAttribute addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, htmlAttribute.length)]; //设置文字的大小 [htmlAttribute addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:14] range:NSMakeRange(0, htmlAttribute.length)]; return htmlAttribute; #测试 ( NSString *newString = htmlString; NSData *data = [newString dataUsingEncoding:NSUnicodeStringEncoding]; NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; NSMutableAttributedString *htmlAttribute = [[NSMutableAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil]; return htmlAttribute; ) }
9,自定义 UITextView 关键字高亮与点击检测
10,替换属性字符串中的图片为字符
#:属性字符串attributeString
    //方法一
//    NSMutableString *plainString = [NSMutableString stringWithString:attributeString.string];
//    __block NSUInteger base = 0;
//    [self enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, self.length)
//                     options:0
//                  usingBlock:^(LiuqsTextAttachment *value, NSRange range, BOOL *stop) {
//                      if (value) {
//                          [plainString replaceCharactersInRange:NSMakeRange(range.location + base, range.length)
//                                                     withString:value.emojiTag];
//                          base += value.emojiTag.length - 1;
//                      }
//                  }];
    
    //方法二(推荐)
    NSMutableAttributedString *mutableAttributeString = [[NSMutableAttributedString alloc] initWithAttributedString:attributeString];
    [mutableAttributeString enumerateAttribute:@"NSAttachment" inRange:NSMakeRange(0, self.length) options:0 usingBlock:^(id  _Nullable value, NSRange range, BOOL * _Nonnull stop) {
        
        NSLog(@"value===%@",value);
        NSLog(@"range===%@",NSStringFromRange(range));

        if ([value isKindOfClass:[NSTextAttachment class]]) {
            LiuqsTextAttachment *attachment = (LiuqsTextAttachment *)value;
            [mutableAttributeString replaceCharactersInRange:range withString:attachment.emojiTag];
        }
        
    }];
    
    return [mutableAttributeString string];
11,清空UItextView的所有内容
self.toolView.jq_inputView.text = @" ";
[self.toolView.jq_inputView deleteBackward]; //删除一个字节
12,UITextView/UITextField检测并过滤Emoji表情符号
当用户切换键盘为Emoji表情时,输入的表情不响应(即表情符号不显示到UITextView或UITextField)。这里可以通过UITextView或UITextField的回调和是否为emoji键盘:

 /*
 *第一种方法,简单粗暴
 */
 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
 {
     // 不让输入表情
     if ([textView isFirstResponder]) {
         if ([[[textView textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textView textInputMode] primaryLanguage]) {
             NSLog(@"输入的是表情,返回NO");
             UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"不能输入表情" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
             [alertView show];
             return NO;
         }
     }
     return YES;
 }

为避免当用户通过中文键盘输入中文“哈哈”后出现可选文字中选中的Emoji笑脸,最后在- (void)textFieldDidEndEditing:(UITextField *)textField方法中统一通过检查最终字符串textField/textView.text的内容,通过Emoji筛unicode编码来判断是否存在Emoji表情,如果存在则提醒用户做修改。

 //在输入完成时,调用下面那个方法来判断输入的字符串是否含有表情
 - (void)textFieldDidEndEditing:(UITextField *)textField
 {
     if ([self stringContainsEmoji:textField.text]) {
         NSLog(@"含有表情");
         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"输入内容含有表情,请重新输入" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
         [alertView show];
         textField.text = @"";
         [textField becomeFirstResponder];
     }else {
         NSLog(@"不含有表情");
     }

 }

 /*
  *第二种方法,利用Emoji表情最终会被编码成Unicode,因此,
  *只要知道Emoji表情的Unicode编码的范围,
  *就可以判断用户是否输入了Emoji表情。
  */
 - (BOOL)stringContainsEmoji:(NSString *)string
 {
     // 过滤所有表情。returnValue为NO表示不含有表情,YES表示含有表情
     __block BOOL returnValue = NO;
     [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {

         const unichar hs = [substring characterAtIndex:0];
         // surrogate pair
         if (0xd800 <= hs && hs <= 0xdbff) {
             if (substring.length > 1) {
                 const unichar ls = [substring characterAtIndex:1];
                 const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                 if (0x1d000 <= uc && uc <= 0x1f77f) {
                     returnValue = YES;
                 }
             }
         } else if (substring.length > 1) {
             const unichar ls = [substring characterAtIndex:1];
             if (ls == 0x20e3) {
                 returnValue = YES;
             }
         } else {
             // non surrogate
             if (0x2100 <= hs && hs <= 0x27ff) {
                 returnValue = YES;
             } else if (0x2B05 <= hs && hs <= 0x2b07) {
                 returnValue = YES;
             } else if (0x2934 <= hs && hs <= 0x2935) {
                 returnValue = YES;
             } else if (0x3297 <= hs && hs <= 0x3299) {
                 returnValue = YES;
             } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
                //想过滤的字符可以在这里做处理
                if (![substring isEqualToString:@"®"]) {
                    returnValue = YES;
                }
             }
         }
     }];
     return returnValue;
 }

13,UITextView插入图片时,通常会想在前后插入换行(\n),但是呢,如果加了行高之类的东西,那么就尴尬了,因为计算的高度会出问题。
#方案一:在图片前后分别再插入一个附件,高度为0或1,宽度为屏幕宽。
#first,尴尬了,附件有个默认的高度,大概10-15左右吧,
这个高度是去不掉的,而且就算高度为0,还是可以点击到附件。
如果想做点击图片放大的话,这又是个难题。
#final,放弃方案一。
#方案二:回归添加换行(\n)
        /*
            1,取图片前一位,如果是图片,那么就不添加回车,如果不是图片,那么就添加回车。
            2,取前一位时注意图片是第一位的情况。
            3,经测试得到,一个回车是20的高度。如果有一个回车就在totalImageHeight的基础上添加20。
            4,注意属性字符要准备2份,一份用来展示(带回车),一份把图片替换为空(不带回车),因为totalImageHeight已经把回车的高度加上了。计算纯文本就可以了。
            5,替换文本后需要重新设置富文本属性,不然会恢复初始化状态,行高间距字体大小都没了。
            6,连续两张图片的算一个间距,所以这里要减去有多少个连续的图片,最后测试选择一个连续的两张图-10的间距。
            7,换行的模式选择NSLineBreakByCharWrapping,因为这样可以兼容到字母、数字。
               举例:paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
            8, 根据URL找到指定缓存(如果存在的话)
               UIImage* image = [[SDImageCache sharedImageCache] imageFromMemoryCacheForKey:url];
            9,插入图片原理:看SDWebImage中是否有缓存图片,有则把正则匹配的图片范围直接替换为图片,否则,先默认插入一个宽高均为SCREEN_WIDTH-25的附件,然后SDWebImage异步下载图,下载成功之后,判断找到对应的附件,替换,textView高度减去差值,重新添加到tableview的头部。
         
         */

14,系统UITextView可以开始识别手机号、网址等。
textView.delegate = self;
textView.dataDetectorTypes = UIDataDetectorTypeLink; //开启识别链接

UIDataDetectorTypePhoneNumber  :识别手机号
UIDataDetectorTypeLink  :识别链接
UIDataDetectorTypeAll  :识别所有


#点击链接会走这个方法
//链接委托(链接最好用一个括号括起来,或者在链接后面加个空格。)
- (BOOL)textView:(UITextView*)textView
    shouldInteractWithURL:(NSURL*)URL
                  inRange:(NSRange)characterRange
{
    NSLog(@"URL tap handle:%@", URL);

    return YES; //返回yes,点击链接的时候就会自动打开。
}

#点击附件会走这里的方法
/*
 附件委托新方法。
 返回YES,可以从下面弹出复制图片或保存图片,但是呢,不是很好看。
 */
- (BOOL)textView:(UITextView*)textView
    shouldInteractWithTextAttachment:(NSTextAttachment*)textAttachment
                             inRange:(NSRange)characterRange
                         interaction:(UITextItemInteraction)interaction
{
    //获取附件
    CustomTextAttachMent* attachment = (CustomTextAttachMent*)textAttachment;

    NSLog(@"%@", attachment.imgURL); //获取原图URL

#这里我使用HJPhotoBrowser做了点击图片放大的功能。
    self.clickImgURL = attachment.imgURL;
    self.clickImg = attachment.image;

    HJPhotoBrowser* photoBrowser = [HJPhotoBrowser new];
    photoBrowser.delegate = self;
    //    photoBrowser.currentImageIndex = indexPath.item;
    photoBrowser.imageCount = 1;
    photoBrowser.sourceImagesContainerView = self.view;

    [photoBrowser show];

    return NO;
}

15,UITextView实现左右点击效果

感觉两个手势就搞定了,待定(该博客还没看)

16,UITextView实现富文本
        /*
         1,取图片前一位,如果是图片,那么就不添加回车,如果不是图片,那么就添加回车。
         2,取前一位时注意图片是第一位的情况。
         3,经测试得到,一个回车是20的高度。如果有一个回车就在totalImageHeight的基础上添加20。
         4,注意属性字符要准备2份,一份用来展示(带回车),一份把图片替换为空(不带回车),因为totalImageHeight已经把回车的高度加上了。计算纯文本就可以了。
         5,替换文本后需要重新设置富文本属性,不然会恢复初始化状态,行高间距字体大小都没了。
         6,连续两张图片的算一个间距,所以这里要减去有多少个连续的图片,最后测试选择一个连续的两张图-10的间距。
         7,换行的模式选择NSLineBreakByCharWrapping,因为这样可以兼容到字母、数字。
         举例:paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
         8, 根据URL找到指定缓存(如果存在的话)
         UIImage* image = [[SDImageCache sharedImageCache] imageFromMemoryCacheForKey:url];
         9,插入图片原理:看SDWebImage中是否有缓存图片,有则把正则匹配的图片范围直接替换为图片,否则,先默认插入一个宽高均为SCREEN_WIDTH-25的附件,然后SDWebImage异步下载图,下载成功之后,判断找到对应的附件,替换,textView高度减去差值,重新添加到tableview的头部。
         
         10,注意替换SDWebImage下载完成的图片时,要重新创建一个CustomTextAttachMent,不然一张图的时候,第一次进入显示失败。
         */

你可能感兴趣的:(UITextView-使用集合)