如何在Xamarin中将svg图像加载到选项卡标题中
我正在构建一个简单的应用程序,它有3个选项卡,每个选项卡都有一个图标和一个文本。 我基于代码的示例项目存在于此处: 我发现的唯一问题是,它使用像素化图像作为选项卡标题,我想将其更改为SVG资源文件 我添加了一个FFImageLoading库,并从这里添加了svg支持 我设法将一个图像添加到其中一个选项卡内容页,但在标题中没有看到我试图看到的svg图像 这是我目前的代码: TodayPage.xaml.cs如何在Xamarin中将svg图像加载到选项卡标题中,svg,xamarin.forms,tabs,Svg,Xamarin.forms,Tabs,我正在构建一个简单的应用程序,它有3个选项卡,每个选项卡都有一个图标和一个文本。 我基于代码的示例项目存在于此处: 我发现的唯一问题是,它使用像素化图像作为选项卡标题,我想将其更改为SVG资源文件 我添加了一个FFImageLoading库,并从这里添加了svg支持 我设法将一个图像添加到其中一个选项卡内容页,但在标题中没有看到我试图看到的svg图像 这是我目前的代码: TodayPage.xaml.cs public partial class TodayPage : ContentPag
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";
}
}
public分部类今日页面:ContentPage
{
今日公共网页()
{
初始化组件();
初始化组件();
//IconImageSource=“today.png”我得到了相同的结果,下面是我在选项卡栏中针对svg图像的解决方法
对于android,请访问此页面
然后将SVG文件导入网站,然后下载xml文件,如以下操作(单击import
,选择SVG
,选择SVG文件,然后选择Export
,将可绘制文件矢量化,下载xml文件)。将xml文件复制到AndroidResource/drawable
文件夹(请检查生成操作是否为xml文件的AndroidResource
)。注意:如果要更改svg文件的线条颜色,请打开xml,然后更改填充颜色
然后可以在PCLXML中使用它,如下面的代码所示
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App3" xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
BarBackgroundColor="Green"
x:Class="App3.MainPage">
<local:TodayPage IconImageSource="{x:OnPlatform Android=ic_today,iOS=today.svg}" >
</local:TodayPage>
<NavigationPage Title="Schedule" IconImageSource="myIcon.png">
<x:Arguments>
<local:Page1 />
</x:Arguments>
</NavigationPage>
</TabbedPage>
下面是跑步截图
有关IOS,请参阅本帖中Dinesh_官方的回复:
对于调试SVG,以下是一些可能有帮助的步骤
如果您更换了另一个已确认的工作SVG,它会工作吗?如果不是,则ffimageloading会初始化吗
确认嵌入的资源。(将其放入App.xaml.cs中)
验证您的svg是否已优化。以下是您推荐的工具:
ffimageloading有时与特定SVG存在问题。
检查他们的github上的问题,看看是否有其他人报告了类似于您的问题,并希望发布一个解决方案
today.svg是作为嵌入式资源添加的,对吗?(很抱歉,这个问题很明显,只是检查一下)1.我不确定它们是否优化了,我从这里下载了一个2.资源是嵌入式资源,我可以在调试中看到它以正确的名称进入循环。3.我使用了CachedImageRenderer.Init(true);var ignore=typeof(SvgCachedImage);就像在FfimageLoading的wiki中一样,android解决方案对我很有效,我仍然不知道如何实现iOS变体,以及在加载不同的资源/渲染器时如何区分android和iOS。Lean Lu,我是否需要为我将拥有的每个选项卡创建选项卡渲染器?@Dermemo在iOS中,你应该创建一个custom呈现程序,然后覆盖GetIcon
方法,这是演示代码。您也可以下载。我更新了我的问题,似乎从来没有调用过GetIcon。我在原始帖子中附加了我的新代码。我感谢您的帮助!
<?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>
[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;
}
}
}
<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>
<?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>
[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;
}
}
}
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App3" xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
BarBackgroundColor="Green"
x:Class="App3.MainPage">
<local:TodayPage IconImageSource="{x:OnPlatform Android=ic_today,iOS=today.svg}" >
</local:TodayPage>
<NavigationPage Title="Schedule" IconImageSource="myIcon.png">
<x:Arguments>
<local:Page1 />
</x:Arguments>
</NavigationPage>
</TabbedPage>
public static void PrintEmbeddedResources()
{
#if DEBUG
var assembly = typeof(App).GetTypeInfo().Assembly;
var logTxt = "Embedded Resources:" + Environment.NewLine;
foreach (var res in assembly.GetManifestResourceNames())
{
Debug.WriteLine("found resource: " + res);
}
#endif
}