zoukankan      html  css  js  c++  java
  • MetroGridHelper:WP7设计师与开发人员的得力助手

    作为沉浸于开发行业多年的老手,大家一定对这些话题并不陌生:整理页面边距、对齐图像内容以及让自己的应用程序更美观。随着软件消费者中“外貌协会”成员的比重不断上升,用户界面不够抢眼的应用几乎已经无法在市场上占得一席之地。

    不久前,我有幸参加了Windows Phone设计团队举办的“美观开发空间”活动。我要由衷地赞叹,这是一次真正的创意空间交流活动,到处是有趣的参与者、舒缓的音乐以及为市场创造出更好、更漂亮的应用程序的热烈渴求。

    在活动中我一直坐在两位用户体验设计师Corrina与Arturo身边,与他们讨论设计工作中的原则性取向;很偶然地,我们的话题转移到一副简洁 而相当美观的网格图上,这也正是二位在Windows Phone平台上开发的主要焦点。图像由多个红色正方形构成,每个方形为25x25像素,两个方形之间相隔12像素,也就是说每个独立单元都拥有宽高为 24像素的反衬背景。(还是那句话,Metro风格要求边框长度始终为12的整数)

    设计将使用典型的Photoshop层来容纳这些方形,或者是在应用程序页面之上插入XAML借以完成图形对齐、网格设计及位置调整等等。

    我的想法是:如果最终外观设计方案能够与Windows Phone上现有的性能计数器相似,那么肯定会大受欢迎——在调试时,我们能够将这套网格重叠覆盖在整个应用程序框架上,使其成为独立而完整的全局显示方 案。就在活动过程当中,我即兴用代码将自己的想法表达了出来,下面请大家分享我的成果。

    要使用这款计数器,我们只需打开App.xaml.cs文件(这里囊括了其它多款性能计数器),并将其添加进来。如果大家只是打算简单设计一下,那 么我建议各位直接将其启用,这样一来我们就能够让它作用于实机及模拟器中的应用程序。之所以要把它与模拟器关联起来,是因为我们能够将最终显示效果通过截 图与朋友及家人分享,并聆听他们在图像位置方面提出的意见。

    1. // Show graphics profiling information while debugging.  
    2. if (System.Diagnostics.Debugger.IsAttached)  
    3. {  
    4.     // Display the current frame rate counters.  
    5.     Application.Current.Host.Settings.EnableFrameRateCounter = true;  
    6.    
    7.     // Display the metro grid helper.  
    8.     MetroGridHelper.IsVisible = true; 

    以下是这段简单的代码在与小型应用程序协作时显示出的效果:

    效果

    在这个例子中,我遇到了Windows Phone设计中的经典“bug”:文本信息区块之一在插入过程中未能正确显示应有的Metro风格。也就是说,该区块的左侧边距为“0”,而不是 Metro要求的12像素,这使得对应文字内容比其它字体更靠左。通过上图中正方形的对比,相信大家能更清晰地理解我遇到的问题,字体错位现象十分明显。

    如果大家不喜欢默认的红色以及~0.15的不透明度,我还为不透明度及颜色添加了简单的静态属性设置选项,希望能让各位获得自己理想中的方形单元效 果。在运行过程中,可见属性不会显示出来,但请大家注意,只要网格本身仍然存在于可视化元素列表当中,就会占用对应的性能资源(因此请务必在应用程序的发 布版本中把网格去掉,否则会造成毫无意义的资源浪费)。

    源代码

    我已经在NuGet上发布过源文件——这应该是大家在自己的项目中使用这款小成品的最佳方式。如果今后我做出任何修正或添加某些功能,各位也将会在NuGet网站上及时找到最新版本。

    ◆确保自己已经安装了NuGet(http://www.nuget.org/)

    ◆使用控制台或软件包管理器安装该软件包,我把它命名为MetroGridHelper

    PM> Install-Package MetroGridHelper

    当然,大家也可以将这部分源代码在项目中整理成一个全新的文件,MetroGridHelper.cs:

    1. // (c) Copyright Microsoft Corporation.  
    2. // This source is subject to the Microsoft Public License (Ms-PL).  
    3. // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.  
    4. // All other rights reserved.  
    5.  
    6. using System.Collections.Generic;  
    7. using System.Diagnostics;  
    8. using System.Windows.Controls;  
    9. using System.Windows.Media;  
    10. using System.Windows.Shapes;  
    11.  
    12. namespace System.Windows  
    13. {  
    14.     /// <summary>  
    15.     /// A utility class that overlays a designer-friendly grid on top of the  
    16.     /// application frame, for use similar to the performance counters in  
    17.     /// App.xaml.cs. The color and opacity are configurable. The grid contains  
    18.     /// a number of squares that are 24x24, offset with 12px gutters, and all  
    19.     /// 24px away from the edge of the device.  
    20.     /// </summary>  
    21.     public static class MetroGridHelper  
    22.     {  
    23.         private static bool _visible;  
    24.         private static double _opacity = 0.15;  
    25.         private static Color _color = Colors.Red;  
    26.         private static List<Rectangle> _squares;  
    27.         private static Grid _grid;  
    28.    
    29.         /// <summary>  
    30.         /// Gets or sets a value indicating whether the designer grid is  
    31.         /// visible on top of the application's frame.  
    32.         /// </summary>  
    33.         public static bool IsVisible  
    34.         {  
    35.             get 
    36.             {  
    37.                 return _visible;  
    38.             }  
    39.             set 
    40.             {  
    41.                 _visible = value;  
    42.                 UpdateGrid();  
    43.             }  
    44.         }  
    45.    
    46.         /// <summary>  
    47.         /// Gets or sets the color to use for the grid's squares.  
    48.         /// </summary>  
    49.         public static Color Color  
    50.         {  
    51.             get { return _color; }  
    52.             set 
    53.             {  
    54.                 _color = value;  
    55.                 UpdateGrid();  
    56.             }  
    57.         }  
    58.    
    59.         /// <summary>  
    60.         /// Gets or sets a value indicating the opacity for the grid's squares.  
    61.         /// </summary>  
    62.         public static double Opacity  
    63.         {  
    64.             get { return _opacity; }  
    65.             set 
    66.             {  
    67.                 _opacity = value;  
    68.                 UpdateGrid();  
    69.             }  
    70.         }  
    71.    
    72.         /// <summary>  
    73.         /// Updates the grid (if it already has been created) or initializes it  
    74.         /// otherwise.  
    75.         /// </summary>  
    76.         private static void UpdateGrid()  
    77.         {  
    78.             if (_squares != null)  
    79.             {  
    80.                 var brush = new SolidColorBrush(_color);  
    81.                 foreach (var square in _squares)  
    82.                 {  
    83.                     square.Fill = brush;  
    84.                 }  
    85.                 if (_grid != null)  
    86.                 {  
    87.                     _grid.Visibility = _visible ? Visibility.Visible : Visibility.Collapsed;  
    88.                     _grid.Opacity = _opacity;  
    89.                 }  
    90.             }  
    91.             else 
    92.             {  
    93.                 BuildGrid();  
    94.             }  
    95.         }  
    96.    
    97.         /// <summary>  
    98.         /// Builds the grid.  
    99.         /// </summary>  
    100.         private static void BuildGrid()  
    101.         {  
    102.             _squares = new List<Rectangle>();  
    103.    
    104.             var frame = Application.Current.RootVisual as Frame;  
    105.             if (frame == null || VisualTreeHelper.GetChildrenCount(frame) == 0)  
    106.             {  
    107.                 Deployment.Current.Dispatcher.BeginInvoke(BuildGrid);  
    108.                 return;  
    109.             }  
    110.    
    111.             var child = VisualTreeHelper.GetChild(frame, 0);  
    112.             var childAsBorder = child as Border;  
    113.             var childAsGrid = child as Grid;  
    114.             if (childAsBorder != null)  
    115.             {  
    116.                 // Not a pretty way to control the root visual, but I did not  
    117.                 // want to implement using a popup.  
    118.                 var content = childAsBorder.Child;  
    119.                 if (content == null)  
    120.                 {  
    121.                     Deployment.Current.Dispatcher.BeginInvoke(BuildGrid);  
    122.                     return;  
    123.                 }  
    124.                 childAsBorder.Child = null;  
    125.                 Deployment.Current.Dispatcher.BeginInvoke(() =>  
    126.                 {  
    127.                     Grid newGrid = new Grid();  
    128.                     childAsBorder.Child = newGrid;  
    129.                     newGrid.Children.Add(content);  
    130.                     PrepareGrid(frame, newGrid);  
    131.                 });  
    132.             }  
    133.             else if (childAsGrid != null)  
    134.             {  
    135.                 PrepareGrid(frame, childAsGrid);  
    136.             }  
    137.             else 
    138.             {  
    139.                 Debug.WriteLine("Dear developer:");  
    140.                 Debug.WriteLine("Unfortunately the design overlay feature requires that the root frame visual");  
    141.                 Debug.WriteLine("be a Border or a Grid. So the overlay grid just isn't going to happen.");  
    142.                 return;  
    143.             }  
    144.         }  
    145.    
    146.         /// <summary>  
    147.         /// Does the actual work of preparing the grid once the parent frame is  
    148.         /// in the visual tree and we have a Grid instance to work with for  
    149.         /// placing the chilren.  
    150.         /// </summary>  
    151.         /// <param name="frame">The phone application frame.</param>  
    152.         /// <param name="parent">The parent grid to insert the sub-grid into.</param>  
    153.         private static void PrepareGrid(Frame frame, Grid parent)  
    154.         {  
    155.             var brush = new SolidColorBrush(_color);  
    156.    
    157.             _grid = new Grid();  
    158.             _grid.IsHitTestVisible = false;  
    159.    
    160.             // To support both orientations, unfortunately more visuals need to  
    161.             // be used. An alternate implementation would be to react to the  
    162.             // orientation change event and re-draw/remove squares.  
    163.             double width = frame.ActualWidth;  
    164.             double height = frame.ActualHeight;  
    165.             double max = Math.Max(width, height);  
    166.    
    167.             for (int x = 24; x < /*width*/ max; x += 37)  
    168.             {  
    169.                 for (int y = 24; y < /*height*/ max; y += 37)  
    170.                 {  
    171.                     var rect = new Rectangle  
    172.                     {  
    173.                         Width = 25,  
    174.                         Height = 25,  
    175.                         VerticalAlignment = System.Windows.VerticalAlignment.Top,  
    176.                         HorizontalAlignment = System.Windows.HorizontalAlignment.Left,  
    177.                         Margin = new Thickness(x, y, 0, 0),  
    178.                         IsHitTestVisible = false,  
    179.                         Fill = brush,  
    180.                     };  
    181.                     _grid.Children.Add(rect);  
    182.                     _squares.Add(rect);  
    183.                 }  
    184.             }  
    185.    
    186.             _grid.Visibility = _visible ? Visibility.Visible : Visibility.Collapsed;  
    187.             _grid.Opacity = _opacity;  
    188.    
    189.             // For performance reasons a single surface should ideally be used  
    190.             // for the grid.  
    191.             _grid.CacheMode = new BitmapCache();  
    192.    
    193.             // Places the grid into the visual tree. It is never removed once  
    194.             // being added.  
    195.             parent.Children.Add(_grid);  
    196.         }  
    197.     }  
  • 相关阅读:
    题解 [CF891C] Envy
    题解 [BZOJ4710] 分特产
    题解 [BZOJ2159] Crash的文明世界
    题解 [BZOJ4144] Petrol
    #leetcode刷题之路1-两数之和
    week 7 文件操作与模板
    coursera 北京大学 程序设计与算法 专项课程 STL week8 list
    coursera 北京大学 程序设计与算法 专项课程 完美覆盖
    JSTL标签库不起作用的解决方案 .(转)
    javax.servlet.jsp.PageContext.getELContext()Ljavax/el/ELContext解决办法(转)
  • 原文地址:https://www.cnblogs.com/shihao/p/2550134.html
Copyright © 2011-2022 走看看