TheFooBarWay
TheFooBarWay

Reputation: 594

Windows 10 universal app round button with 'animation' when clicked

I am currently trying to create a simple button in the shape of a circle that reacts int eh same way the default button does to a click (you can visually see a reaction when clicking on a default button, the color changes among other things).

I have made a circular button using the Ellipse attribute. This removed any reaction (in terms of visuals) the button had to a click. In an attempt to bring it back I used the visual manager. My issue is that I cannot combine the two successfully.

How should I go about doing this?

Is there perhaps a simpler way to make a round button that reacts to clicks?

Ideally I would like something that does this with code and avoid the use of Blend which I have seen mentioned in several places.

Below are the two code snippets in XAML.

Just a simple round button:

<Button Name="bottomCircle" Width="100" Height="100" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="2">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Grid>
                <Ellipse Fill="Blue">
                </Ellipse>
                <ContentPresenter HorizontalAlignment="Center"
                          VerticalAlignment="Center"/>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

A button with "animation":

<Button Content="Click Me" x:Name="ClickMe" Background="Blue" Grid.Row="2"  Width="100" Height="100" >
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Grid Background="Transparent">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver"/>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Black" />
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedHighlightBackground" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarBackgroundThemeBrush}" />
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="BorderBrush">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarBackgroundThemeBrush}" />
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Foreground">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonBackgroundThemeBrush}" />
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="BorderBrush">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Green" />
                                </ObjectAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Background">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" /> 
                                </ObjectAnimationUsingKeyFrames> 
                            </Storyboard> 
                        </VisualState> 
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Background="{TemplateBinding Background}">
                    <Border x:Name="PressedHighlightBackground" Background="Transparent">
                        <ContentControl x:Name="ContentContainer" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Padding="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </Border>
                </Border>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

Upvotes: 1

Views: 54

Answers (1)

Petter Hesselberg
Petter Hesselberg

Reputation: 5518

If you change the CornerRadius of your border elements to some large number, you'll get a circle:

<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        CornerRadius="100" Background="{TemplateBinding Background}">
    <Border x:Name="PressedHighlightBackground" Background="Transparent"
            CornerRadius="100">
        <ContentControl x:Name="ContentContainer"
                        Foreground="{TemplateBinding Foreground}"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        Padding="{TemplateBinding Padding}"
                        Content="{TemplateBinding Content}"
                        ContentTemplate="{TemplateBinding ContentTemplate}"/>
    </Border>
</Border>

(I do believe you can get away with just a single Border element, though.)

Also, using Storyboard and ObjectAnimationUsingKeyFrames is cumbersome. You can use VisualState.Setters instead, which is easier to maintain.

To react to clicks and moseovers only within the circle, remove the outer Grid, which doesn't provide anything anyway. In addition, be advised that the visual state MouseOver works better if you rename it PointerOver.

This works the way you want:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button Content="Click Me" x:Name="ClickMe" Background="Blue" Grid.Row="2"  Width="100" Height="100" Foreground="White">
        <Button.Template>
            <ControlTemplate TargetType="Button">
                <Border
                    x:Name="ButtonBackground"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="100" Background="{TemplateBinding Background}">
                    <Border
                        x:Name="PressedHighlightBackground"
                        Background="Transparent"
                        CornerRadius="100">
                        <ContentControl x:Name="ContentContainer"
                            Foreground="{TemplateBinding Foreground}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            Padding="{TemplateBinding Padding}"
                            Content="{TemplateBinding Content}"
                            ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </Border>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="PointerOver">
                                <VisualState.Setters>
                                    <Setter
                                        Target="ContentContainer.Foreground"
                                        Value="Pink" />
                                    <Setter
                                        Target="PressedHighlightBackground.Background"
                                        Value="Blue" />
                                    <Setter
                                        Target="ButtonBackground.BorderBrush"
                                        Value="{StaticResource AppBarBackgroundThemeBrush}" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <VisualState.Setters>
                                    <Setter
                                        Target="ContentContainer.Foreground"
                                        Value="Black" />
                                    <Setter
                                        Target="PressedHighlightBackground.Background"
                                        Value="{StaticResource AppBarBackgroundThemeBrush}" />
                                    <Setter
                                        Target="ButtonBackground.BorderBrush"
                                        Value="{StaticResource AppBarBackgroundThemeBrush}" />
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Disabled">

                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Border>
            </ControlTemplate>
        </Button.Template>
    </Button>
</Grid>

Upvotes: 1

Related Questions