如何为 UILabel 指定日语编码?
How to specify Japanese encoding for a UILabel?
当我尝试在 iOS 上的 UILabel 中显示日文字符串时,它使用中文编码而不是日文显示。
这两种编码几乎相同,除了少数特定情况。例如,字符直 (Unicode U+76F4) 在中文(上)与日文(下)中的呈现方式如下:
(更多示例参见here)
只有当用户的系统区域设置为 ja-jp
(日本)时,日语字符串才能正确呈现,但我希望它在 all 中呈现为日语用户。
有没有办法强制使用日文编码? Android 有 TextView.TextLocale
,但我在 [=43= 上没有看到类似的东西] UILabel
(。我将此标记为 Swift/Objective-C,因为虽然我正在寻找 Xamarin.iOS 解决方案,但 API 几乎是相同)
我发现了一个非常 似乎有效的解决方案。然而,没有办法简单地设置标签的区域设置似乎很荒谬,所以如果有人发现我遗漏的东西,请 post 回答。
这个技巧依赖于 Hiragino
字体默认使用日文编码而不是中文编码显示汉字这一事实。但是,对于英文文本,字体看起来很糟糕,所以我必须在每个标签中的每个字符串中搜索日文子字符串,并使用 NSMutableAttributedString
手动更改字体。字体也是 所以我不得不找到另一个解决方法来解决这个问题。
[assembly: ExportRenderer(typeof(Label), typeof(RingotanLabelRenderer))]
namespace MyApp
{
public class MyLabelRenderer : LabelRenderer
{
private readonly UIFont HIRAGINO_FONT = UIFont.FromName("HiraginoSans-W6", 1); // Size gets updated later
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// BUGFIX: Chinese encoding is shown by default. Switch to Hiragino font, which correctly shows Japanese characters
// Taken from
if (Control?.Text != null && e.PropertyName == "Text")
{
var kanjiRanges = GetJapaneseRanges(Control.Text).ToList();
if (kanjiRanges.Count > 0)
{
var font = HIRAGINO_FONT.WithSize((nfloat)Element.FontSize);
var attributedString = Control.AttributedText == null
? new NSMutableAttributedString(Control.Text)
: new NSMutableAttributedString(Control.AttributedText);
// Search through string for all instances of Japanese characters and update the font
foreach (var (start, end) in kanjiRanges)
{
int length = end - start + 1;
var range = new NSRange(start, length);
attributedString.AddAttribute(UIStringAttributeKey.Font, font, range);
// Bugfix: Hiragino font is broken ( so needs to be adjusted upwards
// jesus christ Apple
attributedString.AddAttribute(UIStringAttributeKey.BaselineOffset, (NSNumber)(Element.FontSize/10), range);
}
Control.AttributedText = attributedString;
}
}
}
// Returns all (start,end) ranges in the string which contain only Japanese strings
private IEnumerable<(int,int)> GetJapaneseRanges(string str)
{
for (int i = 0; i < str.Length; i++)
{
if (IsJapanese(str[i]))
{
int start = i;
while (i < str.Length - 1 && KanjiHelper.IsJapanese(str[i]))
{
i++;
}
int end = i;
yield return (start, end);
}
}
}
private static bool IsJapanese(char character)
{
// An approximation. See https://github.com/caguiclajmg/WanaKanaSharp/blob/792f45a27d6e543d1b484d6825a9f22a803027fd/WanaKanaSharp/CharacterConstants.cs#L110-L118
// for a more accurate version
return character >= '\u3000' && character <= '\u9FFF'
|| character >= '\uFF00';
}
}
}
您只需要为属性字符串指定语言标识符,例如
let label = UILabel()
let text = NSAttributedString(string: "直", attributes: [
.languageIdentifier: "ja", // << this !!
.font: UIFont.systemFont(ofSize: 64)
])
label.attributedText = text
测试 Xcode 13.2 / iOS 15.2
当我尝试在 iOS 上的 UILabel 中显示日文字符串时,它使用中文编码而不是日文显示。
这两种编码几乎相同,除了少数特定情况。例如,字符直 (Unicode U+76F4) 在中文(上)与日文(下)中的呈现方式如下:
(更多示例参见here)
只有当用户的系统区域设置为 ja-jp
(日本)时,日语字符串才能正确呈现,但我希望它在 all 中呈现为日语用户。
有没有办法强制使用日文编码? Android 有 TextView.TextLocale
,但我在 [=43= 上没有看到类似的东西] UILabel
(
我发现了一个非常 似乎有效的解决方案。然而,没有办法简单地设置标签的区域设置似乎很荒谬,所以如果有人发现我遗漏的东西,请 post 回答。
这个技巧依赖于 Hiragino
字体默认使用日文编码而不是中文编码显示汉字这一事实。但是,对于英文文本,字体看起来很糟糕,所以我必须在每个标签中的每个字符串中搜索日文子字符串,并使用 NSMutableAttributedString
手动更改字体。字体也是
[assembly: ExportRenderer(typeof(Label), typeof(RingotanLabelRenderer))]
namespace MyApp
{
public class MyLabelRenderer : LabelRenderer
{
private readonly UIFont HIRAGINO_FONT = UIFont.FromName("HiraginoSans-W6", 1); // Size gets updated later
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// BUGFIX: Chinese encoding is shown by default. Switch to Hiragino font, which correctly shows Japanese characters
// Taken from
if (Control?.Text != null && e.PropertyName == "Text")
{
var kanjiRanges = GetJapaneseRanges(Control.Text).ToList();
if (kanjiRanges.Count > 0)
{
var font = HIRAGINO_FONT.WithSize((nfloat)Element.FontSize);
var attributedString = Control.AttributedText == null
? new NSMutableAttributedString(Control.Text)
: new NSMutableAttributedString(Control.AttributedText);
// Search through string for all instances of Japanese characters and update the font
foreach (var (start, end) in kanjiRanges)
{
int length = end - start + 1;
var range = new NSRange(start, length);
attributedString.AddAttribute(UIStringAttributeKey.Font, font, range);
// Bugfix: Hiragino font is broken ( so needs to be adjusted upwards
// jesus christ Apple
attributedString.AddAttribute(UIStringAttributeKey.BaselineOffset, (NSNumber)(Element.FontSize/10), range);
}
Control.AttributedText = attributedString;
}
}
}
// Returns all (start,end) ranges in the string which contain only Japanese strings
private IEnumerable<(int,int)> GetJapaneseRanges(string str)
{
for (int i = 0; i < str.Length; i++)
{
if (IsJapanese(str[i]))
{
int start = i;
while (i < str.Length - 1 && KanjiHelper.IsJapanese(str[i]))
{
i++;
}
int end = i;
yield return (start, end);
}
}
}
private static bool IsJapanese(char character)
{
// An approximation. See https://github.com/caguiclajmg/WanaKanaSharp/blob/792f45a27d6e543d1b484d6825a9f22a803027fd/WanaKanaSharp/CharacterConstants.cs#L110-L118
// for a more accurate version
return character >= '\u3000' && character <= '\u9FFF'
|| character >= '\uFF00';
}
}
}
您只需要为属性字符串指定语言标识符,例如
let label = UILabel()
let text = NSAttributedString(string: "直", attributes: [
.languageIdentifier: "ja", // << this !!
.font: UIFont.systemFont(ofSize: 64)
])
label.attributedText = text
测试 Xcode 13.2 / iOS 15.2