eri*_*yue 6 objective-c uitextview ios
我只是想创建一个像这样的UITextView(不是两个textviews,空白区域是一个uiimage)

rob*_*off 15
没有内置的UIView子类可以执行此操作(除非UIWebView您编写正确的HTML和CSS),但使用Core Text很容易.我把我的测试项目放在我的ShapedLabel github存储库中,这就是它的样子:

该项目有一个UIView名为的子类ShapedLabel.这是它的工作原理.
创建一个UIView名为的子类ShapedLabel.给它这些属性:
@property (nonatomic, copy) NSString *text;
@property (nonatomic) UITextAlignment textAlignment;
@property (nonatomic, copy) NSString *fontName;
@property (nonatomic) CGFloat fontSize;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) UIColor *shapeColor;
@property (nonatomic, copy) UIBezierPath *path;
Run Code Online (Sandbox Code Playgroud)
您将要覆盖要发送的每个属性setter方法setNeedsDisplay,例如:
- (void)setFontName:(NSString *)fontName {
_fontName = [fontName copy];
[self setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
我依靠ARC担心释放旧的价值_fontName.如果您不使用ARC ...开始.它非常简单,自iOS 4.0起就得到了支持.
无论如何,那么你需要实现drawRect:,真正的工作完成.首先,我们将使用shapeColorif设置填写形状:
- (void)drawRect:(CGRect)rect
{
if (!_path)
return;
if (_shapeColor) {
[_shapeColor setFill];
[_path fill];
}
Run Code Online (Sandbox Code Playgroud)
我们检查以确保我们拥有所需的所有其他参数:
if (!_text || !_textColor || !_fontName || _fontSize <= 0)
return;
Run Code Online (Sandbox Code Playgroud)
接下来我们处理该textAligment属性:
CTTextAlignment textAlignment = NO ? 0
: _textAlignment == UITextAlignmentCenter ? kCTCenterTextAlignment
: _textAlignment == UITextAlignmentRight ? kCTRightTextAlignment
: kCTLeftTextAlignment;
CTParagraphStyleSetting paragraphStyleSettings[] = {
{
.spec = kCTParagraphStyleSpecifierAlignment,
.valueSize = sizeof textAlignment,
.value = &textAlignment
}
};
CTParagraphStyleRef style = CTParagraphStyleCreate(paragraphStyleSettings, sizeof paragraphStyleSettings / sizeof *paragraphStyleSettings);
Run Code Online (Sandbox Code Playgroud)
我们创造CTFont下一个.请注意,这与a CGFont或a 不同UIFont.您可以将a转换CGFont为CTFont使用CTFontCreateWithGraphicsFont,但不能轻易地将a转换UIFont为a CTFont.无论如何我们只是CTFont直接创建:
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)_fontName, _fontSize, NULL);
Run Code Online (Sandbox Code Playgroud)
我们创建属性字典,定义我们想要看到的所有样式属性:
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)font, kCTFontAttributeName,
_textColor.CGColor, kCTForegroundColorAttributeName,
style, kCTParagraphStyleAttributeName,
nil];
CFRelease(font);
CFRelease(style);
Run Code Online (Sandbox Code Playgroud)
一旦我们有了属性字典,我们就可以创建将属性字典附加到文本字符串的属性字符串.这是Core Text使用的:
CFAttributedStringRef trib = CFAttributedStringCreate(NULL, (__bridge CFStringRef)_text, (__bridge CFDictionaryRef)attributes);
Run Code Online (Sandbox Code Playgroud)
我们创建了一个Core Text framesetter,它将从属性字符串中布置文本:
CTFramesetterRef setter = CTFramesetterCreateWithAttributedString(trib);
CFRelease(trib);
Run Code Online (Sandbox Code Playgroud)
Core Text假定图形上下文将具有"标准"Core Graphics坐标系,其原点位于左下角.但是UIKit改变了上下文以将原点放在左上角.我们假设路径是在考虑到这一点的情况下创建的.所以我们需要一个垂直翻转坐标系的变换:
// Core Text lays out text using the default Core Graphics coordinate system, with the origin at the lower left. We need to compensate for that, both when laying out the text and when drawing it.
CGAffineTransform textMatrix = CGAffineTransformIdentity;
textMatrix = CGAffineTransformTranslate(textMatrix, 0, self.bounds.size.height);
textMatrix = CGAffineTransformScale(textMatrix, 1, -1);
Run Code Online (Sandbox Code Playgroud)
然后我们可以创建路径的翻转副本:
CGPathRef flippedPath = CGPathCreateCopyByTransformingPath(_path.CGPath, &textMatrix);
Run Code Online (Sandbox Code Playgroud)
最后,我们可以要求框架设置一个文本框架.这实际上适合path属性定义的形状内的文本:
CTFrameRef frame = CTFramesetterCreateFrame(setter, CFRangeMake(0, 0), flippedPath, NULL);
CFRelease(flippedPath);
CFRelease(setter);
Run Code Online (Sandbox Code Playgroud)
最后我们绘制文本.我们需要再次
CGContextRef gc = UIGraphicsGetCurrentContext();
CGContextSaveGState(gc); {
CGContextConcatCTM(gc, textMatrix);
CTFrameDraw(frame, gc);
} CGContextRestoreGState(gc);
CFRelease(frame);
}
Run Code Online (Sandbox Code Playgroud)
这就是它.您现在可以在屏幕上放置一个漂亮的形状标签.
对于后代(如果我删除测试项目),这里是ShapedLabel该类的完整源代码.
#import <UIKit/UIKit.h>
@interface ShapedLabel : UIView
@property (nonatomic, copy) NSString *text;
@property (nonatomic) UITextAlignment textAlignment;
@property (nonatomic, copy) NSString *fontName;
@property (nonatomic) CGFloat fontSize;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) UIColor *shapeColor;
@property (nonatomic, copy) UIBezierPath *path;
@end
Run Code Online (Sandbox Code Playgroud)
#import "ShapedLabel.h"
#import <CoreText/CoreText.h>
@implementation ShapedLabel
@synthesize fontName = _fontName;
@synthesize fontSize = _fontSize;
@synthesize path = _path;
@synthesize text = _text;
@synthesize textColor = _textColor;
@synthesize shapeColor = _shapeColor;
@synthesize textAlignment = _textAlignment;
- (void)commonInit {
_text = @"";
_fontSize = UIFont.systemFontSize;
// There is no API for just getting the system font name, grr...
UIFont *uiFont = [UIFont systemFontOfSize:_fontSize];
_fontName = [uiFont.fontName copy];
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)setFontName:(NSString *)fontName {
_fontName = [fontName copy];
[self setNeedsDisplay];
}
- (void)setFontSize:(CGFloat)fontSize {
_fontSize = fontSize;
[self setNeedsDisplay];
}
- (void)setPath:(UIBezierPath *)path {
_path = [path copy];
[self setNeedsDisplay];
}
- (void)setText:(NSString *)text {
_text = [text copy];
[self setNeedsDisplay];
}
- (void)setTextColor:(UIColor *)textColor {
_textColor = textColor;
[self setNeedsDisplay];
}
- (void)setTextAlignment:(UITextAlignment)textAlignment {
_textAlignment = textAlignment;
[self setNeedsDisplay];
}
- (void)setShapeColor:(UIColor *)shapeColor {
_shapeColor = shapeColor;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
if (!_path)
return;
if (_shapeColor) {
[_shapeColor setFill];
[_path fill];
}
if (!_text || !_textColor || !_fontName || _fontSize <= 0)
return;
CTTextAlignment textAlignment = NO ? 0
: _textAlignment == UITextAlignmentCenter ? kCTCenterTextAlignment
: _textAlignment == UITextAlignmentRight ? kCTRightTextAlignment
: kCTLeftTextAlignment;
CTParagraphStyleSetting paragraphStyleSettings[] = {
{
.spec = kCTParagraphStyleSpecifierAlignment,
.valueSize = sizeof textAlignment,
.value = &textAlignment
}
};
CTParagraphStyleRef style = CTParagraphStyleCreate(paragraphStyleSettings, sizeof paragraphStyleSettings / sizeof *paragraphStyleSettings);
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)_fontName, _fontSize, NULL);
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)font, kCTFontAttributeName,
_textColor.CGColor, kCTForegroundColorAttributeName,
style, kCTParagraphStyleAttributeName,
nil];
CFRelease(font);
CFRelease(style);
CFAttributedStringRef trib = CFAttributedStringCreate(NULL, (__bridge CFStringRef)_text, (__bridge CFDictionaryRef)attributes);
CTFramesetterRef setter = CTFramesetterCreateWithAttributedString(trib);
CFRelease(trib);
// Core Text lays out text using the default Core Graphics coordinate system, with the origin at the lower left. We need to compensate for that, both when laying out the text and when drawing it.
CGAffineTransform textMatrix = CGAffineTransformIdentity;
textMatrix = CGAffineTransformTranslate(textMatrix, 0, self.bounds.size.height);
textMatrix = CGAffineTransformScale(textMatrix, 1, -1);
CGPathRef flippedPath = CGPathCreateCopyByTransformingPath(_path.CGPath, &textMatrix);
CTFrameRef frame = CTFramesetterCreateFrame(setter, CFRangeMake(0, 0), flippedPath, NULL);
CFRelease(flippedPath);
CFRelease(setter);
CGContextRef gc = UIGraphicsGetCurrentContext();
CGContextSaveGState(gc); {
CGContextConcatCTM(gc, textMatrix);
CTFrameDraw(frame, gc);
} CGContextRestoreGState(gc);
CFRelease(frame);
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1800 次 |
| 最近记录: |