如何在 wpf 按钮(如 google 按钮)周围创建阴影效果
Posted
技术标签:
【中文标题】如何在 wpf 按钮(如 google 按钮)周围创建阴影效果【英文标题】:How to create a shadow drop effect around a wpf button like the google button 【发布时间】:2012-09-20 01:27:54 【问题描述】:我正在尝试在 wpf 中创建一个 google 按钮。我发现以下链接指定了 google 的按钮 css 样式
Google button css style
我现在也在网上搜了一下,发现这个样式很像google的按钮
<Style x:Key="GoogleGreyButton" TargetType="x:Type Button">
<Setter Property="Background" Value="#FFF5F5F5"/>
<Setter Property="BorderBrush" Value="#FFDCDCDC"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="#FF666666"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="8,7"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="TemplateBinding BorderThickness"
Padding="TemplateBinding Padding"
BorderBrush="TemplateBinding BorderBrush"
CornerRadius="1"
Background="TemplateBinding Background">
<ContentPresenter HorizontalAlignment="TemplateBinding HorizontalContentAlignment"
VerticalAlignment="TemplateBinding VerticalContentAlignment"/>
</Border>
<ControlTemplate.Triggers>
<!--TODO: Set the right colors-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#FFC6C6C4" />
<Setter Property="Foreground" Value="#FF020202" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
` <!--Some setters here--> `
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Trigger Property="IsPressed" Value="True">
部分我需要像上面的Google button css style 那样产生一些阴影效果,请问我该如何实现?
【问题讨论】:
您应该考虑使用表达式混合来创建您的 wpf UI。它很好地满足您的需求 链接失效了。 【参考方案1】:您可以通过更改 BorderThickness 一些来产生阴影效果。试试这样的:
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="DarkGray" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderThickness" Value="1,1,2,2" />
</Trigger>
请注意,这样做可能会稍微弄乱您的布局,因为它会改变按钮的总宽度和高度,因此当悬停按钮时,它周围的其他控件可能会“颠簸”一点。
如果您想使用适当的阴影,可以像这样向按钮添加阴影:
<Button>
<Button.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" Softness="1" ShadowDepth="10" Opacity="0.5" />
</Button.BitmapEffect>
</Button>
编辑:
正如 MrDosu 评论的那样,BitMapEffect 已被弃用,因此您可能应该改用 Effect。
这是一个使用 Effect 的示例:
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="DarkGray" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Button.Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Trigger>
【讨论】:
在 .NET Framework 4 或更高版本中,BitmapEffect 类已过时。如果您尝试使用 BitmapEffect 类,您将得到一个过时的异常。 BitmapEffect 类的非过时替代品是 Effect 类。在大多数情况下,Effect 类的速度要快得多。 还有一个问题,单击按钮后鼠标左键向上的触发属性是什么?我希望按钮在单击后返回IsEnabled
状态。
尝试使用 ToggleButton,BorderThickness 不起作用,但 DropShadowEffect 起作用。【参考方案2】:
过去,我是这样实现材质提升的:
public static class UI
private static readonly DropShadowEffect[] sShadows = new[]
new DropShadowEffect()
BlurRadius = 5,
ShadowDepth = 1
,
new DropShadowEffect()
BlurRadius = 8,
ShadowDepth = 1.5
,
new DropShadowEffect()
BlurRadius = 14,
ShadowDepth = 4.5
,
new DropShadowEffect()
BlurRadius = 25,
ShadowDepth = 8
,
new DropShadowEffect()
BlurRadius = 35,
ShadowDepth = 13
;
public static readonly DependencyProperty ElevationProperty = DependencyProperty.RegisterAttached("Elevation", typeof(double), typeof(UI), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsRender, null, OnElevationChanged));
public static double GetElevation(this UIElement element) => element.GetValue(ElevationProperty) as double? ?? default;
public static void SetElevation(this UIElement element, double elevation) => element.SetValue(ElevationProperty, elevation);
private static object OnElevationChanged(DependencyObject dependencyObject, object value)
if (dependencyObject is UIElement element && value is double elevation)
if (elevation == 0)
element.Effect = null;
else
var effect = CreateElevation(elevation, element.Effect);
if (effect != null)
element.Effect = effect;
return value;
private static void MixShadows(DropShadowEffect target, DropShadowEffect other, double balance)
target.BlurRadius = target.BlurRadius * (1 - balance) + other.BlurRadius * balance;
target.ShadowDepth = target.ShadowDepth * (1 - balance) + other.ShadowDepth * balance;
private static Effect CreateElevation(double elevation, Effect source)
if (elevation < 0 || elevation > 12)
throw new ArgumentOutOfRangeException("Elevation must be between 0 and 12.", nameof(elevation));
elevation = Math.Max(0, elevation / 12 * shadows.Length - 1);
var shadows = sShadows;
var prevIndex = (int)Math.Floor(elevation);
var index = (int)elevation;
var nextIndex = (int)Math.Ceiling(elevation);
var approx = elevation - index;
var shadow = shadows[index];
var modify = false;
if (approx != 0)
MixShadows(shadow, approx < 0 ? shadows[prevIndex] : shadows[nextIndex], Math.Abs(approx));
if (source is DropShadowEffect sourceShadow)
sourceShadow.BlurRadius = shadow.BlurRadius;
sourceShadow.ShadowDepth = shadow.ShadowDepth;
shadow = sourceShadow;
modify = true;
shadow.Direction = 270;
shadow.Color = Color.FromArgb(0xAA, 0, 0, 0);
shadow.Opacity = .42;
shadow.RenderingBias = RenderingBias.Performance;
return modify ? null : shadow;
那么,
<Button local:Elevation="2">Elevated button</Button>
2 到 12 之间的任何值都可以设置为任何UIElement
的高度。
【讨论】:
以上是关于如何在 wpf 按钮(如 google 按钮)周围创建阴影效果的主要内容,如果未能解决你的问题,请参考以下文章
WPF中我设计了一个界面,界面上有个按钮,点击按钮,如何将界面内容保存在电脑指定位置(如:桌面上)。