【发布时间】:2020-10-17 01:05:43
【问题描述】:
我正在构建一个简单的应用程序,它有 3 个选项卡,每个选项卡都有一个图标和一个文本。 我的代码基于的示例项目存在于此处:
我发现它的唯一问题是,它使用像素化图像作为标签标题,我想将其更改为 SVG 资源文件。
我添加了一个 FFImageLoading 库并从这里添加了 svg 支持
我设法将图像添加到其中一个选项卡内容页面,但我没有看到我试图在标题中看到的 svg 图像。
这是我目前的代码:
TodayPage.xaml.cs
public partial class TodayPage : ContentPage
{
public TodayPage()
{
InitializeComponent();
InitializeComponent();
// IconImageSource = "today.png"; <-- this will show the pixilated image
IconImageSource = SvgImageSource.FromResource("today.svg"); //<--not working
Title = "Today";
}
}
TodayPage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:forms="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
x:Class="TabsApp.TodayPage">
<ContentPage.Content>
<StackLayout>
<forms:SvgCachedImage WidthRequest="200" HeightRequest="200" Source="resource://TabsApp.Resources.today.svg"/>
<Label Text="Today's appointments go here going" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
MainPage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabsApp;assembly=TabsApp"
x:Class="TabsApp.MainPage">
<local:TodayPage />
<NavigationPage Title="Schedule" IconImageSource="schedule.png">
<x:Arguments>
<local:SchedulePage />
</x:Arguments>
</NavigationPage>
<local:SettingPage />
</TabbedPage>
谢谢
编辑
感谢 Leon,我设法在 Android 中加载了 svg 文件。 我仍在努力在 iOS 中加载 svg 文件。
我设法在 iOS 中创建了一个自定义选项卡渲染器,代码如下:
[assembly: ExportRenderer(typeof(TabPage), typeof(PageTabRenderer))]
namespace TabsApp.iOS
{
[Foundation.Preserve(AllMembers = true)]
public class PageTabRenderer : TabbedRenderer
{
protected override async Task<Tuple<UIImage, UIImage>> GetIcon(Page page)
{
var navigationPage = page as NavigationPage;
if (navigationPage != null && navigationPage.CurrentPage != null)
{
var imageSource = navigationPage.IconImageSource == null ? navigationPage.CurrentPage.IconImageSource : navigationPage.IconImageSource;
return await this.GetNativeUIImage(imageSource);
}
return await this.GetNativeUIImage(page.IconImageSource);
}
private async Task<Tuple<UIImage, UIImage>> GetNativeUIImage(ImageSource imageSource)
{
var imageicon = await GetNativeImageAsync(imageSource);
return new Tuple<UIImage, UIImage>(imageicon, null);
}
private async Task<UIImage> GetNativeImageAsync(ImageSource imageSource)
{
if (imageSource is FileImageSource fileImage && fileImage.File.Contains(".svg"))
{
var imageicon = await ImageService.Instance.LoadFile(fileImage.File).WithCustomDataResolver(new SvgDataResolver(15, 15, true)).AsUIImageAsync();
return imageicon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
}
else
{
var imageicon = await GetUIImage(imageSource);
return imageicon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
}
}
private Task<UIImage> GetUIImage(ImageSource imageSource)
{
var handler = GetImageSourceHandler(imageSource);
return handler.LoadImageAsync(imageSource);
}
private static IImageSourceHandler GetImageSourceHandler(ImageSource source)
{
IImageSourceHandler sourceHandler = null;
if (source is UriImageSource)
sourceHandler = new ImageLoaderSourceHandler();
else if (source is FileImageSource)
sourceHandler = new FileImageSourceHandler();
else if (source is StreamImageSource)
sourceHandler = new StreamImagesourceHandler();
else if (source is FontImageSource)
sourceHandler = new FontImageSourceHandler();
return sourceHandler;
}
}
}
这是我的 mainpage.xaml
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabsApp;assembly=TabsApp"
x:Class="TabsApp.MainPage">
<local:TodayPage />
<NavigationPage Title="Schedule" IconImageSource="today1.svg">
<x:Arguments>
<local:SchedulePage />
</x:Arguments>
</NavigationPage>
<local:SettingPage />
</TabbedPage>
我还复制了 TabPage 类,但没有看到 svg 图标加载。我尝试调试它,似乎从未调用过 GetIcon。
****** 编辑 2 *******
在到处玩弄代码之后,我设法弄明白了。如果有人有兴趣实现类似的设计
main.xaml
<?xml version="1.0" encoding="UTF-8"?>
<custom:TabPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabsApp;assembly=TabsApp"
xmlns:custom="clr-namespace:TabsApp.custom;assembly=TabsApp"
x:Class="TabsApp.MainPage"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
android:TabbedPage.IsSmoothScrollEnabled="True"
android:TabbedPage.IsSwipePagingEnabled="False"
xmlns:iOS="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
iOS:Page.UseSafeArea="true" NavigationPage.HasNavigationBar="False"
BarTextColor="{DynamicResource SecondaryTextColor}" UnselectedTabColor="Black" SelectedTabColor="Blue"
NavigationPage.HasBackButton="False">
<local:TodayPage IconImageSource="{x:OnPlatform Android=ic_today, iOS=today-24px.svg}"/>
<local:SchedulePage IconImageSource="{x:OnPlatform Android=ic_schedule, iOS=schedule-24px.svg}"/>
<local:SettingPage IconImageSource="{x:OnPlatform Android=ic_settings, iOS=settings-24px.svg}"/>
</custom:TabPage>
重要的是要注意两点:IconImageSource 将根据平台而改变,SelectedTabColor 将是 Android 和 iOS 在选择选项卡项时的色调颜色。
您需要像 Lean 写的那样将 svg 文件转换为可绘制的矢量文件并将它们放在 /drawable 文件夹中。
对于 iOS,您需要添加一个自定义选项卡渲染器,这是我使用的:
[assembly: ExportRenderer(typeof(TabPage), typeof(PageTabRenderer))]
namespace TabsApp.iOS
{
[Foundation.Preserve(AllMembers = true)]
public class PageTabRenderer : TabbedRenderer
{
readonly nfloat imageYOffset = 7.0f;
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (TabBar.Items != null)
{
foreach (var item in TabBar.Items)
{
item.Title = null;
item.ImageInsets = new UIEdgeInsets(imageYOffset, 0, -imageYOffset, 0);
}
}
}
protected override async Task<Tuple<UIImage, UIImage>> GetIcon(Page page)
{
var navigationPage = page as NavigationPage;
if (navigationPage != null && navigationPage.CurrentPage != null)
{
var imageSource = navigationPage.IconImageSource == null ? navigationPage.CurrentPage.IconImageSource : navigationPage.IconImageSource;
return await this.GetNativeUIImage(imageSource);
}
return await this.GetNativeUIImage(page.IconImageSource);
}
private async Task<Tuple<UIImage, UIImage>> GetNativeUIImage(ImageSource imageSource)
{
var imageicon = await GetNativeImageAsync(imageSource);
return new Tuple<UIImage, UIImage>(imageicon, null);
}
private async Task<UIImage> GetNativeImageAsync(ImageSource imageSource)
{
if (imageSource is FileImageSource fileImage && fileImage.File.Contains(".svg"))
{
var imageicon = await ImageService.Instance.LoadFile(fileImage.File).WithCustomDataResolver(new SvgDataResolver(15, 15, true)).AsUIImageAsync();
return imageicon.ImageWithRenderingMode(UIImageRenderingMode.Automatic);
}
else
{
var imageicon = await GetUIImage(imageSource);
return imageicon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
}
}
private Task<UIImage> GetUIImage(ImageSource imageSource)
{
var handler = GetImageSourceHandler(imageSource);
return handler.LoadImageAsync(imageSource);
}
private static IImageSourceHandler GetImageSourceHandler(ImageSource source)
{
IImageSourceHandler sourceHandler = null;
if (source is UriImageSource)
sourceHandler = new ImageLoaderSourceHandler();
else if (source is FileImageSource)
sourceHandler = new FileImageSourceHandler();
else if (source is StreamImageSource)
sourceHandler = new StreamImagesourceHandler();
else if (source is FontImageSource)
sourceHandler = new FontImageSourceHandler();
return sourceHandler;
}
}
}
把所有的*.svg 文件放到*.iOS 文件夹的/Resources 文件夹中就可以了。
【问题讨论】:
-
today.svg 被添加为嵌入式资源对吗? (很抱歉这个明显的问题,但只是检查)
标签: svg xamarin.forms tabs