注:本文由BeyondVincent(破船)原创首发
转载请注明出处:BeyondVincent(破船)@DevDiv.com
更多内容请查看下面的帖子
[DevDiv原创]Windows 8 开发Step by Step
小引
在Windows 8的开始屏幕上全是一些方块,当我们用鼠标或者手去触摸时,会有不同的按下倾斜效果,移动的时候也会有放大+半透明的效果。这效果非常的cool。那么这篇博文,我就在自定义一下Button,让其具有类似的效果(Tile内容更新的效果不在此范围,或许在以后的文章中我会写,此文只讨论按下、移动效果)。
注:我在这里称这样的按钮为TileButton
自定义TileButton的关键技术
A、继承自Button,这样会方便很多,只需要做极少部分的处理
B、截获按下事件,首先分析按下位置,然后根据位置做不同的效果
C、移动过程中,对按钮做放大和半透明处理,增加用户体验
制作步骤
1、新建空白工程,名称为BV_TileButton
2、在项目工程上单击右键,选择添加->选择类->输入BV_TileButton,然后确定
3、打开BV_TileButton.cs文件:
里面的内容如下:
/*
* ==============================================================================
* Filename: BV_TileButton.cs
*
* Description:
* TileButton实现了按下、拖动等效果,有点类似开始屏幕那些磁贴的按下、拖动效果、还支持缩放、旋转等。
* 还存在的问题:在边界按下时,进行拖动没有效果,暂时不知道如何处理
*
* Version: 1.0
* Created: 2012/11/15 21:32:23
*
* Author: BeyondVincent(破船)
* http://weibo.com/beyondvincent
* qq:77973689
* ==============================================================================
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
namespace BV_TileButton
{
class BV_TileButton : Button
{
// 翻转效果
PlaneProjection projection;
// 移动、缩放、旋转等转换
CompositeTransform transform;
// 按下时,倾斜的角度
int angle = 10;
// 拖动多远时,开始移动空间
double dragoffx = 5;
double dragoffy = 5;
// 构造函数 做一些初始化工作
public BV_TileButton()
{
projection = new PlaneProjection();
Projection = projection;
transform = new CompositeTransform();
RenderTransform = transform;
ManipulationMode = ManipulationModes.Rotate | ManipulationModes.Scale | ManipulationModes.TranslateX | ManipulationModes.TranslateY;
}
/*
* 按下时的事件处理,两个步骤
* 1、首先判断当前按下去的位置在控件的那个区域(控件共分为9个区域,详见PressPointLocation定义)
* 2、根据按下去的位置,对控件做不同的效果
*/
protected override void OnPointerPressed(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
// 获得当前区域位置
PressPointLocation location = GetPointLocation(e.GetCurrentPoint(this).Position);
// 开始对控件做效果处理
if (location == (PressPointLocation.Left | PressPointLocation.YCenter))
{// 左中
projection.RotationY = angle;
projection.CenterOfRotationX = 1;
}
else if (location == (PressPointLocation.Left | PressPointLocation.Top))
{// 左上
projection.RotationX = -angle;
projection.RotationY = angle;
projection.CenterOfRotationX = 1;
projection.CenterOfRotationY = 1;
}
else if (location == (PressPointLocation.Top | PressPointLocation.XCenter))
{// 上中
projection.RotationX = -angle * 2;
projection.CenterOfRotationY = 1;
}
else if (location == (PressPointLocation.Right | PressPointLocation.Top))
{// 右上
projection.RotationY = projection.RotationX = -angle;
projection.CenterOfRotationX = 0;
projection.CenterOfRotationY = 1;
}
else if (location == (PressPointLocation.Right | PressPointLocation.YCenter))
{// 右中
projection.RotationY = -angle;
projection.CenterOfRotationX = 0;
}
else if (location == (PressPointLocation.Right | PressPointLocation.Bottom))
{// 右下
projection.RotationX = angle;
projection.RotationY = -angle;
projection.CenterOfRotationX = 0;
projection.CenterOfRotationY = 0;
}
else if (location == (PressPointLocation.Bottom | PressPointLocation.XCenter))
{// 下中
projection.RotationX = angle * 2;
projection.CenterOfRotationY = 0;
}
else if (location == (PressPointLocation.Left | PressPointLocation.Bottom))
{// 左下
projection.RotationY = projection.RotationX = angle;
projection.CenterOfRotationX = 1;
projection.CenterOfRotationY = 1;
}
else if (location == (PressPointLocation.XCenter | PressPointLocation.YCenter))
{// 正中
CompositeTransform transform = RenderTransform as CompositeTransform;
transform.CenterX = ActualWidth/2;
transform.CenterY = ActualHeight/2;
transform.ScaleX = 0.9;
transform.ScaleY = 0.9;
}
}
/*
* 按下放开时的事件处理
* 主要是做一些还原处理(旋转角度归零、缩放还原、透明度设置等)
*/
protected override void OnPointerReleased(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
projection.RotationX = 0;
projection.RotationY = 0;
CompositeTransform transform = RenderTransform as CompositeTransform;
transform.CenterX = ActualWidth / 2;
transform.CenterY = ActualHeight / 2;
transform.ScaleX = 1;
transform.ScaleY = 1;
Opacity = 1;
dragoffx = 0;
dragoffy = 0;
}
/*
* 有移动等操作时的事件处理
* 主要包括移动、放大、透明等
*/
protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
{
dragoffx += e.Delta.Translation.X;
dragoffy += e.Delta.Translation.Y;
if (-10 <= dragoffx && dragoffx <= 10 && -10 <= dragoffy && dragoffy <= 10)
return;
transform.CenterX = ActualWidth / 2;
transform.CenterY = ActualHeight / 2;
transform.ScaleX = 1.1;
transform.ScaleY = 1.1;
Opacity = 0.5;
projection.RotationX = 0;
projection.RotationY = 0;
transform.TranslateX += e.Delta.Translation.X;
transform.TranslateY += e.Delta.Translation.Y;
transform.ScaleX *= e.Delta.Scale;
transform.ScaleY *= e.Delta.Scale;
transform.Rotation += e.Delta.Rotation;
base.OnManipulationDelta(e);
}
/*
* 获取控件所在的区域算法
*/
PressPointLocation GetPointLocation(Point point)
{
PressPointLocation location = PressPointLocation.None;
double tempwidth = ActualWidth / 3;
if (point.X < tempwidth)
{
location |= PressPointLocation.Left;
}
else if (point.X > tempwidth * 2)
{
location |= PressPointLocation.Right;
}
else
{
location |= PressPointLocation.XCenter;
}
double tempheight = ActualHeight / 3;
if (point.Y < tempheight)
{
location |= PressPointLocation.Top;
}
else if (point.Y > tempheight * 2)
{
location |= PressPointLocation.Bottom;
}
else
{
location |= PressPointLocation.YCenter;
}
Debug.WriteLine(location.ToString());
return location;
}
}
public enum PressPointLocation
{
None = 0,
Left = 1,
Top = 2,
Right = 4,
Bottom = 8,
XCenter = 16,
YCenter = 32
}
/*
* 获取指定控件的Rect
*/
public static class BV_ToolAPI
{
public static Rect GetElementRect(this FrameworkElement element)
{
GeneralTransform buttonTransform = element.TransformToVisual(null);
Point point = buttonTransform.TransformPoint(new Point());
return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
}
}
}
代码有详细注释,在此不过多讲解。
4、在MainPage.xaml文件中,添加如下代码:
注意:其中3行3列的girid控件是为了演示效果,为控件划分不同的区域。在实际开发中,不需要。
<Page
x:Class="BV_TileButton.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BV_TileButton"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="Green">
<local:BV_TileButton HorizontalAlignment="Center" Height="150" VerticalAlignment="Center" Width="310" >
<local:BV_TileButton.Content>
<Grid Margin="0 0 0 0">
<Image Source="Assets/widelogo.png" Margin="-15,-9,-16,-10"/>
<Image Source="Assets/logo.png" Margin="-19,94,234,-6"/>
<TextBlock Text="5" FontSize="30" Foreground="Red" Margin="244,90,0,0"/>
<TextBlock Text="读书的女孩子,很好噢" FontSize="25" FontFamily="宋体" Foreground="Magenta" Margin="7,20,10,72"/>
<Grid Margin="-15,-9,-16,-10" Visibility="Visible">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="0" Grid.Row="0"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="0" Grid.Row="1"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="0" Grid.Row="2"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="1" Grid.Row="0"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="1" Grid.Row="1"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="1" Grid.Row="2"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="2" Grid.Row="0"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="2" Grid.Row="1"/>
<Border BorderThickness="1" BorderBrush="Red" Grid.Column="2" Grid.Row="2"/>
</Grid>
</Grid>
</local:BV_TileButton.Content>
</local:BV_TileButton>
</Grid>
</Page>
5、运行效果展示:
6、代码下载: