WP7应用开发笔记(11) 自定义按钮

不知不觉写了很多东西,不过结构有点乱了,写完了需要整理一下。回顾一下界面设计,这草图又要出来献丑了。

除了已经实现的圆形触控控件以外,其他按钮都是圆环+图片的方式,有比较有写一个自定义控件,取个名字叫RoundButton。

 

RoundButton类

RoundButton具有和Button相同的行为和视觉状态,唯一区别是RoundButton拥有图标

那么继承Button并添加依赖属性ImageSource类型为ImageSource。

再添加一个ImageBrush用于绘制图片。

代码如下:

    public class RoundButton : Button
{
protected ImageBrush OpacityImageBrush;
private const string OpacityImageBrushName = "OpacityImageBrush";

public RoundButton()
{
DefaultStyleKey = typeof(RoundButton);
}

public readonly DependencyProperty ImageSourceProperty
= DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(RoundButton), new PropertyMetadata(OnImageSourceChanged));

private static void OnImageSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var sender = o as RoundButton;

if (sender == null || e.NewValue == e.OldValue)
return;

sender.SetImageBrush(e.NewValue as ImageSource);
}

public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();
OpacityImageBrush = GetTemplateChild(OpacityImageBrushName) as ImageBrush;

if (ImageSource == null)
ImageSource = new BitmapImage(new Uri("/VirtualKeyboard.Controls;component/Icons/word.ok.png", UriKind.RelativeOrAbsolute));
else
SetImageBrush(ImageSource);
}

private void SetImageBrush(ImageSource imageSource)
{
if (OpacityImageBrush == null)
return;

OpacityImageBrush.ImageSource = imageSource;
}
}

 

 

RoundButton模板

编写好RoundButton类后还需要编写其模板已呈现出圆形按钮的效果

基本模板由两个重叠的圆Ellipse构成:

<StackPanel>
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Margin="3">
<Ellipse
x:Name="ButtonBackground"
Stroke
="{TemplateBinding BorderBrush}"
StrokeThickness
="{StaticResource PhoneStrokeThickness}"
Fill
="{TemplateBinding Background}"
Margin
="{StaticResource PhoneTouchTargetOverhang}" />
<Ellipse
x:Name="ButtonForeground"
Fill
="{TemplateBinding Foreground}"
Margin
="{StaticResource PhoneTouchTargetOverhang}">
<Ellipse.OpacityMask>
<ImageBrush x:Name="OpacityImageBrush" />
</Ellipse.OpacityMask>
</Ellipse>
</Grid>
</StackPanel>

呈现如下:

 

为了对输入响应我需要按下的视觉状态VisualState Pressed 通过VisualStateGroups添加相应的动画板Storyboard实现

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="ButtonForeground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

 

呈现效果:

完整XAML代码

 

View Code
<Style TargetType="local:RoundButton">
<Setter Property="BorderBrush" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="12" />
<Setter Property="Padding" Value="10,3,10,5"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RoundButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneContrastBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="ButtonForeground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel>
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Margin="3">
<Ellipse
x:Name="ButtonBackground"
Stroke
="{TemplateBinding BorderBrush}"
StrokeThickness
="{StaticResource PhoneStrokeThickness}"
Fill
="{TemplateBinding Background}"
Margin
="{StaticResource PhoneTouchTargetOverhang}" />
<Ellipse
x:Name="ButtonForeground"
Fill
="{TemplateBinding Foreground}"
Margin
="{StaticResource PhoneTouchTargetOverhang}">
<Ellipse.OpacityMask>
<ImageBrush x:Name="OpacityImageBrush" />
</Ellipse.OpacityMask>
</Ellipse>
</Grid>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


完成播放器界面布局

有了按钮,我还PS了一套图标,将RoundButton设置好布局后效果如下,是不是有点感觉了。

posted @ 2012-01-26 14:12  kiminozo  阅读(1552)  评论(5编辑  收藏  举报