将文本拟合為可用的大小
您可能需要将文本塊合并到特定的矩形區域。 可以計算一個值
對于Label的FontSize屬性,基于文本字元的數量,矩形區域的大小以及兩個數字。
第一個數字是行間距。 這是每行文本的标簽視圖的垂直高度。 對于與三個平台關聯的預設字型,它與FontSize屬性大緻相關,如下所示:
iOS: lineSpacing = 1.2 * label.FontSize
Android: lineSpacing = 1.2 * label.FontSize
Windows Phone: lineSpacing = 1.3 * label.FontSize
第二個有用的數字是平均字元寬度。 對于預設字型的大寫和小寫字母的正常混合,平均字元寬度約為字型大小的一半,與平台無關:
averageCharacterWidth = 0.5 * label.FontSize
例如,假設您想要包含寬度為320個機關的80個字元的文本字元串,并且希望字型大小盡可能大。 将寬度(320)除以字元數(40)的一半,即可得到8的字型大小,您可以将其設定為Label的FontSize屬性。 對于有些不确定且不能事先測試的文本,您可能希望使此計算更保守一點以避免意外。
以下程式使用行間距和平均字元寬度來适合頁面上的文本段落,減去狀态欄占用的iPhone頂部區域。 為了在此程式中排除iOS狀态欄,該程式使用ContentView。
ContentView派生自布局,但僅将Content屬性添加到從布局繼承的内容屬性。 ContentView也是Frame的基類。 盡管ContentView除了占用矩形空間區域之外沒有其他功能,但它有兩個用途:大多數情況下,ContentView可以是其他視圖的父級,以定義新的自定義視圖。 但是ContentView也可以模拟邊距。
正如您可能已經注意到的那樣,Xamarin.Forms沒有保證金的概念,傳統上它與填充相似,不同之處在于填充位于視圖和視圖的一部分内,而保證位于視圖之外,實際上是父視圖的一部分。 ContentView讓我們模拟這個。 如果您發現需要在視圖上設定邊距,請将該視圖置于ContentView中,并将該Padding屬性設定在ContentView上。 ContentView從Layout繼承Padding屬性。
EstimatedFontSize程式以稍微不同的方式使用ContentView:它在頁面上設定慣用的填充以避免iOS狀态欄,但随後将ContentView設定為該頁面的内容。 是以,此ContentView與頁面的大小相同,但不包括iOS狀态欄。 正是在此ContentView上附加了SizeChanged事件,并且這是用于計算文本字型大小的此ContentView的大小。
SizeChanged處理程式使用第一個參數來擷取觸發事件的對象(本例中為ContentView),該對象是Label必須适合的對象。 計算在評論中描述:
public class EstimatedFontSizePage : ContentPage
{
Label label;
public EstimatedFontSizePage()
{
label = new Label();
Padding = new Thickness(0,Device.OnPlatform(20, 0, 0), 0, 0);
ContentView contentView = new ContentView
{
Content = label
};
contentView.SizeChanged += OnContentViewSizeChanged;
Content = contentView;
}
void OnContentViewSizeChanged(object sender, EventArgs args)
{
string text =
"A default system font with a font size of S " +
"has a line height of about ({0:F1} * S) and an " +
"average character width of about ({1:F1} * S). " +
"On this page, which has a width of {2:F0} and a " +
"height of {3:F0}, a font size of ?1 should " +
"comfortably render the ??2 characters in this " +
"paragraph with ?3 lines and about ?4 characters " +
"per line. Does it work?";
// Get View whose size is changing.
View view = (View)sender;
// Define two values as multiples of font size.
double lineHeight = Device.OnPlatform(1.2, 1.2, 1.3);
double charWidth = 0.5;
// Format the text and get its character length.
text = String.Format(text, lineHeight, charWidth, view.Width, view.Height);
int charCount = text.Length;
// Because:
// lineCount = view.Height / (lineHeight * fontSize)
// charsPerLine = view.Width / (charWidth * fontSize)
// charCount = lineCount * charsPerLine
// Hence, solving for fontSize:
int fontSize = (int)Math.Sqrt(view.Width * view.Height /
(charCount * lineHeight * charWidth));
// Now these values can be calculated.
int lineCount = (int)(view.Height / (lineHeight * fontSize));
int charsPerLine = (int)(view.Width / (charWidth * fontSize));
// Replace the placeholders with the values.
text = text.Replace("?1", fontSize.ToString());
text = text.Replace("??2", charCount.ToString());
text = text.Replace("?3", lineCount.ToString());
text = text.Replace("?4", charsPerLine.ToString());
// Set the Label properties.
label.Text = text;
label.FontSize = fontSize;
}
}
名為“?1”,“?? 2”,“?3”和“?4”的文本占位符被選擇為唯一的,但其字元數與替換它們的數字相同。
如果目标是使文本盡可能大而文本不會溢出頁面,則結果将驗證該方法:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL3UjNwQTNiNGZiRjZxgjYkhTNkNmMzQTOxIDZjNGMjZWMlNzYlZ2Mi9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
不錯。 一點也不差。 文本實際上顯示在所有三個平台上顯示的少一行中,但該技術看起來很合理。 并非總是為橫向模式計算相同的FontSize,但有時會發生這種情況: