繁体   English   中英

如何将 svg 图像加载到 Xamarin 中的选项卡标题中

[英]How to load a svg image into tab header in Xamarin

我正在构建一个简单的应用程序,它有 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";
        }
    }

今日页面.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>

主页.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;
        }
      
        
        
    }
    
}

这是我的主页.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 *******

在到处玩代码之后,我设法弄明白了。 如果有人有兴趣实施类似的设计

主文件

    <?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 文件夹中,就是这样。

我得到了相同的结果,这是我在选项卡栏中对 svg 图像的解决方法。

对于 android,请访问此页面https://shapeshifter.design/

然后将你的SVG文件导入网站,然后下载xml文件,如下操作(点击Import ,选择svg ,选择svg文件,然后选择Export ,Vector the drawable,下载xml文件)。 将xml文件复制到Android Resource/ Drawable文件夹(请检查build Action是xml文件的AndroidResource )。 注意:如果你想改变svg文件的线条颜色,请打开xml,喜欢填充颜色,改变它。

在此处输入图片说明

在此处输入图片说明

然后你可以像下面的代码一样在 pcl XML 中使用它。

<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_Official在该线程中的回复:

https://forums.xamarin.com/discussion/179773/how-to-use-svg-image-for-tabbed-page-tabbar-icon

对于调试 SSVG,这里有一些可能会有所帮助的步骤。

  1. 如果更换了另一个已确认有效的 SVG,它会起作用吗? 如果不是 ffimageloading 初始化?

  2. 确认您的嵌入资源。 (将其放在 App.xaml.cs 中)

    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
    }
  1. 验证您的 svg 是否已优化。 这是 ffimageloading 推荐的工具: https ://jakearchibald.github.io/svgomg/

  2. ffimageloading 有时会遇到特定 SSVG 的问题。 检查他们 github 上的问题,看看其他人是否报告了与您类似的问题,并希望发布解决方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM