在SOUI中支持高分屏显示
和手机屏幕一样,高分屏在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中支持高分屏显示的更多相关文章
- 在VC++6.0开发中实现全屏显示
全屏显示是一些应用软件程序必不可少的功能.比如在用VC++编辑工程源文件或编辑对话框等资源时,选择菜单“View\Full Screen”,即可进入全屏显示状态,按“Esc”键后会退出全屏显示状态. ...
- SystemUI中设置横竖屏显示
SystemUI中快捷菜单有 “方向锁定” . RotationLockTile protected void handleClick() { if (mController == null) ret ...
- mui禁止横屏显示,仅支持竖屏显示
mui.plusReady(function () { plus.screen.lockOrientation("portrait-primary"); });
- c# Winform 开发分屏显示应用程序
分屏显示即可把一台主机内运行的多个程序分别显示在不同的两个(或多个)屏幕上.目前市面上主流的显卡都支持分屏显示(显示双屏幕),如果需要显示2个以上的屏幕,则应使用“拖机卡”类的硬件. 设置分屏显示的两 ...
- iOS 中各种横竖屏切换总结
iOS 中横竖屏切换的功能,在开发iOS app中总能遇到.以前看过几次,感觉简单,但是没有敲过代码实现,最近又碰到了,demo尝试了几种情况,这里就做下总结.注意 横屏两种情况是反的你知道吗? UI ...
- Android开发中的全屏背景显示方案
引子 不管是Android还是iOS平台中,都可以看到一些应用在启动的时候会先出现一个启动画面(Splash Activity),如QQ.微信等.这个启动画面中往往会将ActionBar和Status ...
- C# WinForm中 让控件全屏显示的实现代码
夏荣全 ( lyout(at)163.com )原文 C#中让控件全屏显示的实现代码(WinForm) 有时候需要让窗口中某一块的内容全屏显示,比如视频播放.地图等等.经过摸索,暂时发现两种可行方法, ...
- QT中关于窗口全屏显示与退出全屏的实现
近期在学习QT时遇到了很多问题这也是其中一个,个人通过在各种书籍和网络上的查阅找到了一些关于这方面的答案,希望能给大家一些帮助. 首先,在QT中对于窗口显示常用的有这么几个方法可以调用: Qt全屏显示 ...
- 在一个没有设置宽高的容器中,为什么设置position:absolute后就可以全屏显示了?
此场景适用于移动端百分比布局,背景全屏显示. 在一个没有设置宽高的容器中设置背景,想要背景全屏显示,设置bcakground-size:100%;后还需设置position:absolut; 原因: ...
随机推荐
- 《Machine Learning》系列学习笔记之第四周
第四周 Model Representation I 让我们来看看如何使用神经网络来表示假设函数.在非常简单的水平上,神经元基本上是将输入(树突)作为输入到输出(轴突)的电输入(称为"尖峰& ...
- ehcache 使用笔记
要想使用 java 的本地缓存,可以考虑用 ehcache,或者 guava. guava 更高端一点,可以自动定时刷新.我选择了 ehcache. 在 spring 中是集成了 ehcache 的. ...
- shiro权限控制
1.1 简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Securi ...
- 微信JS图片上传与下载功能--微信JS系列文章(三)
概述 在前面的文章微信JS初始化-- 微信JS系列文章(一)中已经介绍了微信JS初始化的相关工作,接下来本文继续就微信JS的图片上传功能进行描述,供大家参考. 图片上传 $(function(){ v ...
- Android getAttributeIntValue()详解-霞辉
经常使用getAttributeIntValue()方法,但是大多使用的形式是attrs.getAttributeFloatValue(null, "xxx", 0);只是在中间传 ...
- iOS开发之应用沙盒
1.应用沙盒概述 每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应用必须待在自己的沙盒里,其他应用不能访问该沙盒. 应用沙盒的文件系统目录,如下图所示(假设应用的名 ...
- (转)CentoS 下报的 Requires: perl(:MODULE_COMPAT_5.8.8)
vim /etc/yum.repos.d/epel.repo 把 mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5& ...
- mysql技术内幕InnoDB存储引擎-阅读笔记
mysql技术内幕InnoDB存储引擎这本书断断续续看了近10天左右,应该说作者有比较丰富的开发水平,在源码级别上分析的比较透彻.如果结合高可用mysql和高性能mysql来看或许效果会更好,可惜书太 ...
- 组件之间使用Prop传递数据
<div id="example"> <father></father> </div> <script src="h ...
- 在linux下使用百度ueditor编辑器上传图片
百度ueditor编辑器虽然强大,但是也有不足的地方.如果对ueditor流程不是很熟悉可以说走的弯路比较多,费力不讨好.下面呢,就是要解决ueditor遇到的问题. 用ueditor上传图片遇到的问 ...