MetroGridHelper: A helpful debugging assistant for designers and developers alike

You’ve heard me preach it before: fix those margins, align, and try and make your apps as beautiful and inspiring as you can (see also: my designer tips for developers).

On Thursday, I stopped by the Windows Phone Design Team’s beautiful studio space here on campus. It’s a really creative space, packed with fun people, chill music, and a genuine desire to see even better, more beautiful apps in the marketplace.

While sitting with two of the UX designers, Corrina and Arturo, and talking about some of these design principles, I just happened to be introduced to a nifty, albeit simple, gridline/grid that the team’s been using for some time while working on the Windows Phone. It’s just a set of red squares, 25×25 pixels, offset 12 pixels from one another, and all contained within a page padding of 24px. (Again: the magical Metro number is 12-based on those edges)

The design typically will use a Photoshop layer containing these squares, or maybe some XAML inserted on top of a page in an app, to work on alignment, visualizing the grid, etc., and making tweaks.

I got to thinking: it would be nice if this could be just like the performance counters that we have for the Windows Phone: at debug time, you could opt into overlaying this grid on top of the frame of the entire app, being omnipresent. I coded up a quick implementation during that meeting and here it is!

To use the counter, simply open up the App.xaml.cs file (where the other performance counters are) and add this in. I’d recommend just enabling it when you want to do a quick design pass. You can use this then both with apps on your phone as well as the emulator; it’s helpful in the emulator since you can then screenshot the UI and share that with your friends and family who can critique you on your pixel placement.

?
// Show graphics profiling information while debugging.
if (System.Diagnostics.Debugger.IsAttached)
{
    // Display the current frame rate counters.
    Application.Current.Host.Settings.EnableFrameRateCounter = true;
    // Display the metro grid helper.
    MetroGridHelper.IsVisible = true;

Here’s what it looks like at runtime in a very simple app:


PhoneMetro

In this example, I have one of the classic Windows Phone design “bugs”: one of the TextBlocks has just been inserted, without using the appropriate standard phone style. As a result, it has a Margin value of “0” instead of being 12 pixels offset from the left. It’s more clear now with the squares, since you can see the misalignment easily.

I’ve also added simple static properties for Opacity and Color if you’d rather not use the Red default color and ~0.15 opacity on the squares. The IsVisible property can be flipped off at runtime, but beware that the grid is still present in the visual tree once you add it – so there will be a performance hit (don’t ship an app that uses the grid in release builds).

Get the source

I’ve published the source file on NuGet – that’s a really easy way to get the file into your project, and if I make any fixes or add features in the future, it’ll be easy for you to get those changes:

  • Make sure you have NuGet installed (http://www.nuget.org/)
  • Install the package using the console or package manager. It is called MetroGridHelper

    PM> Install-Package MetroGridHelper

Or you can drop this source code into a new file of your project, MetroGridHelper.cs:

// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;namespace System.Windows
{/// <summary>/// A utility class that overlays a designer-friendly grid on top of the /// application frame, for use similar to the performance counters in/// App.xaml.cs. The color and opacity are configurable. The grid contains /// a number of squares that are 24x24, offset with 12px gutters, and all/// 24px away from the edge of the device./// </summary>public static class MetroGridHelper{private static bool _visible;private static double _opacity = 0.15;private static Color _color = Colors.Red;private static List<Rectangle> _squares;private static Grid _grid;/// <summary>/// Gets or sets a value indicating whether the designer grid is /// visible on top of the application's frame./// </summary>public static bool IsVisible{get{return _visible;}set{_visible = value;UpdateGrid();}}/// <summary>/// Gets or sets the color to use for the grid's squares./// </summary>public static Color Color{get { return _color; }set{_color = value;UpdateGrid();}}/// <summary>/// Gets or sets a value indicating the opacity for the grid's squares./// </summary>public static double Opacity{get { return _opacity; }set{_opacity = value;UpdateGrid();}}/// <summary>/// Updates the grid (if it already has been created) or initializes it/// otherwise./// </summary>private static void UpdateGrid(){if (_squares != null){var brush = new SolidColorBrush(_color);foreach (var square in _squares){square.Fill = brush;}if (_grid != null){_grid.Visibility = _visible ? Visibility.Visible : Visibility.Collapsed;_grid.Opacity = _opacity;}}else{BuildGrid();}}/// <summary>/// Builds the grid./// </summary>private static void BuildGrid(){_squares = new List<Rectangle>();var frame = Application.Current.RootVisual as Frame;if (frame == null || VisualTreeHelper.GetChildrenCount(frame) == 0){Deployment.Current.Dispatcher.BeginInvoke(BuildGrid);return;}var child = VisualTreeHelper.GetChild(frame, 0);var childAsBorder = child as Border;var childAsGrid = child as Grid;if (childAsBorder != null){// Not a pretty way to control the root visual, but I did not// want to implement using a popup.var content = childAsBorder.Child;if (content == null){Deployment.Current.Dispatcher.BeginInvoke(BuildGrid);return;}childAsBorder.Child = null;Deployment.Current.Dispatcher.BeginInvoke(() =>{Grid newGrid = new Grid();childAsBorder.Child = newGrid;newGrid.Children.Add(content);PrepareGrid(frame, newGrid);});}else if (childAsGrid != null){PrepareGrid(frame, childAsGrid);}else{Debug.WriteLine("Dear developer:");Debug.WriteLine("Unfortunately the design overlay feature requires that the root frame visual");Debug.WriteLine("be a Border or a Grid. So the overlay grid just isn't going to happen.");return;}}/// <summary>/// Does the actual work of preparing the grid once the parent frame is/// in the visual tree and we have a Grid instance to work with for/// placing the chilren./// </summary>/// <param name="frame">The phone application frame.</param>/// <param name="parent">The parent grid to insert the sub-grid into.</param>private static void PrepareGrid(Frame frame, Grid parent){var brush = new SolidColorBrush(_color);_grid = new Grid();_grid.IsHitTestVisible = false;// To support both orientations, unfortunately more visuals need to// be used. An alternate implementation would be to react to the// orientation change event and re-draw/remove squares.double width = frame.ActualWidth;double height = frame.ActualHeight;double max = Math.Max(width, height);for (int x = 24; x < /*width*/ max; x += 37){for (int y = 24; y < /*height*/ max; y += 37){var rect = new Rectangle{Width = 25,Height = 25,VerticalAlignment = System.Windows.VerticalAlignment.Top,HorizontalAlignment = System.Windows.HorizontalAlignment.Left,Margin = new Thickness(x, y, 0, 0),IsHitTestVisible = false,Fill = brush,};_grid.Children.Add(rect);_squares.Add(rect);}}_grid.Visibility = _visible ? Visibility.Visible : Visibility.Collapsed;_grid.Opacity = _opacity;// For performance reasons a single surface should ideally be used// for the grid._grid.CacheMode = new BitmapCache();// Places the grid into the visual tree. It is never removed once// being added.
            parent.Children.Add(_grid);}}
}

 

转载于:https://www.cnblogs.com/Yukang1989/archive/2013/01/18/2866160.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

马斯克和贝索斯的“星球大战”

全世界只有3.14 % 的人关注了数据与算法之美商业太空计划已经蓬勃发展了十年。在这个领域中&#xff0c;最雄心勃勃的两家公司当属Blue Origin&#xff08;蓝色起源&#xff09;和SpaceX&#xff08;太空探索技术公司&#xff09;&#xff0c;而它们之间的竞争一直是众人的焦点…

java pojo 是什么_什么是POJO

POJO(Plain Old Java Objects)简单的Java对象&#xff0c;实际就是普通JavaBeans&#xff0c;是为了避免和EJB混淆所创造的简称。在Java应用程序中的角色使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接. 其中有一些属性及其gettersetter方法的类,没有业务逻辑&#xf…

JMeter基础知识

2019独角兽企业重金招聘Python工程师标准>>> 1.JMeter常用术语 1&#xff09;采样器&#xff08;Samplers&#xff09; 采样器是JMeter测试脚本的基础单元&#xff0c;用户可以用他来向服务器发出一个特定的请求&#xff0c;比如HTTP请求、JAVA请求。 2&#xff…

开年趣图汇总:对不起,让你笑了这么久

全世界只有3.14 % 的人关注了数据与算法之美房东家小孩抓周&#xff0c;感觉不管抓什么都很有未来....计算机语言成就一段恋情程序员&#xff0c;千万别像他学习如果编程语言是工具你这工作怎么越做越晚呢&#xff1f;那一刻&#xff0c;程序员露出了尴尬又不失礼貌的微笑这个名…

【视频回放】Best of Build Tour in China 暨 Watching Party - 大湾区专场

活动介绍微软一年一度的Build大会已经在5月25-27日盛大召开&#xff0c;今年的主题演讲&#xff0c;全球CEO Satya Nadella从开发者速度&#xff0c;智能云原生应用&#xff0c;以及在混合工作场景下提高生产力等诸多话题进行探讨。为了让技术社区和开发者更好地了解微软Build大…

Entity Framework Core 6.0 预览4 性能改进

起因微软在Build2021开发者大会上,发布Entity Framework Core 6.0(简称EFCore 6)预览第四版,号称是性能版本,性能提升主要对于Entity Framework Core 5.性能改进:EFCore 5.0和EFCore 6.0基准测试,提升了70%.在查询时,比EFCore5.0提升了31%.内存改进了不少,减少43%.减少内存分配…

这个地球仪太惊艳了,陪孩子畅聊天文地理。

▲数据汪特别推荐点击上图进入玩酷屋一个人一旦对某事物有了浓厚的兴趣&#xff0c;就会主动去求知、去探索、去实践&#xff0c;并在求知、探索、实践中产生愉快的情绪和体验。所以&#xff0c;古今中外的教育家无不重视兴趣在智力开发中的作用。小木之前推荐过一款AR地球仪&a…

两篇很牛的vim使用技巧

2019独角兽企业重金招聘Python工程师标准>>> 读本文之前请注意&#xff1a; 1. 本文的目标是提供一些vim的使用技巧&#xff0c;利用这些技巧可以提高vim的操作效率。部分技巧在vi上也可以使用&#xff0c;但是现在基本上都是用vim了。 2. 本文是整理和总结使用技巧…

辍学程序员改变世界,这位长得像马云的90后要击败Facebook的扎克伯格了…

全世界只有3.14 % 的人关注了数据与算法之美众所周知&#xff0c;Facebook的创始人扎克伯格&#xff08;Mark Zuckerberg&#xff09;&#xff0c;是史上最年轻的世界亿万富豪。小扎作为社交网络时代的的缔造者&#xff0c;成为了当之无愧的程序员界80后杰出代表。但数据汪今天…

java十六进制大小端转换_字节顺序

1、定义 字节顺序,又称端序或尾序(英语:Endianness),在计算机科学领域中,指电脑内存中或在数字通信链路中,组成多字节的字的字节的排列顺序。 在几乎所有的机器上,多字节对象都被存储为连续的字节序列。 2、表现形式 字节的排列方式有两个通用规则。例如,将一个多位数的…

Android开发入门之学习笔记(三):程序窗口的布局

2019独角兽企业重金招聘Python工程师标准>>> Android应用程序的用户界面可以看作是由View和View Group组成的&#xff0c;从字面意思上就可以看出&#xff0c;View Group是可以包含多个View的。借用官方教程的图可以更容易理解&#xff1a; 说到这里&#xff0c;我…

c#爬虫-解决ChromeDriver 版本问题

问题Selenium c# 进行爬虫时报错 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 84产生问题的原因因为下载的ChromeDriver版本与本地chrome浏览器的版本不一致导致的。因…

用gradle启动java项目_构建Java项目

#构建Java项目#上一节我们简要介绍了如何编写一个单机的To Do应用&#xff0c;接下来要打包部署成可执行的应用&#xff0c;我们需要编译源代码&#xff0c;生成的class文件需要打包到JAR文件中。JDK提供了javac 和jar工具帮助你实现这些任务&#xff0c;但是你也不想每次源代码…

今天,滴滴被爆亏损109亿,需裁员2000多人,哪些员工会被裁掉?

全世界只有3.14 % 的人关注了数据与算法之美近日&#xff0c;一份滴滴出行内部流传出来的财务数据显示&#xff0c;该公司2018年持续巨额亏损&#xff0c;全年亏损高达109亿元人民币。若消息属实&#xff0c;那将说明&#xff0c;自2012年滴滴成立以来就一直处于亏损状态&#…

限时秒杀┃“探月计划”来袭,美国米德天文望远镜助孩子观月赏月

▲数据汪特别推荐点击上图进入玩酷屋孩子对于未知的世界充满了好奇&#xff0c;尤其是对于月亮&#xff0c;总是有问不完的问题。例如月亮上是怎么样的&#xff1f;怎么很多人说十五的月亮十六圆&#xff1f;月亮有动物吗&#xff1f;不是说有月兔吗&#xff1f;月亮怎么有时是…

话里话外:企业管理软件的方案设计要规避哪些风险

博主推荐延展咨询资深顾问 梁云文章 企业管理软件作为帮助企业管理者优化工作流程&#xff0c;改善管理水平的信息化工具&#xff0c;现如今被大多数的企业接受并在不同层面进行了应用。作为企业管理软件的方案设计者&#xff0c;我们必须从企业管理者、软件操作者的不同视…

java使用zmodem_SecureCRT 中使用zmodem和Linux服务器交换文件

注意&#xff1a;Linux在默认安装的情况下是没有sz和rz这两条指令的&#xff0c;rmp包为&#xff1a;lrzsz-xx.xx-xxx.rpm&#xff0c;用rmp –q lrzsz查看是否安装&#xff0c;没有的话安装&#xff1a;命令&#xff1a;rpm –ivh lrzsz-xx.xx-xxx.rpm安装后查看&#xff1a;1…

每次有人来家里,总有人问我这个积木在哪买的

▲数据汪特别推荐点击上图进入玩酷屋作为一名资深积木达人&#xff0c;小木我可是大大小小的积木阅览无数&#xff0c;当然乐高也不会放过&#xff0c;虽然“钱包君”已经是路人了。&#xff08;每月的工资用来买乐高~&#xff09;之前给大家推荐了一款STEAM积木&#xff0c;小…

NET问答: 为什么时间格式 dd/MM/yyyy 转成 DateTime 会报错?

咨询区 Shantanu Gupta&#xff1a;我在项目中碰到了一个需求&#xff0c;需要将字符串格式的 dd/MM/yyyy 转成 DateTime&#xff0c;比如下面这样&#xff1a;class Program{static void Main(string[] args){var str "22/11/2009";DateTime date DateTime.Parse(s…

Gallery with Video

2019独角兽企业重金招聘Python工程师标准>>> 实现较为完整的图片展示和视频播放功能&#xff08;Image and video gallery&#xff09;&#xff0c;在FGallery-iPhone&#xff08; http://code4app.com/codesample/4f67f4546803fa6d45000001&#xff09;代码的基础上…