Home > database >  Xamarin Forms how to apply SVG to a button data triggers?
Xamarin Forms how to apply SVG to a button data triggers?

Time:10-13

So my app needs SVGs now or I want to switch png to svg so it can scale well with difference screen sizes. I know I can draw svg using <Path> but <Path> doesn't have data triggers but they do have GestureRecognizers which is useful but without data triggers idk how else to achieve what I want.

This is my current xaml for a button to data trigger and switch its content depending on playing state of a MediaElement. I would like to switch the Text to a SVG of play pause images.

<Button x:Name="OnPlayPauseButtonClicked"
                    Grid.Row="1"
                    Text="&#x25B6;&#xFE0F; Play"
                    VerticalOptions="End"
                    Clicked="OnPlayPauseButton_Clicked">
                <Button.Triggers>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding CurrentState}"
                                 Value="{x:Static xct:MediaElementState.Playing}">
                        <Setter Property="Text"
                                Value="&#x23F8; Pause"/>
                    </DataTrigger>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding CurrentState}"
                                 Value="{x:Static xct:MediaElementState.Buffering}">
                        <Setter Property="IsEnabled"
                                Value="False"/>
                    </DataTrigger>
                </Button.Triggers>
            </Button>

I have tried putting my play and pause svg files into drawable folder and apply the Value to property of ImageSource. That didn't work. I then tried converting the SVG to XML and use the instead and it didn't work.

Is there a way to do this without using any dependencies?

Thanks in advance.

CodePudding user response:

You can use SkiaSharp to draw patterns, create custom controls to load it. For drawing patterns, refer to this document. The answer to this issue can also help you.

CodePudding user response:

You have a few options here:

1. Font Icons

There is a much better way to accomplish what you are trying to do using Font Icons, e.g. Material Design Icons. Here is a cheat sheet for the icons.

This is not strictly a dependency, if you add the fonts as a resource (which you need to do in either case using PNGs, SVGs or - in this case - an image font).

<Button x:Name="OnPlayPauseButtonClicked" Grid.Row="1" Text="&#xF040A;" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked"
        FontFamily="materialdesignicons">
    <Button.Triggers>
        <DataTrigger TargetType="Button"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Playing}">
            <!-- Pause Button Icon -->
            <Setter Property="Text" Value="&#xF03E4;"/>
        </DataTrigger>
                <DataTrigger TargetType="Button"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Paused}">
            <!-- Play Button Icon -->
            <Setter Property="Text" Value="&#xF040A;"/>
        </DataTrigger>
        <DataTrigger TargetType="Button"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Buffering}">
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </Button.Triggers>
</Button>

James Montemagno also has a great blog post on this: https://montemagno.com/using-font-icons-in-xamarin-forms-goodbye-images-hello-fonts/

2. ImageButton

You can add your images to your project's resources and load them into an ImageButton. How to use ImageButtons refer to this link: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/imagebutton.

SVGs

There is a library that allows you to load SVGs, this will require the following nuget to be installed: https://github.com/luberda-molinet/FFImageLoading/

<ImageButton x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked">
    <ImageButton.Triggers>
        <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Playing}">
            <!-- Pause Button Icon -->
            <Setter Property="Source">
               <Setter.Value>
                   <ffimageloadingsvg:SvgCachedImage Source="resource://YourAppName.Resources.Pause.svg"/>
               </Setter.Value>
            </Setter>
        </DataTrigger>
                <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Paused}">
            <!-- Play Button Icon -->
            <Setter Property="Source">
               <Setter.Value>
                   <ffimageloadingsvg:SvgCachedImage Source="resource://YourAppName.Resources.Play.svg"/>
               </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Buffering}">
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </ImageButton.Triggers>
</ImageButton>

PNGs

To see how to add images to your app, refer to this page: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/images?tabs=windows#embedded-images

<ImageButton x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End" Clicked="OnPlayPauseButton_Clicked">
    <ImageButton.Triggers>
        <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Playing}">
            <!-- Pause Button Icon -->
            <Setter Property="Source" Value="{local:ImageResource Pause.PNG}" />
        </DataTrigger>
                <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Paused}">
            <!-- Play Button Icon -->
            <Setter Property="Source" Value="{local:ImageResource Play.PNG}" />
        </DataTrigger>
        <DataTrigger TargetType="ImageButton"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Buffering}">
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </ImageButton.Triggers>
</ImageButton>

[Update] 3: Use SvgCachedImage directly

You can also use SvgCachedImage directly instead of a Button and attach a TapGestureRecognizer to it:

<ffimageloadingsvg:SvgCachedImage x:Name="OnPlayPauseButtonClicked" Grid.Row="1" VerticalOptions="End">
    <ffimageloadingsvg:SvgCachedImage.Triggers>
        <DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Playing}">
            <!-- Pause Button Icon -->
            <Setter Property="Source"
                    Value="resource://YourAppName.Resources.Pause.svg"/>
        </DataTrigger>
        <DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Paused}">
            <!-- Play Button Icon -->
            <Setter Property="Source"
                    Value="resource://YourAppName.Resources.Play.svg"/>
        </DataTrigger>
        <DataTrigger TargetType="ffimageloadingsvg:SvgCachedImage"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static xct:MediaElementState.Buffering}">
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </ffimageloadingsvg:SvgCachedImage.Triggers>
    <ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
        <TapGestureRecognizer Tapped="OnPlayPauseButton_Clicked"/>
    </ffimageloadingsvg:SvgCachedImage.GestureRecognizers>
</ffimageloadingsvg:SvgCachedImage>
  • Related