日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

[转] Android系统如何实现UI的自适应

發(fā)布時間:2025/3/15 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转] Android系统如何实现UI的自适应 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:?http://www.cnblogs.com/melaniedeng/archive/2012/05/17/2506869.html

?

?

做Android應用的人都知道,要一個apk適用多個不同的手機屏幕是很容易的,就是在項目的res文件夾下面有多套相關的資源文件。程序運行的時候,Android系統(tǒng)會根據當前設備的信息去加載不同文件夾下的資源文件。但是Android系統(tǒng)是怎么做到這一點的呢?上網上搜了一下,很少有這方便的介紹,只好自己研究下代碼了。下面是我研究代碼得到的結果(正確性有待確認),在這里分享一下。

?

這里以ICS上在Activity的onCreate()方法里面調用setContentView(int resourceID)為例,介紹一下系統(tǒng)如何根據我們的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就成了系統(tǒng)認為的“最合適”的資源問價了。

?

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

轉載于:https://www.cnblogs.com/jalenwang/archive/2012/09/01/android-resouces.html

總結

以上是生活随笔為你收集整理的[转] Android系统如何实现UI的自适应的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。