Поместите файлы мультиплатформенных значков в ваш проект .NetStandard как Embedded Resources . Это означает, что я нашел все различные разрешения, предоставленные Google (_xxhdpi, _xhdpi, _hdpi, _mdpi и т. Д.), А затем переименовал их в следующее:
А затем поместите их в папку Resources / Google в моем проекте ( FormsFirebase.Ui ). Так, например, EmbeddedResourceId для первого файла в приведенном выше списке - FormsFirebase.Ui.Resources.Google.icon@¾x.png
.
Как вы вскоре увидите, переименование этих файлов, как показано выше, позволит Forms9Patch.Button
выбрать правильное изображение для правильного разрешения экрана (так, чтобы оно выглядело великолепно) - избавляя вас от необходимости управлять этим. Аналогично, включение их в проект .NetStandard означает, что они доступны для всех платформ - освобождая вас от необходимости разбираться с этим несколько раз!
В вашем Forms9Patch.Button
см. выше значок изображения в разрешении независимой моды. Это можно сделать несколькими способами. Один из более подробных способов:
var myButton = new Forms9Patch.Button
{
Text = "Sign in with xxhdpi",
TextColor=Color.White,
FontSize=14,
FontFamily="sans-serif",
WidthRequest=60,
IconImage = new Forms9Patch.Image
{
Source = Forms9Patch.ImageSource.FromMultiResource("FormsFirebase.Ui.Resources.Google.icon", GetType().Assembly),
Padding = 1,
},
Spacing = 4,
TintIcon = false,
BackgroundColor = Color.FromRGB(81,134,236)
};
Несколько замечаний:
Во-первых, я установил TintIcon
в false
, чтобы не подкрасил значок в тот же цвет, что и TextColor
. Также я установил IconImage
, а не BackgroundImage
. Это необходимо для того, чтобы убедиться, что изображение равноценно тексту, а не слою под ним.
Также обратите внимание, что я могу установить отступы IconImage
, а также Forms9Patch.Button.Padding
и Forms9Patch.Button.Spacing
(расстояние между IconImage
и [ 1113] или HtmlText
, в зависимости от того, было ли для HasTightSpacing
установлено значение true).
Вместо использования нескольких файлов .png
(для каждого разрешения экрана), если у вас есть .svg
версия вашего изображения, вы можете использовать ее вместо этого. Гораздо меньше работы!
Еще одна вещь, которая может вас заинтересовать: подобно тому, как Forms9Patch обрабатывает изображения независимо от платформы (помещая их в кроссплатформенный проект в качестве встроенных ресурсов), он может сделать то же самое со шрифтами. Это означает, что вы можете поместить файл шрифта (.ttf или .otf) в ваш кроссплатформенный проект и использовать его EmbeddedResourceId в качестве значения для FontFamily
. И это поведение может быть расширено до элементов Xamarin.Forms с помощью Forms9Patch.EmbeddedResourceFontEffect
.
Теперь немного прозелитизма (извините, если это не относится к вам): я вижу, что вы использовали XAML в качестве примера кода. Обратите внимание, что я не в своем ответе. Если вы новичок в .Net и / или Xamarin.Forms, я настоятельно рекомендую не использовать XAML. Не поймите меня неправильно, XAML великолепен - он просто не для начинающих. Зачем? Слишком много вещей происходит под одеялом, которые, как новичок, могут сбить вас с толку и замедлить. Скорее, я бы порекомендовал вам написать весь ваш пользовательский интерфейс на C #, чтобы вы могли научиться управлять своими свойствами и узнать, как на самом деле работает привязка. Как только вы освоите создание очень эффективных макетов с наилучшим «контекстно-зависимым» использованием связывания, тогда вы готовы к XAML. Для меня настоящим тестом была возможность сделать очень сложную разметку ячейки в большом списке в ListView плавно прокручивать на недорогом телефоне Android. После этого опыта я смог воспользоваться всеми преимуществами разработки на XAML (и их немало), не беспокоясь о том, что меня сковывают мои ошибки новичка.
I agree that using TreeViewAction.Unknown
in this case is less than desirable. Consider using the BeforeSelect
event, which provides an opportunity to prevent the AfterSelect
event.
Create a GotFocus
event handler that sets a flag. Then, create a BeforeSelect
event handler that, if the flag is set, cancels the event and clears the flag. For example:
private bool treeViewWasNewlyFocused = false;
private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if(treeViewWasNewlyFocused)
{
e.Cancel = true;
treeViewWasNewlyFocused = false;
}
}
private void TreeView1_GotFocus(object sender, EventArgs e)
{
treeViewWasNewlyFocused = true;
}
Мне пришлось решить ту же самую проблему (но на компактной платформе), когда событие BeforeSelect не отображается (я был сбит с толку).
Но думаю, получил довольно элегантное решение и надеюсь, что это поможет другим !!
Я создал производный элемент управления TreeView (чтобы можно было выбрать несколько элементов одновременно), но также исправлю «автоматический» выбор первого узла при получении FOCUS.
Затем я переопределил обработчики событий как таковые:
/// <summary>
/// //This actually occurs AFTER actual Treeview control:
/// - Got Focus in reality
/// - Executed the "innate" behaviour (like a button showing "depressed")
/// - The "innate and UNWANTED behaviour of the Treeview is to selected the first Node
/// when gets the focus.
///The key here is the Treeview executes in this order (when Tree Selected and didn't have focus):
/// - First the Node is selected (before OnGotFocus is executed)
/// Since when LostFocus "treeHasFocus" = false the OnAfterSelect handler isn't called!!
///
/// - Then the OnGotFocus is called:
/// This will set treeHasFocus to True and will not react to selections
/// </summary>
/// <param name="e"></param>
protected override void OnGotFocus(EventArgs e)
{
treeHasFocus = true;
//base.OnGotFocus(e);
}
/// <summary>
/// Alot easier to handle here (in Derived TreeView control then using all kinds of
/// -= events to try to prevent.
///
/// This was the cleanest way I could find (prevent firing of AfterSelect)
/// </summary>
/// <param name="e"></param>
protected override void OnLostFocus(EventArgs e)
{
treeHasFocus = false;
//base.OnLostFocus(e);
}
/// <summary>
/// - Treeview Control defaults to selecting the first node (when gets focus)
/// - We do NOT want this - since would automatically Highlight the first node (select)
/// - treeHasFocus is NOT true for the first unwanted "automatic" selection of the first item
/// - Upon loosing Focus, the AfterSelect handler is never called.
/// </summary>
/// <param name="e"></param>
protected override void OnAfterSelect(TreeViewEventArgs e)
{
if (treeHasFocus)
base.OnAfterSelect(e);
this.SelectedNode = null;
}