在鼠标悬停和按下状态之间跳过VSM中的正常按钮状态

时间:2015-11-13 11:40:02

标签: wpf blend visualstatemanager

按下按钮时,状态转换如下:

Normal -> MouseOver -> Normal -> Pressed -> Normal -> MouseOver

我遇到的问题是MouseOverPressed状态在视觉上有很多共同之处,而这些状态之间的过渡会使动画混乱。作为一个更实际的例子,我有一个按钮,默认情况下有一个黑色边框,并且在MouseOverPressed状态下有一个绿色边框。当我按下它时,它首先从绿色变为黑色然后变为绿色,这是不可取的。有没有办法在这种情况下跳过Normal状态或让它看起来不好?

enter image description here

这是按钮的模板:

<Button Command="{Binding PlayScene}" Width="220">
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Border x:Name="border"
                    BorderThickness="3"
                    Margin="2 0"
                    BorderBrush="{DynamicResource ButtonBorderBrush}"
                    RenderTransformOrigin="0.5,0.5">
                <Border.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Border.RenderTransform>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualStateGroup.Transitions>
                            <VisualTransition GeneratedDuration="0:0:0.2"/>
                            <VisualTransition GeneratedDuration="0:0:0.2" To="Pressed">
                                <VisualTransition.GeneratedEasingFunction>
                                    <BackEase EasingMode="EaseOut"/>
                                </VisualTransition.GeneratedEasingFunction>
                            </VisualTransition>
                            <VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>
                        </VisualStateGroup.Transitions>
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource HighlightBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(Brush.RelativeTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="border">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="1.1"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(Brush.RelativeTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="border">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="1.1"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="border">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0.95"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="border">
                                    <EasingDoubleKeyFrame KeyTime="0" Value="0.95"/>
                                </DoubleAnimationUsingKeyFrames>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource HighlightDarkBrush}"/>
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>

                <Border.Background>
                    <ImageBrush ImageSource="{Binding Image}" Stretch="UniformToFill">
                        <ImageBrush.RelativeTransform>
                            <TransformGroup>
                                <ScaleTransform CenterY="0.5" CenterX="0.5"/>
                                <SkewTransform CenterY="0.5" CenterX="0.5"/>
                                <RotateTransform CenterY="0.5" CenterX="0.5"/>
                                <TranslateTransform/>
                            </TransformGroup>
                        </ImageBrush.RelativeTransform>
                    </ImageBrush>
                </Border.Background>

                <ContentPresenter x:Name="contentPresenter" />
            </Border>
        </ControlTemplate>
    </Button.Template>
</Button>

1 个答案:

答案 0 :(得分:3)

视觉状态转换在进入实际状态之前运行。由于您没有在转换中设置画笔,因此它们默认为基值(在本例中为ButtonBorderBrush)。我并不完全确定你想要的结果,但是我的例子假设你想立即将HighlightBrush(在MouseOver状态下)的颜色改为HighlightDarkBrush(在Pressed状态下),显然如果从一种颜色淡化到另一种颜色是希望故事板动画动画可以改变以实现它。

<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"/>
<VisualTransition GeneratedDuration="0:0:0.2" To="Pressed">
    <VisualTransition.GeneratedEasingFunction>
        <BackEase EasingMode="EaseOut"/>
    </VisualTransition.GeneratedEasingFunction>
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource HighlightDarkBrush}"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualTransition>
<VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>

基本上,您需要将Storyboard添加到Pressed状态和= Pressed转换。如果只将它添加到过渡中,颜色将在进入状态后恢复。

另请注意,虽然看起来好像过渡序列是

MouseOver -> Normal-> Pressed
实际情况并非如此。如果你给Normal状态一些值(目前正在使用基值),你可以自己看到这个:

<VisualState x:Name="Normal">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TestBrush}"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

如果(例如)TestBrush是红色画笔,则当鼠标未结束时,边框将仅为红色。在状态之间,它将是黑色(ButtonBorderBrush)