不同生产环境下,有不同的屏幕适配策略。如WPF用<ViewBox>标签包裹控件进行自适应,如安卓中通过分包准备各种大小尺寸的图片资源,如游戏开发中常用的九宫图等等。。。
同样屏幕适配还有很多方式,常见的情况有:
- 不管如何改变分辨率的大小和宽高比,都能保持控件宽高比,但不能保持控件的物理宽高,若超出屏幕则出现水平和垂直滚动条。如高于设计的分辨率宽高比,则控件等比缩小,屏幕左右两边留白;或是控件不缩小,屏幕下部超框,显示垂直滚动条。
- 不管如何改变分辨率的大小和宽高比,都能保持控件宽高比,但不能保持控件的物理宽高,若超出屏幕能够自动调整控件布局的响应式布局。
- 不管如何改变分辨率的大小和宽高比,都能保持控件宽高比,同时能保持控件的物理宽高,即自动缩放控件大小。
在WPF中有时候由于界面过于复杂(多处动态加载等),光是用<ViewBox>标签不一定能满足需求了。现在本文讨论上述第三种自适应方式,在WPF下做尝试。
同一控件在不同分辨率下,能有同样的物理宽高,说明该控件的Width、Height属性值是当程序运行时,根据当前的分辨率动态地由函数计算出来的。可以猜测公式为:
y = Ax + B (A、B为待求的常量)
其中:
- y是控件的Width或Height值,单位是像素。因为要在不同分辨率下保持物理尺寸一致,所以在不同分辨率下的y值(像素)也不一样。
- x是当前分辨率与设计分辨率的比值,是运行时的动态计算出来的。
- A、B是一个待求的常量,所以要通过一组(至少两个)这样的式子做方程组才能求解。当两个分辨率的宽高比一样时,B为0,后面也会解释这一点。
下面先求x值。
public class ScreenResolution { public static double SCALEX = 1.0; public static double SCALEY = 1.0; public static Size StandardSize = new Size(1920, 1080); // 设计分辨率 public static Size ActualSize = new Size(1920, 1080); // 真实分辨率 static ScreenResolution() { ActualSize.Width = SystemParameters.WorkArea.Width; ActualSize.Height = SystemParameters.WorkArea.Height; SCALEX = ActualSize.Width / StandardSize.Width; SCALEY = ActualSize.Height / StandardSize.Height; } }
与设计分辨率相同时,SCALEX = 1。再用(1280*720)分辨率测试,则SCALEX = 0.66。注意,当屏幕下方显示任务栏时,(1920*1080)分辨率下任务栏高40像素,所以实际上的WorkArea.Height = 1040,即SCALEY ≈ 0.963。
然后求常量A、B。
以(1920*1080)为标准分辨率,现在为了保持一个Button控件在不同分辨率下的物理宽高都是(2.54cm*1cm),通过实际操作、不断调整,可得下面的方程组:
宽度:
===>>
高度:
===>>
知道UI控件宽高与当前分辨率对设计分辨率的宽高比值的关系后,前台界面XAML中将一个UI控件(如Button)的宽高进行绑定。
<Button x:Name="btn" Width="{Binding ButtonWidth}" Height="{Binding ButtonHeight}" Content="自适应"/>
然后ViewModel的构造函数中,对ButtonWidth和ButtonHeight属性值赋值,套用公式,A、B常量采用上面求得的结果。
ButtonWidth = 100 * ScreenResolution.SCALEX; ButtonHeight = 40 * ScreenResolution.SCALEY;
因为(1920*1080)与(1028*720)的宽高比完全一致,所以常量B为0。如果两种分辨率宽高比不一致,如(1280*960)就比(1280*720)在高上多了一截,那么就要在上面的式子中加上常量B来调整。
这种自适应的方法适用于调整控件宽高,以及控件位置布局,特别适用于运行时分辨率宽高比与设计的分辨率宽高比不一致的情况。缺点是需要调整的控件都要去计算它的宽高函数,工作量大。
该方式切入点是为保证在不同分辨率下UI在屏幕中显示大小基本与设计分辨率下的效果一致,所以是从物理宽高的角度出发,来计算像素宽高值在不同分辨率下的函数关系的。