koogawa blog

iOS、Android、foursquareに関する話題

UITextViewに画像を埋め込んでテキストを回り込ませる

iOS 7から追加されたText Kitの機能を使ってUITextViewに画像を埋め込み、テキストを回り込ませる方法をメモしておきます。

ここでは例として、次のようなテキストに画像を埋め込むことを考えてみます。

f:id:koogawa:20131223194851p:plain

1.非表示領域を設定

このテキストの上に何も考えずに画像を配置すると、次のようになると思います。

f:id:koogawa:20131223194909p:plain

そこで、まずは非表示領域(テキストを表示しない領域)を設定します。

非表示領域を設定するにはText Kitのメイン機能である NSTextContainerexclusionPaths プロパティを使います。このプロパティに UIBezierPath 型で領域を指定すれば、その領域が非表示領域になります。

まずは四角形でやってみます。

// UITextViewに埋め込む画像
UIImage *image = [UIImage imageNamed:@"Star"];

// 非表示領域を設定(四角形)
CGRect exclusionRect =
    CGRectMake(40, 30, image.size.width, image.size.height);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:exclusionRect];

// テキストビューに設定
self.textView.textContainer.exclusionPaths = @[path];

この状態でプログラムを実行してみると次のようになります。

f:id:koogawa:20131223194930p:plain

2.画像を追加

次は非表示領域に画像を埋め込みます。

UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = exclusionRect;
[self.textView addSubview:imageView];

f:id:koogawa:20131223194946p:plain

これで UITextView に画像を埋め込み、テキストを回り込ませることができました。

非表示領域を星形にしてみる

非表示領域は UIBezierPath で指定することからもわかるように、四角形である必要はありません。ここではせっかくなので、画像に合わせて星形にしてみましょう。

// 非表示領域を設定(星形)
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(160.0, 30.0)];
[path addLineToPoint:CGPointMake(210.0, 100.0)];
[path addLineToPoint:CGPointMake(280.0, 120.0)];
[path addLineToPoint:CGPointMake(230.0, 180.0)];
[path addLineToPoint:CGPointMake(240.0, 265.0)];
[path addLineToPoint:CGPointMake(160.0, 230.0)];
[path addLineToPoint:CGPointMake(95.0 , 270.0)];
[path addLineToPoint:CGPointMake(100.0, 180.0)];
[path addLineToPoint:CGPointMake(40.0 , 120.0)];
[path addLineToPoint:CGPointMake(125.0, 105.0)];
[path closePath];

f:id:koogawa:20131223194959p:plain

これでキレイに画像にテキストが回り込むようになりました。

サンプルソース

Text Kitについては、先日発売されたこちらの書籍でかなり詳しく解説されています。