1.UITextView中#话题#功能的简单实现
我的实现借鉴了上述文章中的思路,根据项目中的要求进行了修改。
#import <Foundation/Foundation.h>
//附件到话题词上的信息
@interface LJTextViewBinding : NSObject
@property (nonatomic, strong) NSString *topicName;
@property (nonatomic, strong) NSNumber *topicId;
@property (nonatomic, strong) NSString *rangePosition;
-(instancetype)initWithTopicName:(NSString*)name topicId:(NSNumber*)tId;
@end
//插入话题
-(void)insertTopic:(NSString *)strDescription eventId:(NSNumber*)eId
{
NSInteger tmpWordCount = _maxWord-_textView.text.length;
if (strDescription.length > tmpWordCount)
{
return;
}
LJTextViewBinding *topicBinding = [[LJTextViewBinding alloc]initWithTopicName:strDescription topicId:eId];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = textlineSpacing;// 字体的行间距
NSAttributedString *topicAttributedString = [[NSAttributedString alloc] initWithString:strDescription
attributes: @{NSForegroundColorAttributeName : UIColorFromRGB(0x0bbe06),NSFontAttributeName : [UIFont systemFontOfSize:16], NSParagraphStyleAttributeName : paragraphStyle,LJTextBindingAttributeName:topicBinding}];
NSRange selectedRange = self.textView.selectedRange;
NSRange rangeTopic = NSMakeRange(selectedRange.location,strDescription.length);
NSMutableAttributedString *attributedString = self.textView.attributedText.mutableCopy;
if (self.isUserPutIn)//如果用户输入#号,然后选择话题列表,先要删除前面的#号
{
[attributedString deleteCharactersInRange:NSMakeRange(selectedRange.location-1, 1)];
selectedRange = NSMakeRange(selectedRange.location-1, selectedRange.length);
rangeTopic = NSMakeRange(rangeTopic.location-1,strDescription.length);
self.isUserPutIn = NO;
}
// 插入到当前选中位置.
[attributedString replaceCharactersInRange:selectedRange
withAttributedString:topicAttributedString];
// 设置富文本会导致 textView 的 font 变为另一种富文本默认字体,因此需要专门指定字体为原先字体.
[attributedString addAttribute:NSFontAttributeName
value:FONT(16)
range:(NSRange){0,attributedString.length}];
self.textView.attributedText = attributedString;
self.textView.selectedRange = NSMakeRange(selectedRange.location+strDescription.length, 0);
[_textView setTypingAttributes:textAttrDict];
[self textViewDidChange:_textView];
}
//得到用户输入的话题数组
- (NSArray *)getTopicRangeArray:(NSAttributedString *)attributedString {
NSAttributedString *traveAStr = attributedString ?: _textView.attributedText;
__block NSMutableArray *rangeArray = [NSMutableArray array];
[[self topicExpression] enumerateMatchesInString:traveAStr.string
options:0
range:NSMakeRange(0, traveAStr.string.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange resultRange = result.range;
NSDictionary *attributedDict = [traveAStr attributesAtIndex:resultRange.location effectiveRange:NULL];
if (attributedDict[QYPPTextBindingAttributeName])
{
LJTextViewBinding *binding = attributedDict[QYPPTextBindingAttributeName];
binding.rangePosition = NSStringFromRange(resultRange);
if (binding)
{
[rangeArray addObject:binding];
}
}
}];
return rangeArray;
}
- (void)textViewDidChangeSelection:(UITextView *)textView
{
NSArray *rangeArray = [self getTopicRangeArray:nil];
for (NSInteger i = 0; i < rangeArray.count; i++) {
LJTextViewBinding *binding = rangeArray[i];
NSRange range = NSRangeFromString(binding.rangePosition);
NSRange unionRange = NSUnionRange(textView.selectedRange, range);
NSRange intersectionRange = NSIntersectionRange(textView.selectedRange, range);
if (!(intersectionRange.location == 0 || intersectionRange.length < 1) && ![NSStringFromRange(intersectionRange)isEqualToString:NSStringFromRange(range)])
{
textView.selectedRange = unionRange;
break;
}
if (textView.selectedRange.location > range.location && textView.selectedRange.location < range.location + range.length) {
textView.selectedRange = range;
break;
}
}
}