Blu*_*eft 6 objective-c uilabel xamarin.ios xamarin.forms swift
当我尝试在 iOS 上的 UILabel 中显示日语字符串时,它会使用中文编码而不是日语显示。
\n除了少数特定情况外,这两种编码几乎相同。例如,以下是字符 \xe7\x9b\xb4 (Unicode U+76F4) 在中文(上)与日文(下)中的呈现方式:
\n\n(请参阅此处了解更多示例)
\n日语字符串正确呈现的唯一时间是当用户的系统区域设置为ja-jp(日本)时,但我希望它为所有用户呈现为日语。
有没有办法强制日语编码? Android 有TextView.TextLocale,但我在 iOS 上没有看到类似的东西UILabel
(对于 Android 也是同样的问题。我标记了这个 Swift/Objective-C,因为虽然我正在寻找 Xamarin.iOS 解决方案,但 API 几乎是相同的)
\n我发现了一个看起来非常有效的解决方案。然而,没有办法简单地设置标签的区域设置似乎很荒谬,所以如果有人发现我错过的东西,请发布答案。
这个技巧依赖于这样一个事实: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 /sf/answers/4973164311/
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 (/sf/answers/3107830071/) 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';
}
}
}
Run Code Online (Sandbox Code Playgroud)