Я хочу, чтобы мое приложение Xamarin.Forms отображало значок и текст на вкладках. Я могу отображать значки FontAwesome с помощью TabbedRenderer, но значок и текст слишком близки друг к другу. Вот как это выглядит:
Другие раньше хотели добавить пространство между иконкой и текстом. Я понял, как визуализировать CustomView для содержимого вкладки с помощью TabbedRenderer, но я не могу получить желаемый результат. Ответов здесь недостаточно (многословные не обработанные тексты и т. д.). Ответ здесь от Маюреш Дешмукх звучит хорошо, но когда я пытаюсь создать представление со свойством app:tabInlineLabel, я получаю сообщение об ошибке, префикс пространства имен «приложение» не разрешается. Если бы я мог пройти мимо этого, я бы попытался настроить CustomView ActionBar на использование тега TabLayout, подобного тому, который включен в сообщение.
Я хотел бы, чтобы у меня был способ увидеть макет, который отображается по умолчанию в коде, чтобы я мог просто настроить его, чтобы добавить небольшое левое поле или отступ к тексту, поскольку, кроме недостатка места, он выглядит великолепно.
Я хочу, чтобы ширина вкладок увеличивалась по мере необходимости, чтобы соответствовать полному тексту, с горизонтальной прокруткой, если это необходимо. Некоторый перенос длинных текстов на 2-ю строку, как это иногда происходит по умолчанию, был бы в порядке, если бы интервал работал, но это необязательно - вот лучшая версия с переносом, которую я мог придумать... обрезано, поэтому непригодно для использования:
Из этого кода представления:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:id="@+id/nav_icon"
android:contentDescription=""
android:layout_marginBottom="5px"
android:layout_marginTop="5px"
android:layout_weight="3"
/>
<TextView
android:id="@+id/nav_label"
android:shadowColor="@android:color/black"
android:paddingLeft="5px"
android:layout_marginBottom="5px"
android:layout_marginTop="5px"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:textColor="@android:color/white"
/>
</LinearLayout>
Вот версия, в которой текст не переносится... но вкладка не расширяется, чтобы соответствовать тексту:
И код представления, который производит это:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:gravity="center_vertical"
android:id="@+id/nav_icon"
android:contentDescription=""
android:paddingBottom="5px"
android:paddingTop="5px"
android:layout_marginTop="15px"
/>
<TextView
android:id="@+id/nav_label"
android:shadowColor="@android:color/black"
android:paddingLeft="15px"
android:paddingBottom="5px"
android:paddingTop="20px"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:singleLine="true"
android:textAllCaps="true"
/>
</LinearLayout>
Это мой Android TabbedPageRenderer (который, я думаю, работает нормально — это макет, который, по моему мнению, нуждается в исправлении (я играл с жестко запрограммированным текстом, поэтому он не одинаков на всех моих скриншотах здесь, но в остальном это согласуется между скриншоты):
using System.Linq;
using Android.App;
using Android.Content;
using Android.Views;
using Android.Widget;
using Origami.MobileForms.Droid.Renderers;
using Origami.MobileForms.Droid.Utility;
using Origami.MobileForms.Pages;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(FormTabbedPage), typeof(ExtendedTabbedPageRenderer))]
namespace Origami.MobileForms.Droid.Renderers
{
public static class DebugViewContents
{
public static void DebugLayout(this Android.Views.View self, int indent = 0)
{
// write info about me first
var indents = new string('\t', indent);
System.Diagnostics.Debug.WriteLine(indents + self.GetType().Name);
// check if I'm a view group
var vg = self as ViewGroup;
if (vg == null) return;
// enumerate my children
var children = Enumerable.Range(0, vg.ChildCount).Select(x => vg.GetChildAt(x));
// recurse on each child
foreach (var child in children)
DebugLayout(child, indent + 1);
}
}
public class ExtendedTabbedPageRenderer : TabbedRenderer
{
public ExtendedTabbedPageRenderer(Context context) : base(context) { }
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
{
Activity activity = this.Context as Activity;
if (activity.ActionBar.TabCount > 0)
{
SetTabIcons();
}
base.DispatchDraw(canvas);
}
private void SetTabIcons()
{
var element = this.Element;
if (null == element)
{
return;
}
Activity activity = this.Context as Activity;
if ((null != activity && null != activity.ActionBar && activity.ActionBar.TabCount > 0))
{
for (int i = 0; i < element.Children.Count; i += 1)
{
Android.App.ActionBar.Tab tab = activity.ActionBar.GetTabAt(i);
var page = element.Children[i];
if ((null != tab) && (null != page) && (null != page.IconImageSource))
{
if (tab.CustomView == null)
{
var iconKey = "\uf15c";
int fontSize = 30;
string fontName = "FontAwesome.otf";
// IconDrawable class copied from https://github.com/winstongubantes/Xamarin.Forms/blob/master/CustomIconizeFont/CustomIconizeFont/CustomIconizeFont.Android/Custom/Utils/IconDrawable.cs, with slight modifications to how it loads the typeface
var drawable = new IconDrawable(this.Context, iconKey, fontName).Color(Xamarin.Forms.Color.White.ToAndroid()).SizeDp(fontSize);
tab.SetIcon(drawable);
if (tab.Text.Contains("Child"))
tab.SetText("The Child Tab");
else
tab.SetText("The Parent Tab");
LayoutInflater layoutInflater = LayoutInflater.From(this.Context);
Android.Views.View view = layoutInflater.Inflate(Resource.Layout.IconAndText, null);
TextView tab_label = (TextView)view.FindViewById(Resource.Id.nav_label);
tab_label.SetText(tab.Text.ToCharArray(), 0, tab.Text.ToCharArray().Length);
ImageView tab_icon = (ImageView)view.FindViewById(Resource.Id.nav_icon);
tab_icon.SetImageDrawable(tab.Icon);
tab.SetCustomView(view);
}
}
}
}
}
}
}
Я играл с макетом больше дня, но так и не смог стать лучше, чем этот. Любая идея, как я могу увидеть макет по умолчанию и/или изменить свой макет, чтобы он выглядел как по умолчанию, за исключением отступов между значком и текстом?
В качестве альтернативы, совершенно другая стратегия заключается в добавлении отступов к значку. Учитывая, что я использую значки FontAwesome и отображаю их в виде рисунков, используя этот класс, который кажется потенциально выполнимым. В методе Draw этого класса я попытался добавить пробелы после _iconChar при установке textValue. Это создало пространство справа от значка, но сместило значок влево и обрезало левую часть значка. Это показывает его с 3 конечными пробелами. С одним выглядит довольно хорошо с некоторыми иконками, но ужасно/явно обрезано с другими.
Помощь с любым или всеми из следующих будет очень полезно!
- с помощью приложения: варианты на мой взгляд и/или
- просмотр содержимого представления по умолчанию и/или
- настройка моего представления, чтобы оно работало правильно и/или
- Изменение функциональности IconDrawable для небольшого уменьшения значка, чтобы он помещался с одним или двумя завершающими пробелами в пространстве, отведенном значку на вкладке Android.