和手机屏幕一样,高分屏在PC上使用越来越多。传统的桌面程序都是像素为单位进行UI布局,而且是适配传统的96dpi的显示器的。这就导致这些程序在高分屏上显示很小,用户用起来很难受。

虽然windows系统提供了桌面程序自动放大功能,但这个放大效果是以牺牲显示效果为代价的,一个在普屏上显示很好的软件到了高分屏上显示变得非常粗糙。

要解决这个问题非常麻烦,对于有些项目甚至变成不可能完成的任务:

如果使用同一套布局,布局系统需要支持放大时使用的字体的重建,还需要支持放大时使用的图片资源的重新获取,还需要支持放大时布局位置的自动调整,然而上述3条实现任意一条都不容易。

如果使用不同的布局,就是说为普屏配置一套布局,为高分屏配置另一套布局,尽管麻烦,理论上也是可行的,但还有新的问题:维护成本高,一个地方UI元素的调整可能需要修改两个不同的布局文件;不适应动态调整,对于多显示器有不同DPI的情况,很难做到DPI的动态切换。

Android系统对于DPI的支持比较理想(IOS没有研究):

首先Android的布局语言使用的坐标一般都用dp,sp为单位,也就是说在布局的时候,UI的位置,字体的大小都是dpi无关的,无论在高分屏还是普屏下显示的大小都是一样的。

对于图片,Android系统提供适配多种DPI的图片资源包,如果开发者只提供一种资源包,则使用这个资源包适配目标屏幕的dpi进行缩放,同样达到类似dpi无关的显示效果。

当然Android系统适配手机通常只有一个屏幕,不需要做动态DPI切换,这一点是和PC不同的地方。

鉴于我对于Android还有些经验,SOUI的dpiaware工作主要是参考Android的设计。

如前所述,要在一套UI布局中支持dpiaware,SOUI需要支持DPI变化时的字体重建,布局坐标重排,图片资源重新获取3部分工作。

首先明确DPI是布局元素相关的,SOUI中最基本的布局元素就是SWindow对象,要在SOUI实现DpiAware, 我们在DPI变化时给每个SWindow发一个UM_DIPCHANGED消息,SWindow对象收到这个消息后处理自己持有的字体,图片的重建,完成后请求宿主重新执行布局操作。

1 字体重建:SOUI有一个UI中使用的字体Pool,在窗口中保存有使用的字体的描述,DPI变化后直接使用保存的字体描述重新创建新的字体。

2 图片重建:SOUI中使用ISkinObj来代表一个绘制对象,系统内的绘制对象保存在SkinPool中,每一个绘制对象有两个属性:name, scale (scale属性是新增加的),DPI变化时,一个窗口持有的ISkinObj对象到SkinPool中查询name相同但scale不同的ISkinObj,找到了就使用这个新对象绘制,如果没有找到则使用当前图片自动缩放出一个Clone对象,并把它加入到SkinPool里去。

3 重新布局:相对于2.6以前版本的SOUI的布局,2.6版本的坐标描述增加了坐标单位dp,在窗口的位置及大小描述中加上dp就代码这个值是dpi相关的坐标,窗口的DPI变化后自动使用新DPI重新布局。

上面是DPIAware的基本解决方案,当然细节还有很多,具体参见系统代码。

下面我们看一下MultiLangs这个demo如何处理dpiaware。

首先演示图片的自动dpi适配。

1 在资源中增加适配不同DPI的4个图片资源,如下图:

2 在uires.idx里引入这4个图片。

<img>
<file name="pic_100" path="image\pic_100.png"/>
<file name="pic_125" path="image\pic_125.png"/>
<file name="pic_150" path="image\pic_150.png"/>
<file name="pic_200" path="image\pic_200.png"/>
</img>

3 在skin.xml中增加4个skin对象, 注意它们使用相同的name,不同的scale

<skin>
<imglist name="scale_pic" scale="100" src="img:pic_100"/>
<imglist name="scale_pic" scale="125" src="img:pic_125"/>
<imglist name="scale_pic" scale="150" src="img:pic_150"/>
<imglist name="scale_pic" scale="200" src="img:pic_200"/>
</skin>

4 最后就是在布局XML中引用该skin对象,直接使用name引用即可,不需要关注scale

<page title="page1">
<img skin="scale_pic" pos="|0,|0" offset="-0.5,-0.5"/>
<window pos="20,20,@100dp,@30dp" colorBkgnd="rgba(255,0,0,128)">100dp*30dp</window>
</page>

到此完成了图片的配置。

字体和布局的DPIAware很简单,只需要在那些需要dpi自动缩放的位置或者字体大小数字后加上dp即可,可参考上面的XML, pos,size,width, height等属性都可以通过加dp来实现dpiaware。

DpiAware至此完成!

启程软件  2017年5月4日

在SOUI中支持高分屏显示的更多相关文章

  1. 在VC++6.0开发中实现全屏显示

    全屏显示是一些应用软件程序必不可少的功能.比如在用VC++编辑工程源文件或编辑对话框等资源时,选择菜单“View\Full Screen”,即可进入全屏显示状态,按“Esc”键后会退出全屏显示状态. ...

  2. SystemUI中设置横竖屏显示

    SystemUI中快捷菜单有 “方向锁定” . RotationLockTile protected void handleClick() { if (mController == null) ret ...

  3. mui禁止横屏显示,仅支持竖屏显示

    mui.plusReady(function () { plus.screen.lockOrientation("portrait-primary"); });

  4. c# Winform 开发分屏显示应用程序

    分屏显示即可把一台主机内运行的多个程序分别显示在不同的两个(或多个)屏幕上.目前市面上主流的显卡都支持分屏显示(显示双屏幕),如果需要显示2个以上的屏幕,则应使用“拖机卡”类的硬件. 设置分屏显示的两 ...

  5. iOS 中各种横竖屏切换总结

    iOS 中横竖屏切换的功能,在开发iOS app中总能遇到.以前看过几次,感觉简单,但是没有敲过代码实现,最近又碰到了,demo尝试了几种情况,这里就做下总结.注意 横屏两种情况是反的你知道吗? UI ...

  6. Android开发中的全屏背景显示方案

    引子 不管是Android还是iOS平台中,都可以看到一些应用在启动的时候会先出现一个启动画面(Splash Activity),如QQ.微信等.这个启动画面中往往会将ActionBar和Status ...

  7. C# WinForm中 让控件全屏显示的实现代码

    夏荣全 ( lyout(at)163.com )原文 C#中让控件全屏显示的实现代码(WinForm) 有时候需要让窗口中某一块的内容全屏显示,比如视频播放.地图等等.经过摸索,暂时发现两种可行方法, ...

  8. QT中关于窗口全屏显示与退出全屏的实现

    近期在学习QT时遇到了很多问题这也是其中一个,个人通过在各种书籍和网络上的查阅找到了一些关于这方面的答案,希望能给大家一些帮助. 首先,在QT中对于窗口显示常用的有这么几个方法可以调用: Qt全屏显示 ...

  9. 在一个没有设置宽高的容器中,为什么设置position:absolute后就可以全屏显示了?

    此场景适用于移动端百分比布局,背景全屏显示. 在一个没有设置宽高的容器中设置背景,想要背景全屏显示,设置bcakground-size:100%;后还需设置position:absolut; 原因: ...

随机推荐

  1. 一个蛋疼的CTF图片隐写

    话不多说,直接上原题 TIPS:心中无码 打开解题链接,是一张png图片,直接用16进制编辑器打开,没有附加其它文件.看下文件区段信息也很正常. 又拖进stegsolve,Blue的0位很不正常 多次 ...

  2. scrapy学习笔记

    1.scrapy用哪条命令行重新编辑已有的项目?cd projectname 2.如何在pycharm中开启scrapy?先在终端创建一个项目(即文件夹),再在pycharm中打开.

  3. Day4 数据库的建立||数据库对外查询||使用命令行来操作数据库

    ###数据库的创建 建立一个项目 先进行测试,测试新项目是否可以成功运行 创建一个PersonContrary包,并建立一个Person类实现BaseColumns借口,在此类中添加所有的表的列名,并 ...

  4. [译]Selenium Python文档:目录

    作者:Baiju Muthukadan 协议:本文档采用知识共享署名 - 共享4.0国际许可. 原英文网址:http://selenium-python.readthedocs.io/index.ht ...

  5. Tcl与Design Compiler (三)——DC综合的流程

    本文属于原创手打(有参考文献),如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner 1.基本流程概述 首先 ...

  6. sql语句实现累计数

    前言,要实现按某个字段统计,直接用count/sum……group by语句就可以实现,但是要实现累计统计,比如按时间累计统计,从12月3号开始累计数据,比如:4号统计3.4号的数据,5号统计3.4. ...

  7. Spring+SpringMVC+MyBatis+easyUI整合优化篇(七)图片上传功能

    日常啰嗦 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合>讲了富文本编辑器UEditor的整合与使用 ...

  8. JAVA经典算法40题

    1: JAVA经典算法40题 2: [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 3 ...

  9. Timer,TimerTask通过程序计数器实现的定时任务

    1.程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看 做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型, 各种虚 ...

  10. 2017腾讯实习生Android客户端开发面试总结

    欢迎访问我的个人博客转发请注明出处:http://wensibo.top/2017/04/13/2017Tencent_review/ 前言 先做个自我介绍,本人大三狗一枚,就读的是广州一个普通的一本 ...