UITextView高级用法
2014-11-17 18:58
169 查看
目前有三个需求,1.给每个字体加边框;2.随着文字的内容的变化改变控件大小;3点击单词能够识别出该单词。
其实要实现这三个功能已经不是上层API能做的事情了,这时候你要理解清楚UITextView的整个实现过程,才有可能找到解决方案。
a.苹果Text Kit Framework
从上面可以看出UITextVIew在框架中的位置,实际上它继承了UIScrollView。
从上面可以看出UITextVIew内部是怎么实现文字显示和排版布局的。具体的实现可以看这篇文章:https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html
b.给每个字体加边框
其实这个效果的实现思路就是给每个字加上一个背景,那么怎么给每个字后面加一个黑色的,比原来稍微大一些的字呢?
我原来的想法是用另外一个UITextView去实现这个功能,后来我分析这个方案是有可能失败的,因为你放大字体,那么就有可能导致排版和原来不一样,那么这个方案就失去了意义,因为编程就必须考虑代码的健壮性。
后来就在网上寻找怎么去画一个字?最后的代码像是这样的:
-(void)drawRect:(CGRect)rect{ NSMutableDictionary
*attributes = [[NSMutableDictionaryalloc]init];
[attributessetObject:self.fontforKey:NSFontAttributeName];
[attributessetObject:[NSNumbernumberWithFloat:8]forKey:NSStrokeWidthAttributeName];
[attributessetObject:[UIColorblackColor]forKey:NSStrokeColorAttributeName]; NSMutableParagraphStyle
*paragraphStyle = [[NSMutableParagraphStylealloc]init];
paragraphStyle.alignment =self.textAlignment;
[attributessetObject:paragraphStyleforKey:NSParagraphStyleAttributeName]; if
(self.text.length
!= 0) { CGPoint point = [self.layoutManagerlocationForGlyphAtIndex:0]; if
(self.textAlignment ==NSTextAlignmentLeft)
{ rect.origin.x = point.x;
} rect.origin.y =9;
} [self.textdrawInRect:rectwithAttributes:attributes];
[selfsetNeedsDisplay]; }
c.随着文字的内容的变化改变控件大小;
这个在ios8下面实在没有什么好的实现方案,无论是去寻找字体大小和行数还是scrollView.contentSize都不够准确,后来想一下这个页面布局可能是UIView负责做的事情,后来发现UIView有两个方法已经实现了这个功能:
- (CGSize)sizeThatFits:(CGSize)size; //
return 'best' size to fit given size. does not actually resize view. Default is return existing view size - (void)sizeToFit;
// calls sizeThatFits: with current view bounds and changes bounds size.
d.点击单词能够识别出该单词
很明显这个涉及到每个字符的位置,只要找到了单词的位置和你点击屏幕的位置,就能找到点击的单词。
通过上面的分析,我们发现UITextView对于文字的布局,有一个叫做NSLayoutManager的类,其中有这么一个方法:
CGFloat fraction =0; NSInteger
characterIndex = [textView.layoutManager characterIndexForPoint:locationinTextContainer:textView.textContainerfractionOfDistanceBetweenInsertionPoints:&fraction];
获取你点击位置的字符index,fraction如果是大于0并且小于1,就说明你点击的就是这个字符,没有超出范围,知道了字符的位置,后面判断是否为单词就很简单的。
e.总结
通过对UITextView的操作发现当你的需求增多的时候,你必须了解整个框架,而不是仅仅调用几个系统的API,你需要知道你的需求在系统的哪个层次上面。
“双语播放器”已在app store上架,欢迎大家前去下载(主要用于看电影,学英语,程序员一定要学好英语!)
这里是链接:
https://itunes.apple.com/cn/app/shuang-yu-bo-fang-qi-kan-dian/id950279764?mt=8
其实要实现这三个功能已经不是上层API能做的事情了,这时候你要理解清楚UITextView的整个实现过程,才有可能找到解决方案。
a.苹果Text Kit Framework
从上面可以看出UITextVIew在框架中的位置,实际上它继承了UIScrollView。
从上面可以看出UITextVIew内部是怎么实现文字显示和排版布局的。具体的实现可以看这篇文章:https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html
b.给每个字体加边框
其实这个效果的实现思路就是给每个字加上一个背景,那么怎么给每个字后面加一个黑色的,比原来稍微大一些的字呢?
我原来的想法是用另外一个UITextView去实现这个功能,后来我分析这个方案是有可能失败的,因为你放大字体,那么就有可能导致排版和原来不一样,那么这个方案就失去了意义,因为编程就必须考虑代码的健壮性。
后来就在网上寻找怎么去画一个字?最后的代码像是这样的:
-(void)drawRect:(CGRect)rect{ NSMutableDictionary
*attributes = [[NSMutableDictionaryalloc]init];
[attributessetObject:self.fontforKey:NSFontAttributeName];
[attributessetObject:[NSNumbernumberWithFloat:8]forKey:NSStrokeWidthAttributeName];
[attributessetObject:[UIColorblackColor]forKey:NSStrokeColorAttributeName]; NSMutableParagraphStyle
*paragraphStyle = [[NSMutableParagraphStylealloc]init];
paragraphStyle.alignment =self.textAlignment;
[attributessetObject:paragraphStyleforKey:NSParagraphStyleAttributeName]; if
(self.text.length
!= 0) { CGPoint point = [self.layoutManagerlocationForGlyphAtIndex:0]; if
(self.textAlignment ==NSTextAlignmentLeft)
{ rect.origin.x = point.x;
} rect.origin.y =9;
} [self.textdrawInRect:rectwithAttributes:attributes];
[selfsetNeedsDisplay]; }
c.随着文字的内容的变化改变控件大小;
这个在ios8下面实在没有什么好的实现方案,无论是去寻找字体大小和行数还是scrollView.contentSize都不够准确,后来想一下这个页面布局可能是UIView负责做的事情,后来发现UIView有两个方法已经实现了这个功能:
- (CGSize)sizeThatFits:(CGSize)size; //
return 'best' size to fit given size. does not actually resize view. Default is return existing view size - (void)sizeToFit;
// calls sizeThatFits: with current view bounds and changes bounds size.
d.点击单词能够识别出该单词
很明显这个涉及到每个字符的位置,只要找到了单词的位置和你点击屏幕的位置,就能找到点击的单词。
通过上面的分析,我们发现UITextView对于文字的布局,有一个叫做NSLayoutManager的类,其中有这么一个方法:
CGFloat fraction =0; NSInteger
characterIndex = [textView.layoutManager characterIndexForPoint:locationinTextContainer:textView.textContainerfractionOfDistanceBetweenInsertionPoints:&fraction];
获取你点击位置的字符index,fraction如果是大于0并且小于1,就说明你点击的就是这个字符,没有超出范围,知道了字符的位置,后面判断是否为单词就很简单的。
e.总结
通过对UITextView的操作发现当你的需求增多的时候,你必须了解整个框架,而不是仅仅调用几个系统的API,你需要知道你的需求在系统的哪个层次上面。
“双语播放器”已在app store上架,欢迎大家前去下载(主要用于看电影,学英语,程序员一定要学好英语!)
这里是链接:
https://itunes.apple.com/cn/app/shuang-yu-bo-fang-qi-kan-dian/id950279764?mt=8
相关文章推荐
- ImageMagick高级用法
- 细说 ASP.NET Cache 及其高级用法
- shell高级用法--函数
- GDB高级用法
- Scanf系列函数的高级用法
- C语言 宏的高级用法
- new 高级用法
- Nmap高级用法与典型场景目录
- Android高级之xUtils框架(四):DBUtils的用法
- 07 python中变量高级用法
- ViewPager高级用法大全
- 细说 ASP.NET Cache 及其高级用法
- C++_std::bind std::function 高级用法
- Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
- 再谈Newtonsoft.Json高级用法
- Newtonsoft.Json高级用法
- fw:sed的高级用法
- ORM对象关系映射之GreenDAO高级用法
- 12.2 剪贴板的高级用法
- Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法