首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Xamarin中将svg图像加载到制表符头中

如何在Xamarin中将svg图像加载到制表符头中
EN

Stack Overflow用户
提问于 2020-10-14 21:29:26
回答 2查看 2.1K关注 0票数 1

我正在构建一个简单的应用程序,它有3个选项卡,每个选项卡都有一个图标和一个文本。我基于我的代码的示例项目存在于这里:

链接

我发现的唯一问题是,它对选项卡头使用像素化的图像,我想将其更改为SVG资源文件。

我添加了一个FFImageLoading库,并从这里添加了svg支持。

链接

我设法将一个图像添加到一个选项卡内容页面中,但我没有看到我试图在标题中看到的svg图像。

到目前为止,这是我的代码:

TodayPage.xaml.cs

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
<?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

代码语言:javascript
运行
复制
<?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中创建了一个自定义选项卡呈现器,下面是代码:

代码语言:javascript
运行
复制
[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

代码语言:javascript
运行
复制
<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

代码语言:javascript
运行
复制
    <?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将是安卓和iOS的色调。

您需要像精益编写的那样将svg文件转换为可绘制的向量文件,并将它们放在/drawable文件夹中。

至于iOS,您需要添加一个自定义选项卡呈现器--这是我使用的一个:

代码语言:javascript
运行
复制
[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文件放在/Resources文件夹中的*.iOS文件夹中,仅此而已。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-15 05:58:09

我得到了同样的结果,这是我在标签栏中svg图像的解决方法。

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

然后将您的SVG文件导入网站,然后下载xml文件,类似于以下操作(单击Import,选择svg,选择svg文件,然后选择Export,向量可绘制,下载xml文件)。将xml文件复制到Android文件夹(请检查Resource/ Drawable文件的)。注意:如果您想更改svg文件的行颜色,请打开xml,喜欢填充颜色,更改它。

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

代码语言:javascript
运行
复制
<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

票数 1
EN

Stack Overflow用户

发布于 2020-10-15 05:59:19

对于调试SVGS,以下是一些可能有帮助的步骤。

  1. 如果你更换了一个不同的已确认工作的SVG,它会起作用吗?如果没有,是否初始化了?
  2. 确认你嵌入的资源。(把这个放在App.xaml.cs中)
代码语言:javascript
运行
复制
    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. 有时,特定的SVGS也会出现问题。查看他们的github上的问题,看看是否有其他人报告了类似于您的问题,并希望发布了一项工作。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64361755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档