Android系統如何?UI的自適應

來源:互聯網
上載者:User

http://www.cnblogs.com/melaniedeng/archive/2012/05/17/2506869.html

   
   
   

做Android應用的人都知道,要一個apk適用多個不同的手機螢幕是很容易的,就是在項目的res檔案夾下面有多套相關的資源檔。程式啟動並執行時候,Android系統會根據當前裝置的資訊去載入不同檔案夾下的資源檔。但是Android系統是怎麼做到這一點的呢?上網上搜了一下,很少有這方便的介紹,只好自己研究下代碼了。下面是我研究代碼得到的結果(正確性有待確認),在這裡分享一下。

這裡以ICS上在Activity的onCreate()方法裡面調用setContentView(int resourceID)為例,介紹一下系統如何根據我們的id(R.layout.xxxx)找到合適的layout檔案進行解析載入:

如果你的res下面有三種不同的layout:layout, layout-sw480dp和 layout-sw600dp,這裡的sw<N>dp表示這個layout檔案夾下面的布局檔案只有在裝置短邊的最小寬頻為N時才載入。你的裝置是800x480的解析度,那麼這個apk安裝在你的裝置上就會載入 layout-sw480dp裡面的布局檔案。下面是framework的java層調用鏈:

Activity.setContentView(int resourceID) -> PhoneWindow.setContentView(int resourceID) -> LayoutInflater.inflate(int resource, ViewGroup root) -> LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot) -> Resources.getLayout(int id) ->
Resources.loadXmlResourceParser(int id, String type) -> Resources.getValue(int id, TypedValue outValue, boolean resolveRefs) -> AssetManager.getResourceValue(int ident, int density, TypedValue outValue, boolean resolveRefs) -> AssetManager.loadResourceValue(int
ident, short density, TypedValue outValue, boolean resolve)

在上面的掉用鏈中:

1. 最後載入的是哪個xml是由Resources.getValue(int id, TypedValue outValue, boolean resolveRefs)調用完成之後的outValue.string決定的,因為outValue.string的值就是你的資源檔的具體路徑,如:

  1) xxx/values/xxx.xml

  2) xxx/layout-sw600dp/xxx.xml

2. AssetManager.loadResourceValue()調的是frameworks/base/core/jni/android_util_AssetManager.cpp裡面的native方法, 如何獲得正確的outValue值,在native方法倆面主要有以下幾步:

  1) 調用frameworks/base/libs/utils/ResourceTypes.cpp 的ResTable::getResource(),遍曆所有資源檔

  2) 在ResTable::getResource()裡面調用ResTable::getEntry()來確定資源檔來自哪個entry,即layout,或者layout-sw<N>dp,由此可見,ResTable::getEntry()是我們這個問題的關鍵

  3) 在ResTable::getEntry()裡面:

    a) 首先擷取本裝置的configurion資訊,螢幕解析度,螢幕大小,locale,橫豎屏等。

    b) 根據得到的本裝置的configurion資訊,過濾掉不適應本裝置的entry,比如裝置是800x480的,那麼超過此解析度的資源(例:layout-sw600dp)就要被過濾掉,實現在frameworks/base/include/utils/ResourceTypes.h中ResTable_config的match函數中

    c) 對過濾後的resource進行最佳適配,找到最符合的entry檔案。因為之前已經將不符合的,即大解析度的entry已經被過濾掉了,所以這裡就找剩下的最大的就是最佳適配的。實現在frameworks/base/include/utils/ResourceTypes.h中ResTable_config的isBetterThan()函數中。

3. 我做了一個嘗試,就是想讓800x480解析度的裝置上的應用都載入 layout-sw600dp裡面的資源檔。所以將上面b)步驟的frameworks/base/include/utils/ResourceTypes.h裡面ResTable_config的match函數改動如下:

?
/*if (smallestScreenWidthDp != 0&& smallestScreenWidthDp > settings.smallestScreenWidthDp){return false;}*/if
(smallestScreenWidthDp != 0
&& smallestScreenWidthDp > 600) {return
false;}

我將settings.smallestScreenWidthDp強制換成了600,這樣的話,所有比600dp小的(包含600)在內的資源檔在做過濾時就被保留了下來,而c)步驟不做檢查,只找最大的,所以layout-sw600dp就成了系統認為的“最合適”的資源問價了。

將重新編譯frameworks/base/libs/utils/產生的lib庫push到/system/libs下面,再重啟手機,然後啟動上述應用,就可以了看見程式載入的layout-sw600dp的ui了。

    

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.