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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

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

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

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

?

這里以ICS上在Activity的onCreate()方法里面調(diào)用setContentView(int resourceID)為例,介紹一下系統(tǒng)如何根據(jù)我們的id(R.layout.xxxx)找到合適的layout文件進(jìn)行解析加載:

如果你的res下面有三種不同的layout:layout, layout-sw480dp和 layout-sw600dp,這里的sw<N>dp表示這個layout文件夾下面的布局文件只有在設(shè)備短邊的最小寬帶為N時才加載。你的 設(shè)備是800x480的分辨率,那么這個apk安裝在你的設(shè)備上就會加載?layout-sw480dp里面的布局文件。下面是framework的 java層調(diào)用鏈:

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)調(diào)用完成之后的outValue.string決定的,因?yàn)閛utValue.string的值就是你的資源文件的具體路徑, 如:

  1) xxx/values/xxx.xml

  2) xxx/layout-sw600dp/xxx.xml

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

  1) 調(diào)用frameworks/base/libs/utils/ResourceTypes.cpp 的ResTable::getResource(),遍歷所有資源文件

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

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

    a) 首先獲取本設(shè)備的configurion信息,屏幕分辨率,屏幕大小,locale,橫豎屏等。

    b) 根據(jù)得到的本設(shè)備的configurion信息,過濾掉不適應(yīng)本設(shè)備的entry,比如設(shè)備是800x480的,那么超過此分辨率的資源 (例:layout-sw600dp)就要被過濾掉,實(shí)現(xiàn)在frameworks/base/include/utils /ResourceTypes.h中ResTable_config的match函數(shù)中

    c) 對過濾后的resource進(jìn)行最佳適配,找到最符合的entry文件。因?yàn)橹耙呀?jīng)將不符合的,即大分辨率的entry已經(jīng)被過濾掉了,所以這里就找剩 下的最大的就是最佳適配的。實(shí)現(xiàn)在frameworks/base/include/utils/ResourceTypes.h中 ResTable_config的isBetterThan()函數(shù)中。

3. 我做了一個嘗試,就是想讓800x480分辨率的設(shè)備上的應(yīng)用都加載?layout-sw600dp里面的資源文件。所以將上面b)步驟的 frameworks/base/include/utils/ResourceTypes.h里面ResTable_config的match函數(shù)改動 如下:

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

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

?

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


轉(zhuǎn)載于:https://my.oschina.net/zhuzihasablog/blog/205455

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。