如何充分利用 Windows Phone 高清屏幕

Nokia 最近发布两款6寸大屏手机:Lumia 1520 和 Lumia 1320。为了支持这种设备 WP 升级了操作系统GDR3 支持了 1080P 的高清分辨率(1520),虽然GER3 是提供了向下兼容的,当然 GDR3 同时支持一些特性来支持 1080P 高清屏幕。

一下所有的讨论的代码实现都在 这里

Windows Phone 7 开始实现了统一分辨率规范 WVGA ( 800 x 480 ),一般适用与 3.7 - 4.3 寸屏。 在 Windows Phone 8 扩展支持了多种分辨率(3种) WVGA,WXGA(768 x 1280),和 720P(720 x 1280),但是他们支持的物理尺寸多数是在 4 – 4.5寸之间,并且无论应用运行在何种分辨率的机器上我们都是从基础分辨率(800 x 480)进行适配,例如 720P 分辨率,屏幕的宽高比是 16:9,它会从基础分辨率进行1.5倍的放大,但是由于宽高比的原因,实际缩放前的分辨率是 480 x 853,高度多出53个像素来适应 720P 的分辨率。 另外 768 x 1280 和基础分辨率的屏幕宽高比都是 15:9 的所以可以直接进行一个 1.6 的屏幕缩放即可。

随着 Windows Phone 8 的 GDR3 的发布,不仅有一个(1920 x 1080)高清分辨率的加入,同样随之带来一些和大屏是手机兼容性的问题。例如一个相同页面在 3.7 寸屏幕上显示和在一个 6寸设备上显示的不同效果,和用户体验。

3.7 inch and 6 inch phones

理论上讲,Windows Phone 也许会运行在更大(7“)屏的设备上,所以我们在需要的时候充分的利用屏幕,至少要在应用中知道我们当前是在何种分辨率的设备中,但是如果我们什么都不做的情况下系统会帮我们进行一个 720P 的应用适配(为了兼容现有应用),也就是从480 x 853进行缩放,但是他不是简单的从 720P 缩放到 1080P,系统会从新渲染而所有控件到 1080P。

所以我们现有的App 可以继续运行在 1080P 的设备上且不会收到影响,但是针对一个新应用我们怎么做才能更好的适配一个1080P的设备呢?例如:检测到当前设备是支持1080P的时候我们播放的视频进行一个适配,所以在GDR3 SDK支持一对新的可侦测属性参数。PhysicalScreenResolution 和 RawDpiX

image

  public partial class BasicInfo : PhoneApplicationPage
  {
    public BasicInfo()
    {
      InitializeComponent();
    }

    string GetBasicScreenInfo()
    {
      var width = App.Current.Host.Content.ActualWidth;
      var height = App.Current.Host.Content.ActualHeight;
      var scaleFactor = (double)App.Current.Host.Content.ScaleFactor / 100d;

      return String.Format("{0} x {1}; {2:0.0} scale factor", width, height, scaleFactor);
    }

    string GetExtendedScreenInfo()
    {
      object temp;
      if (!DeviceExtendedProperties.TryGetValue("PhysicalScreenResolution", out temp))
        return "not available, sorry";

      var screenResolution = (Size)temp;

      // Can query for RawDpiY as well, but it will be the same value
      if (!DeviceExtendedProperties.TryGetValue("RawDpiX", out temp) || (double)temp == 0d)
        return "not available, sorry";

      var dpi = (double)temp;
      var screenDiagonal = Math.Sqrt(Math.Pow(screenResolution.Width / dpi, 2) +
                  Math.Pow(screenResolution.Height / dpi, 2));

      var width = App.Current.Host.Content.ActualWidth;

      return String.Format("{0} x {1}; {2:0.0#} raw scale; {3:0.0}\"", screenResolution.Width, screenResolution.Height, screenResolution.Width / width, screenDiagonal);
    }

    void GetScreenInfoClick(object sender, RoutedEventArgs e)
    {
      basicScreenInfoOutput.Text = GetBasicScreenInfo();
      extendedScreenInfoOutput.Text = GetExtendedScreenInfo();
    }
  }
}

例如 在GDR3 Lumia 920 中运行以上代码的效果:

920_info

在 720P 模拟器中运行的效果(没有GDR3的更新):

emu_info

在6寸设备上运行效果,(基础信息和 720P相同):

6inch_info

但是我们可以获取到一些实际的数值来帮助开发者更好的适配自己的应用。

ZoomBox control

在上面提到的代码示例中有一个叫做 ZoomBox的控件,类似于ViewBox,但是ViewBox可以让内部控件比他本身更大,但是你可以结合 DisplayInformationEx使用,可以更好的适应屏幕。(这里使用了一个滑块 slider 来调整控件区域的大小)

细心的同学可以看到随着滑块的滑动 文字/图片/控件 大小的变化(文字可以自动换行),实际上我们可以在这里使用任何缩放的数值,来根据实际的屏幕尺寸。

920_zoom_1     920_zoom_2

Rendering size – aware content

正如前面说到的不论我们在何种分辨率下进行开发我们在 XAML 中都是用 800*480 这基础分辨率下进行的设计。但是会有这样的一种情况出现,一个4.5寸设备分辨率是480pixels,如果相同的分辨率到一个6寸的设备上那就相当于每一个像素都放大了33%,实际大小就相当于原有的638px的大小。DisplayInformationEx 可以计算这些数值并且配合缩放来使得控件大小看上去一致。

名称解析:

Raw Pixels : 原始像素值 = 实际硬件上的像素数量,例如1080P的设备横向拥有1080个像素点。

Host Pixels:设计/基础 像素 = 在我们设计应用的时候 xaml runtime 提供的像素数,例如所以设备的基数像素点都是480pixels。

View Pixels:显示像素 = 通过DisplayInformationEx 计算适配后 ZoomBox显示出来的像素数,同时和机器的屏幕物理尺寸相关。

有一种情况 例如 Nokia Lumia 820(4.3”) 它的Raw Pixels,Host Pixels,以及 View Pixels 都是相同的。但是在更高分辨率的机器上就会不同了。

示例中的代码是使用 ZoomBox在 Lumia 920中显示一个硬币保持硬币的直径在 0.75“。

920_penny

在上面的这张图中看到 通过ZoomBox的修正,让 155px的 硬币在1.6倍放大的屏幕上(4.5”)表现出与原始大小相符的图片。

另外看一下在 6寸屏幕上显示的效果:

proto_penny

对比一下 lumia 920 和 6寸设备显示的效果。

proto_920_penny

ZoomBox 和 DisplayInformationEx 的使用方法

<screenSizeSupport:ZoomBox

ZoomFactor="{Binding DisplayInformationEx.ViewPixelsPerHostPixel,

  Source={StaticResource DisplayInformationEmulator}}">

<StackPanel>

<Image Source="/Assets/one_cent.png" Width="155" x:Name="scaledPenny"/>

<TextBlock Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap"

      Text="computed size (0.75&quot;)" />

</StackPanel>

</screenSizeSupport:ZoomBox>

And the code to render the penny:

const double sizeOfUsPenny = 0.75;

private void ResizePenny()

{

var width = App.DisplayInformationEmulator.DisplayInformationEx

.GetViewPixelsForPhysicalSize(sizeOfUsPenny);

  scaledPenny.Width = width;

}

DisplayInformationEx and DisplayInformationEmulator

代码中用到的DisplayInformationEx 可以看做是从 DisplayInformation class 中扩展出来的一些属性 来帮助我们得到设备的一些物理设备属性。

DisplayInformationEx_diagram

注意多数信息都是要在GDR3下才可以使用。

为了使用方便推荐将DisplayInformationEmulator添加到系统级资源中,并且支持数据绑定。

<Application.Resources>

<screenSizeSupport:DisplayInformationEmulator x:Key="DisplayInformationEmulator"/>

</Application.Resources>

代码示例中提供了两周访问 DisplayInformationEmulator 的方法 使用开始画面中的 view & change emulated size 或者使用屏幕右上角的 change display size 的图标,然后在 new display values 中选择不同的手机分辨率来模拟不同手机出现的效果。

6inch_physical     6inch_effective     920_change

如果你想固定在一种屏幕尺寸下进行调试可以直接修改 EmulatedScreenInfo="6.5,1080,1.778" 属性。

例如:

<screenSizeSupport:DisplayInformationEmulator x:Key="DisplayInformationEmulator"

  EmulatedScreenInfo="6.5,1080,1.778"/>

以上是在 GDR3 在 1080P 高清屏幕上开发应用的一些技巧分享给大家:)

欢迎大家在这里和我沟通交流或者在新浪微博上 @王博_Nick