在iOS UITextView中的Kerning [英] Kerning in iOS UITextView

查看:350
本文介绍了在iOS UITextView中的Kerning的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于显然是一个bug,UITextView似乎不支持kerning像其他UIKit元素。是否有解决方法,以获得字距调整的工作?



要说清楚,我说的字体文件中定义的字符之间的间距,而不是所有字符之间的一般间距。使用 NSAttributedString NSKernAttributeName 将调整所有字符之间的间距,但内置字符对仍然不工作。



例如:





有解决方法吗? b
$ b

一个简单的解决方法我发现是添加css样式到UITextView使能kerning。如果我使用非文档化的方法 setContentToHTMLString:我可以注入css到文本视图中的秘密web视图。

  NSString * css = @* {text-rendering:optimizeLegibility;}; 
NSString * html = [NSString stringWithFormat:@< html>< head>< style>%@< / style>< / head>< body& ; / html>,css];
[textView performSelector:@selector(setContentToHTMLString :) withObject:html];

这会立即解决问题;然而,这似乎很可能会得到应用程序被拒绝。有没有一个安全的方法来偷偷摸摸一些CSS到文本视图?



其他解决方法我已经实验包括:



使用webview和contenteditable属性。这不是理想的,因为webview有一堆额外的东西,例如输入附件视图,不能轻易隐藏。



子类化 UITextView 并使用核心文本手动呈现文本。这比我希望的更复杂,因为所有的选择东西需要重新配置。因为 UITextView 的私有子类 UITextPosition UITextRange

解决方案

你是对的,你的应用程序可能会被拒绝使用 @selector(setContentToHTMLString:)

  NSString * css = 

@* {text-rendering:optimizeLegibility;};
NSString * html = [NSString stringWithFormat:@< html>< head>< style>%@< / style>< / head>< body& ; / html>,css];
@try {
SEL setContentToHTMLString = NSSelectorFromString([@ [@set,@Content,@To,@HTML,@String,@:] componentsJoinedByString :@]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored-Warc-performSelector-leaks
[textView performSelector:setContentToHTMLString withObject:html];
#pragma clang诊断pop
}
@catch(NSException * exception){
// html + css不能应用于文本视图,所以没有kerning
}

通过将调用包装在@ try / @ catch块中,如果在未来版本的iOS中删除 setContentToHTMLString:方法,则不会崩溃。



使用私有API通常不会推荐,但在这种情况下,我认为使用一个小的黑客vs用CoreText重写UITextView是完全有道理的。


For what apparently is a 'bug,' UITextView does not seem to support kerning like other UIKit Elements. Is there a workaround to get kerning working?

To be clear, I'm talking about the spacing in between pairs of characters that are defined in the font file, not the general spacing between all characters. Using an NSAttributedString with the NSKernAttributeName will adjust the spacing between all characters, but the built in character pairs still don't work.

For Example:

Is there a workaround to fix this?

One simple workaround I have discovered is to add css styles to the UITextView which enable kerning. If I use the undocumented method setContentToHTMLString: I can inject the css to the secret webview within the text view.

NSString *css = @"*{text-rendering: optimizeLegibility;}";
NSString *html = [NSString stringWithFormat:@"<html><head><style>%@</style></head><body>Your HTML Text</body></html>", css];
[textView performSelector:@selector(setContentToHTMLString:) withObject:html];

This fixes the problem immediately; however, it seems very likely this will get the app rejected. Is there a safe way to sneak some css into the text view?

Other workarounds I have experimented with include:

Using a webview and the contenteditable property. This isn't ideal because webview does a bunch of extra stuff that gets in the way, for example the input accessory view which can't easily be hidden.

Subclassing a UITextView and rendering text manually with core text. This is more complex than I'd hoped because all the selections stuff needs to be reconfigured as well. Because of UITextView's private subclasses of UITextPosition and UITextRange this is a huge pain in the ass if not completely impossible.

解决方案

You are right that your app would probably be rejected by using @selector(setContentToHTMLString:). You can however use a simple trick to construct the selector dynamically so that it will not be detected during validation.

NSString *css = @"*{text-rendering: optimizeLegibility;}";
NSString *html = [NSString stringWithFormat:@"<html><head><style>%@</style></head><body>Your HTML Text</body></html>", css];
@try {
    SEL setContentToHTMLString = NSSelectorFromString([@[@"set", @"Content", @"To", @"HTML", @"String", @":"] componentsJoinedByString:@""]);
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [textView performSelector:setContentToHTMLString withObject:html];
    #pragma clang diagnostic pop
}
@catch (NSException *exception) {
    // html+css could not be applied to text view, so no kerning
}

By wrapping the call inside a @try/@catch block, you also ensure that your app will not crash if the setContentToHTMLString: method is removed in a future version of iOS.

Using private APIs is generally not recommended, but in this case I think it totally makes sense to use a small hack vs rewriting UITextView with CoreText.

这篇关于在iOS UITextView中的Kerning的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆