Windows Store apps开发[52]Button控件的自定义——模仿开始屏幕中磁贴的按下、移动效果

注:本文由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、代码下载:
http://www.devdiv.com/thread-169767-1-1.html


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值