![]() |
#2
伍则帝2014-07-08 13:53
设计方案:整个界面主要分为两块:MetroStyle和MetroButton
MetroStyle设计如下: MetroButton设计如下: MetroButton的主要功能是显而易见的,其中主要实现了三个依赖属性:MetroBtnForeImage(绑定Image)、MetroBtnText(绑定Text)、MetroBtnUri(点击MetroButton后跳转Uri)。 实现 MetroButton的制作上参考了烤地瓜的系列教程中ImageButton的制作,只是在其基础上添加了需要的依赖属性和动画。 布局代码:(样式代码太多就不贴了) <grid Name="layout" RenderTransformOrigin="0.5,0.5" > </grid><grid .RenderTransform> <transformgroup> <scaletransform></scaletransform> <skewtransform></skewtransform> <rotatetransform></rotatetransform> <translatetransform></translatetransform> </transformgroup> </grid> <button x:Name="btnMetro" HorizontalAlignment="Center" Style="{DynamicResource MetroButtonStyle}" VerticalAlignment="Center" Tag="{Binding MetroBtnText, ElementName=UserControl}" > <image Name="ForeImage" Source="{Binding MetroBtnForeImage, ElementName=UserControl}" Stretch="Fill" Width="140" Height="140" HorizontalAlignment="Center" VerticalAlignment="Center"></image> </button> 依赖属性定义: /// <summary> /// MetroButton.xaml 的交互逻辑 /// </summary> public partial class MetroButton : UserControl { public MetroButton() { this.InitializeComponent(); } //按钮前景图 public static readonly DependencyProperty MetroBtnForeImageProperty; //按钮文字 public static readonly DependencyProperty MetroBtnTextProperty; //按钮绑定页面uri public static readonly DependencyProperty MetroBtnUriProperty; public ImageSource MetroBtnForeImage { get { return (ImageSource)GetValue(MetroBtnForeImageProperty); } set { SetValue(MetroBtnForeImageProperty, value); } } public string MetroBtnUri { get { return (string)GetValue(MetroBtnUriProperty); } set { SetValue(MetroBtnUriProperty, value); } } public string MetroBtnText { get { return (string)GetValue(MetroBtnTextProperty); } set { SetValue(MetroBtnTextProperty, value); } } static MetroButton() { var metadataImage = new FrameworkPropertyMetadata((ImageSource)null); var metadataText = new FrameworkPropertyMetadata((string)null); var metadataUri = new FrameworkPropertyMetadata((string)null); MetroBtnForeImageProperty = DependencyProperty.RegisterAttached("MetroBtnForeImage", typeof(ImageSource), typeof(MetroButton), metadataImage); MetroBtnTextProperty = DependencyProperty.RegisterAttached("MetroBtnText", typeof(string), typeof(MetroButton), metadataText); MetroBtnUriProperty = DependencyProperty.RegisterAttached("MetroBtnUri", typeof(string), typeof(MetroButton), metadataUri); } } MetroStyle中主要分为了2块:界面布局和页面跳转动画。 界面布局:(主要做的是针对1366*768分辨率的屏幕做的,如果需要适应各种分辨率还需修改) <s:surfacescrollviewer x:Name="GridScrollViewer" VerticalAlignment="Top" HorizontalAlignment="Left" Width="1366" Height="768" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled" PanningMode="HorizontalOnly"> <grid x:Name="OptionGrid" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" VerticalAlignment="Top" Height="768" Width="auto" Background="#00000000" OpacityMask="Black" > </grid><grid .RowDefinitions > <rowdefinition Height="180"></rowdefinition> <rowdefinition Height="152"></rowdefinition> <rowdefinition Height="152"></rowdefinition> <rowdefinition Height="152"></rowdefinition> <rowdefinition Height="136"></rowdefinition> </grid> <grid .ColumnDefinitions > <columndefinition Width="100"></columndefinition> <columndefinition Width="152"></columndefinition> </grid> <textblock Text="开始" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0" FontSize="64" Foreground="White"></textblock> </s:surfacescrollviewer> 跳转动画(布局): <metro:loadanimationcontrol x:Name="LoadControl" Width="1366" Height="768" Visibility="Hidden"> <grid x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5"> </grid><grid .RenderTransform> <transformgroup> <scaletransform></scaletransform> <skewtransform></skewtransform> <rotatetransform></rotatetransform> <translatetransform></translatetransform> </transformgroup> </grid> <rectangle Name="rectangle" Fill="#FF20B1C4" Stroke="Transparent" Width="480" Height="270"> </rectangle><rectangle .RenderTransform> <transformgroup> <scaletransform></scaletransform> <skewtransform></skewtransform> <rotatetransform></rotatetransform> <translatetransform></translatetransform> </transformgroup> </rectangle> <stackpanel Width="auto" Height="auto" HorizontalAlignment="Center" VerticalAlignment="Center"> <image Name="ForwardImage" HorizontalAlignment="Center" Height="206.4" Stretch="Fill" VerticalAlignment="Center" Width="215"></image> </stackpanel> </metro:loadanimationcontrol> 跳转动画(动画): <storyboard x:Key="LoadAnimation" Completed="sb_Completed"> <pointanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="rectangle"> <easingpointkeyframe KeyTime="0" Value="0.5,0.5"></easingpointkeyframe> <easingpointkeyframe KeyTime="0:0:0.3" Value="0.5,0.5"></easingpointkeyframe> </pointanimationusingkeyframes> <doubleanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="rectangle"> <easingdoublekeyframe KeyTime="0:0:0.3" Value="2.90"></easingdoublekeyframe> </doubleanimationusingkeyframes> <doubleanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="rectangle"> <easingdoublekeyframe KeyTime="0:0:0.3" Value="2.90"></easingdoublekeyframe> </doubleanimationusingkeyframes> <doubleanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="rectangle"> <easingdoublekeyframe KeyTime="0:0:0.6" Value="2.90"></easingdoublekeyframe> </doubleanimationusingkeyframes> <doubleanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="rectangle"> <easingdoublekeyframe KeyTime="0:0:0.6" Value="2.90"></easingdoublekeyframe> </doubleanimationusingkeyframes> <doubleanimationusingkeyframes Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="LayoutRoot"> <easingdoublekeyframe KeyTime="0" Value="-1"> </easingdoublekeyframe><easingdoublekeyframe .EasingFunction> <cubicease EasingMode="EaseOut"></cubicease> </easingdoublekeyframe> <easingdoublekeyframe KeyTime="0:0:0.3" Value="1"> </easingdoublekeyframe><easingdoublekeyframe .EasingFunction> <cubicease EasingMode="EaseOut"></cubicease> </easingdoublekeyframe> </doubleanimationusingkeyframes> </storyboard> 跳转动画的实现主要是对一个Rectangle进行翻转并放大,且将MetroButton中的图片置于页面中心,动画播放完后触发Completed事件,执行跳转。 界面布局动态加载MetroButton的实现: 我在项目中添加了两个文件夹:View和Image。Image用于保存页面图标,而View中则保存着相应的页面文件,并且二者中的文件通过文件名一一对应(如:View/v1/Mail.xaml代表着一个页面,相应的在Image/v1下,应存在一个名为Mail.png或Mail.jpg等类型的文件与之对应),在这两个文件夹中还存在子文件夹,在界面加载时,每一个文件夹体现为一个块。 /// <summary> /// MetroStyle.xaml 的交互逻辑 /// </summary> public partial class MetroStyle : Page { private string uri; DirectoryInfo app = null;//页面目录 默认为Application/view DirectoryInfo img = null;//页面图标目录 默认为Application/Image string env; public MetroStyle() { this.InitializeComponent(); env = Environment.CurrentDirectory.Replace("\\bin\\Debug", "");//获取程序根目录 LoadAllApp(); } /// <summary> /// 在主页面加载页面图标 /// </summary> public void LoadAllApp() { defineGrid(); int row = 1; int column = 1; int index = 0; img = new DirectoryInfo(env + "\\Image"); for (int i = 0; i < img.GetDirectories().Length; i++) { index = 0; for (int j = 0; j < app.GetDirectories()[i].GetFiles().Length; j++) { string tmpex = app.GetDirectories()[i].GetFiles()[j].Extension; if (tmpex.Contains("xaml")) { if (row > 3 && j >0) column += 1; if (row > 3 || j == 0) { row = 1; } MetroButton mb = new MetroButton(); //设置页面uri mb.MetroBtnUri = app.GetDirectories()[i].Name + "\\" + app.GetDirectories()[i].GetFiles()[j].Name; //设置图片 mb.MetroBtnForeImage = (ImageSource)new ImageSourceConverter().ConvertFromString(img.GetDirectories()[i].GetFiles()[index].FullName); //设置文字 mb.MetroBtnText = img.GetDirectories()[i].GetFiles()[index].Name.Split('.')[0]; mb.SetValue(Grid.RowProperty, row); mb.SetValue(Grid.ColumnProperty, column); //添加点击事件 mb.PreviewMouseLeftButtonUp += MetroButton_MouseLeftButtonUp; this.OptionGrid.Children.Add(mb); row++; index++; } } column += 2; } } /// <summary> /// 计算Grid大小 /// </summary> public void defineGrid() { app = new DirectoryInfo(env + "\\view"); int sumOfApp = 0; int sumOfPart = app.GetDirectories().Length; int tmp = 0; foreach (DirectoryInfo di in app.GetDirectories()) { sumOfApp = di.GetFiles().Length; int numOfColunm = sumOfApp /2 / 3 + (sumOfApp % 3 > 0 ? 1 : 0); if (tmp == 0) numOfColunm -= 1; for (int i = 0; i < numOfColunm; i++) { ColumnDefinition appColumn = new ColumnDefinition(); appColumn.Width = new GridLength(152); this.OptionGrid.ColumnDefinitions.Add(appColumn); } ColumnDefinition spanColumn = new ColumnDefinition(); spanColumn.Width = new GridLength(50); this.OptionGrid.ColumnDefinitions.Add(spanColumn); tmp++; } } /// <summary> /// /点击MetroButton事件 /// /// <param name="sender"/> /// <param name="e"/> private void MetroButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { uri = (sender as MetroButton).MetroBtnUri; this.ForwardImage.Source = (sender as MetroButton).MetroBtnForeImage; SolidColorBrush rbrg = new SolidColorBrush(getBackgroudColor(this.ForwardImage)); this.rectangle.Fill = rbrg; this.LoadControl.Visibility = Visibility.Visible; Storyboard sb = (Storyboard)this.FindResource("LoadAnimation"); sb.Begin(); } /// <summary> /// 获取图标的背景颜色 /// </summary> /// <param name="img"/> /// <returns></returns> public System.Windows.Media.Color getBackgroudColor(System.Windows.Controls.Image img) { string path = img.Source.ToString().Replace("file:///",""); Bitmap bmp = new Bitmap(path); byte a = bmp.GetPixel(1, 1).A; byte r = bmp.GetPixel(1, 1).R; byte g = bmp.GetPixel(1, 1).G; byte b = bmp.GetPixel(1, 1).B; System.Windows.Media.Color color = System.Windows.Media.Color.FromArgb(a, r, g, b); return color; } /// <summary> /// /动画完成后执行跳转 /// </summary> /// <param name="sender"/> /// <param name="e"/> private void sb_Completed(object sender, EventArgs e) { NavigationService.Navigate(new Uri(@"view\"+uri, UriKind.Relative)); } } |
想做一个win磁贴界面,但wpf还未入门。求实例,求带!