Search code examples
c#ios.netmaui

MAUI iOS Image Button - How to set custom button type to prevent image from fading?


In iOS when you create an image button, you can set the button type to "Custom" to prevent the default animations and styling to the button. When you do this, it allows you to set a pressed and default image and when you press the button they cycle. Check my first two images showing this behavior in iOS Xcode with the green yes button.

Green Button Unpressed Green Button Pressed

I'm trying to replicate this on my iOS .NET MAUI app in Visual Studio. I use ImageButton to set the two images but when I press the button you can see it dims down with a dark highlight making it hard to see the button. How can I make it work so that I only see my images? As mentioned, in Xcode I would just set the button to "Custom" and it would work. I attached the red button image to show how it works in MAUI.

Red Button showing fading

I saw information in the docs about image button handlers but since setting the button to custom in code requires a change in the constructor, I don't see how to do it as the button already exists in the handler and it doesn't seem I can recreate it.

How can I get iOS's custom button type in MAUI?

Below is my button code.

<ImageButton HorizontalOptions="Fill" VerticalOptions="Fill" Aspect="AspectFit" FlexLayout.Grow="1" BackgroundColor="Transparent" IsOpaque="True">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">
                <VisualState.Setters>
                    <Setter Property="Source" Value="{Binding YesButtonImageSource, Mode=OneWay}" />
                    <Setter Property="Scale" Value="1" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Pressed">
                <VisualState.Setters>
                    <Setter Property="Source" Value="{Binding YesButtonPressedImageSource, Mode=OneWay}" />
                    <Setter Property="Scale" Value="1" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</ImageButton>

Solution

  • You need to define a custom ImageButtonHandler where you can override the CreatePlatformView method. Here you can set ButtonType and AdjustsImageWhenHighlighted

    #if IOS
    public class CustomImageButtonHandler: ImageButtonHandler
    {
    
        protected override UIButton CreatePlatformView()
        {
          var platformView = new UIButton(UIButtonType.Custom)
          {
              ClipsToBounds = true,
              AdjustsImageWhenHighlighted = false
           };
    
            return platformView;
        }
    
    }
    #endif
    

    Add your CustomHandler in MauiProgram.cs

    builder.ConfigureMauiHandlers((handlers) => {
        #if IOS
        handlers.AddHandler<ImageButton,CustomImageButtonHandler>();
        #endif
    });
    

    Also your'e defining Visual States incorrectly. Your VisualStateGroup should be wrapped around with VisualStateGroupList and by default your image button should have a Source.

     <ImageButton Source="{Binding YesButtonImageSource, Mode=OneWay}"  HorizontalOptions="Fill" Grid.Row="1" VerticalOptions="Fill" Aspect="AspectFit" FlexLayout.Grow="1" BackgroundColor="Transparent" IsOpaque="True">
      <VisualStateManager.VisualStateGroups>
        <VisualStateGroupList>
             <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal">
                    <VisualState.Setters>
                        <Setter Property="Source" Value="{Binding YesButtonImageSource, Mode=OneWay}" />
                        <Setter Property="Scale" Value="1" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <VisualState.Setters>
                        <Setter Property="Source" Value="{Binding YesButtonPressedImageSource, Mode=OneWay}" />
                        <Setter Property="Scale" Value="1" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateGroupList>     
        </VisualStateManager.VisualStateGroups>
    </ImageButton>