在SOUI中支持高分屏顯示

和手機屏幕同樣,高分屏在PC上使用愈來愈多。傳統的桌面程序都是像素爲單位進行UI佈局,並且是適配傳統的96dpi的顯示器的。這就致使這些程序在高分屏上顯示很小,用戶用起來很難受。windows

雖然windows系統提供了桌面程序自動放大功能,但這個放大效果是以犧牲顯示效果爲代價的,一個在普屏上顯示很好的軟件到了高分屏上顯示變得很是粗糙。佈局

要解決這個問題很是麻煩,對於有些項目甚至變成不可能完成的任務:字體

若是使用同一套佈局,佈局系統須要支持放大時使用的字體的重建,還須要支持放大時使用的圖片資源的從新獲取,還須要支持放大時佈局位置的自動調整,然而上述3條實現任意一條都不容易。ui

若是使用不一樣的佈局,就是說爲普屏配置一套佈局,爲高分屏配置另外一套佈局,儘管麻煩,理論上也是可行的,但還有新的問題:維護成本高,一個地方UI元素的調整可能須要修改兩個不一樣的佈局文件;不適應動態調整,對於多顯示器有不一樣DPI的狀況,很難作到DPI的動態切換。spa

Android系統對於DPI的支持比較理想(IOS沒有研究):設計

首先Android的佈局語言使用的座標通常都用dp,sp爲單位,也就是說在佈局的時候,UI的位置,字體的大小都是dpi無關的,不管在高分屏仍是普屏下顯示的大小都是同樣的。code

對於圖片,Android系統提供適配多種DPI的圖片資源包,若是開發者只提供一種資源包,則使用這個資源包適配目標屏幕的dpi進行縮放,一樣達到相似dpi無關的顯示效果。xml

固然Android系統適配手機一般只有一個屏幕,不須要作動態DPI切換,這一點是和PC不一樣的地方。對象

鑑於我對於Android還有些經驗,SOUI的dpiaware工做主要是參考Android的設計。blog

如前所述,要在一套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日

相關文章
相關標籤/搜索