UWP Button添加圆角阴影(二)

简介: 原文:UWP Button添加圆角阴影(二)原文:UWP Button添加圆角阴影(二) 阴影 对于阴影呢,WindowsCommunityToolkit中已经有封装好的DropShadowPanel啦,只要引用Microsoft.Toolkit.Uwp.UI.Controls这个Nuget包就可以使用啦。
原文: UWP Button添加圆角阴影(二)

原文:UWP Button添加圆角阴影(二)

阴影

对于阴影呢,WindowsCommunityToolkit中已经有封装好的DropShadowPanel啦,只要引用Microsoft.Toolkit.Uwp.UI.Controls这个Nuget包就可以使用啦。
直接把阴影套在咱们的圆角Button外面呢,会出现圆角的Button映出直角的阴影的丑陋状况。对于这种情况肯定是有处理方式的。
看DropShadowPanel的源码,对Content的特殊类型做了处理。下面我详细的说下。
CompositionAPI中的DropShadow这个东西,非常反人类的两点:

  • 只有SpriteVisual拥有Shadow熟悉,也就是说你不能直接给Xaml元素的Visual附加阴影;
  • 给SpriteVisual设置阴影后,这个阴影是绘制在SpriteVisual上面的。
    所以呢,你去看DropShadowPanel的源码,是ContentPresenter后面附了个什么东西当SpriteVisual的Host,然后在Host的ChildVisual也就是SpriteVisual上面设置阴影。也就是说,这个阴影,和Content是没毛关系的。
    那么,官方Demo中Image、Shape、TextBlock的阴影是怎么做到的呢?这就要提到他们三个拥有的一个方法了。说实话,这是我第一次见到多个控件拥有相同的方法,却没有继承相同的接口的情况。。。方法名叫GetAlphaMask(),可以返回一个CompositionSurfaceBrush,Brush的内容是控件的内容填黑,其他地方留空,给DropShadow.Mask设置成这个Brush,阴影就会按照这个轮廓去绘制。
    破案之后呢,思路就(救)出来了,按照这个方法,我们只要给DropShadowPanel的Content设置一个Rectangle,就能获得圆角的阴影啦。
    既然上面已经有一个Rectangle当背景,这里就再利用一下,给背景外面套个DropShadowPanel,接下来结构变成了这样子。
<Style TargetType="Button" x:Key="CornerRadiusShadowButtonStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid x:Name="RootGrid">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <control:DropShadowPanel x:Name="Shadow" xmlns:control="using:Microsoft.Toolkit.Uwp.UI.Controls">
                        <Rectangle x:Name="Background"></Rectangle>
                    </control:DropShadowPanel>
                    <ContentPresenter x:Name="ContentPresenter">
                    </ContentPresenter>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

注意这里有个小坑,DropShadowPanel的HorizontalContentAlignment默认是Left,Content里如果只装Rectangle,是撑不开的。。。要做如下设置:

<control:DropShadowPanel x:Name="Shadow" xmlns:control="using:Microsoft.Toolkit.Uwp.UI.Controls" HorizontalContentAlignment="Stretch">
    <Rectangle x:Name="Background" Fill="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RadiusX="5" RadiusY="5" />
</control:DropShadowPanel>                        

接下来就是编写VisualState了,如果要对DropShadowPanel进行有过渡的动画,需要在DoubleAnimation中设置EnableDependentAnimation="True",不然只播放起始和终止状态。详情请见:情节提要动画 - 从属动画和独立动画
注:调试过程中热更新DropShadowPanel的BlurRadius和Offset动画,再播放会掉帧,重新运行一下就好了。
img_9a8f50fbd56309c65afe34d0a980abd3.gif
但是用DoubleAnimation去控制CompositionAPI中的动画是很不好的,Composition有自己的Animation系统,我们将会在下一篇文章中一起给DropShadowPanel附加隐式(过渡)动画。
下面是完整的代码:

<Style TargetType="Button" x:Key="CornerRadiusShadowButtonStyle">
    <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
    <Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
    <Setter Property="BorderBrush" Value="Transparent" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Padding" Value="20,10,20,10" />
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontWeight" Value="Normal" />
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="UseSystemFocusVisuals" Value="True" />
    <Setter Property="FocusVisualMargin" Value="-3" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid x:Name="RootGrid">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition To="Normal" >
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="1" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="5" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                    </Storyboard>
                                </VisualTransition>
                                <VisualTransition To="PointerOver" >
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="2" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="8" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                    </Storyboard>
                                </VisualTransition>
                                <VisualTransition To="Pressed" >
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="3" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                        <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="12" Duration="0:0:0.1" EnableDependentAnimation="True" />
                                    </Storyboard>
                                </VisualTransition>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Normal" >
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="1" Duration="0" EnableDependentAnimation="True" />
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="5" Duration="0" EnableDependentAnimation="True" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="2" Duration="0" EnableDependentAnimation="True" />
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="8" Duration="0" EnableDependentAnimation="True" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="OffsetY" To="3" Duration="0" EnableDependentAnimation="True" />
                                    <DoubleAnimation Storyboard.TargetName="Shadow" Storyboard.TargetProperty="BlurRadius" To="12" Duration="0" EnableDependentAnimation="True" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="Fill">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <control:DropShadowPanel x:Name="Shadow" xmlns:control="using:Microsoft.Toolkit.Uwp.UI.Controls" HorizontalContentAlignment="Stretch" 
                                             BlurRadius="5" ShadowOpacity="0.8" OffsetX="1" OffsetY="1" Color="Black">
                        <Rectangle x:Name="Background" Fill="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RadiusX="5" RadiusY="5" />
                    </control:DropShadowPanel>
                    <ContentPresenter x:Name="ContentPresenter"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Content="{TemplateBinding Content}"
                        ContentTransitions="{TemplateBinding ContentTransitions}"
                        ContentTemplate="{TemplateBinding ContentTemplate}"
                        Padding="{TemplateBinding Padding}"
                        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                        AutomationProperties.AccessibilityView="Raw" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
目录
相关文章
|
9月前
QT中 QPlainTextEdit自适应高度的问题(防止出现滚动条)
在QT开发过程中,经常使用到QPlainTextEdit来填入大量的文字,一般我们都会设置QPlainText的固定高度或者默认高度,但是随着文字的增多,就会自动出现滚动条,有时候我们可能需要QPlainText的高度随着自动适应文字的高度(即是说不需要出现滚动条)
568 0
|
前端开发 数据可视化
UWP Button添加圆角阴影(三)
原文:UWP Button添加圆角阴影(三) 原文:UWP Button添加圆角阴影(三) Composition DropShadow是CompositionAPI中的东西,使用Storyboard设置某个属性,就是频繁的触发put_xxx()方法,效率远远不如使用CompositionAnimation。
907 0
UWP Button添加圆角阴影(一)
原文:UWP Button添加圆角阴影(一) 原文:UWP Button添加圆角阴影(一) 众所周知,17763之前的UWP控件,大部分是没有圆角属性的;而阴影也只有17763中的ThemeShadow可以直接在xaml中使用,之前的版本只能用DropShadow,用法极其别扭。
1144 0
|
C#
WPF 圆角textbox
原文:WPF 圆角textbox 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a771948524/article/details/9245965 ...
1284 0
|
C#
WPF 圆角输入框
原文:WPF 圆角输入框 今天打算来做一个圆角的输入框 默认输入框:   这个输入框不好看,并且在XP 跟 WIN 7  WIN10 效果 都不太一样   我们今天不用模板的方式,而是 最简单的方式 来实现 圆角 输入框;     ------------------------...
1393 0
|
C# Windows
C#(WPF)为Grid添加实线边框。
原文:C#(WPF)为Grid添加实线边框。 相信大家在做WPF项目的时候,都会用到Grid这个布局控件,一般情况下,如果只是为了布局,那就不需要显示它的边框,但是也有特殊需求,如果把它当做表格来使用,那就需要为它添加实线边框。
2423 0
关于圆角控件
如何新建shape文件:https://jingyan.baidu.com/article/b907e62795139746e7891cb9.html 如何在空间中加入shape.
762 0
|
XML Android开发 数据格式
Android自定义ProgressBar样式:渐变圆角水平进度条
Android自定义ProgressBar样式:渐变圆角水平进度条 关键是android:progressDrawable的设置,设置一个android:progressDrawable资源,但是android:progressDrawable需要是一个layer-list。
4606 0
|
前端开发 Android开发 容器
Android自定义Tablayout下划线指示器Indicator:设置宽高、圆角、渐变颜色
Android自定义Tablayout下划线指示器Indicator:设置宽高、圆角、渐变颜色 Android原生的Tablayout下面有一个指示器(指示线、下划线),如图所示:详情见附录1。
6348 0