最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 換膚技術(shù)資料整理

 更新時間:2017年03月17日 08:52:49   作者:魔都三帥  
這篇文章主要介紹了 Android 換膚技術(shù)總結(jié)的相關(guān)資料,需要的朋友可以參考下

Android換膚技術(shù)總結(jié)

背景

縱觀現(xiàn)在各種Android app,其換膚需求可以歸為

- 白天/黑夜主題切換(或者別的名字,通常2套),如同花順/自選股/天天動聽等,UI表現(xiàn)為一個switcher。
- 多種主題切換,通常為會員特權(quán),如QQ/QQ空間。

對于第一種來說,目測應(yīng)該是直接通過本地theme來做的,即所有圖片/顏色的資源都在apk里面打包了。

而對于第二種,則相對復(fù)雜一些,由于作為一種線上服務(wù),可能上架新皮膚,且那么多皮膚包放在apk里面實在太占體積了,所以皮膚資源會在選擇后再進行下載,也就不能直接使用android的那套theme。

技術(shù)方案

內(nèi)部資源加載方案和動態(tài)下載資源下載兩種。

動態(tài)下載可以稱為一種黑科技了,因為往往需要hack系統(tǒng)的一些方法,所以在部分機型和新的API上有時候可能有坑,但相對好處則很多

- 圖片/色值等資源由于是后臺下發(fā)的,可以隨時更新
- APK體積減小
- 對應(yīng)用開發(fā)者來說,換膚幾乎是透明的,不需要關(guān)心有幾套皮膚
- 可以作為增值服務(wù)賣錢!!

內(nèi)部資源加載方案

內(nèi)部資源加載都是通過android本身那套theme來做的,相對業(yè)務(wù)開發(fā)來說工作量更大(需要定義attr和theme),不同方案類似地都是在BaseActivity里面做setTheme,差別主要在解決以下2個問題的策略:

- setTheme后如何實時刷新,而不用重新創(chuàng)建頁面(尤其是listview里面的item)。
- 哪些view需要刷新,刷新什么(背景?字體顏色?ImageView的src?)。

自定義view

MultipleTheme

做自定義view是為了在setTheme后會去立即刷新,更新頁面UI對應(yīng)資源(如TextView替換背景圖和文字顏色),在上述項目中,則是通過對rootView進行遍歷,對所有實現(xiàn)了ColorUiInterface的view/viewgroup進行setTheme操作來實現(xiàn)即使刷新的。

顯然這樣太重了,需要把應(yīng)用內(nèi)的各種view/viewgroup進行替換。

手動綁定view和要改變的資源類型

Colorful

這個…我們看看用法吧….

ViewGroupSetter listViewSetter = new ViewGroupSetter(mNewsListView);
// 綁定ListView的Item View中的news_title視圖,在換膚時修改它的text_color屬性
listViewSetter.childViewTextColor(R.id.news_title, R.attr.text_color);

// 構(gòu)建Colorful對象來綁定View與屬性的對象關(guān)系
mColorful = new Colorful.Builder(this)
  .backgroundDrawable(R.id.root_view, R.attr.root_view_bg)
  // 設(shè)置view的背景圖片
  .backgroundColor(R.id.change_btn, R.attr.btn_bg)
  // 設(shè)置背景色
  .textColor(R.id.textview, R.attr.text_color)
  .setter(listViewSetter) // 手動設(shè)置setter
  .create(); // 設(shè)置文本顏色

我就是想換個皮膚,還得在activity里自己去設(shè)置要改變哪個view的什么屬性,對應(yīng)哪個attribute?是不是成本太高了?而且activity的邏輯也很容易被弄得亂七八糟。

動態(tài)資源加載方案

resource替換

覆蓋application的getResource方法,實現(xiàn)自己的resource,優(yōu)先加載本地皮膚包文件夾下的資源包,對于性能問題,可以通過attribute或者資源名稱規(guī)范(如需要換膚則用skin_開頭)來優(yōu)化,從而不對不換膚的資源進行額外檢查開銷。

不過由于Android5.1源碼里,drawable初始化的時候調(diào)用的是loadDrawable,而不是resource.getDrawable,而loadDrawable是私有的方法,無法覆蓋,所以雖然很方便,卻無法繼續(xù)使用(不用關(guān)心任何皮膚相關(guān)的事情,android:color指定顏色就行了,神奇滴會自動換膚)。

自定義LayoutInflator.Factory

開源項目可參照Android-Skin-Loader。

即setFactory使用自定義的LayoutInflator.Factory,可以重點關(guān)注該項目中的SkinInflaterFactory和SkinManager(實現(xiàn)了自己的getColor、getDrawable、getBitmap、getColorStateList等等方法)。

需要自定義一個tag比如app:customStyle,重寫所有的style,轉(zhuǎn)成set方法,這樣帶來的犧牲就是增加了換膚的成本,要寫很多style,自己去set,并不完全透明了。

Hack Resources internally

黑科技方法,直接對Resources進行hack,Resources.Java:

// Information about preloaded resources. Note that they are not
// protected by a lock, because while preloading in zygote we are all
// single-threaded, and after that these are immutable.
private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
  = new LongSparseArray<Drawable.ConstantState>();
private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists
  = new LongSparseArray<ColorStateList>();

直接對Resources里面的這三個LongSparseArray進行替換,由于apk運行時的資源都是從這三個數(shù)組里面加載的,所以只要采用interceptor模式:

public class DrawablePreloadInterceptor extends LongSparseArray<Drawable.ConstantState>

自己實現(xiàn)一個LongSparseArray,并通過反射set回去,就能實現(xiàn)換膚,具體getDrawable等方法里是怎么取preload數(shù)組的,可以自己看Resources的源碼。

等等,就這么簡單?,NONO,少年你太天真了,怎么去加載xml,9patch的padding怎么更新,怎么打包/加載自定義的皮膚包,drawable的狀態(tài)怎么刷新,等等。這些都是你需要考慮的,在存在插件的app中,還需要考慮是否會互相覆蓋resource id的問題,進而需要修改apt,把resource id按位放在2個range。

手Q和獨立版QQ空間使用的是這種方案,效果挺好。

總結(jié)

盡管動態(tài)加載方案比較黑科技,可能因為系統(tǒng)API的更改而出問題,但相對來說

好處有

- 靈活性高,后臺可以隨時更新皮膚包
- 相對透明,開發(fā)者幾乎不用關(guān)心有幾套皮膚,不用去定義各種theme和attr,甚至連皮膚包的打包都可以交給設(shè)計或者專門的同學(xué)
- apk體積節(jié)省

存在的問題

沒有完善的開源項目,如果我們采用動態(tài)加載的第二種方案,需要的項目功能包括:

- 自定義皮膚包結(jié)構(gòu)
- 換膚引擎,加載皮膚包資源并load,實時刷新。
- 皮膚包打包工具
- 對各種rom的兼容

如果有這么一個項目的話,就一勞永逸了,有興趣的同學(xué)可以聯(lián)系一下,大家一起搞一搞。

內(nèi)部加載方案大同小異,主要解決的都是即時刷新的問題,然而從目前的一些開源項目來看,仍然沒有特別簡便的方案。讓我選的話,我寧愿讓界面重新創(chuàng)建,比如重啟activity,或者remove所有view再添加回來(或者你可能想遍歷rootview,然后一個個檢查是否需要換膚然后set…)。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • Android實現(xiàn)圖像切換器

    Android實現(xiàn)圖像切換器

    這篇文章主要為大家詳細介紹了Android實現(xiàn)圖像切換器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Android實現(xiàn)快遞物流跟蹤布局效果

    Android實現(xiàn)快遞物流跟蹤布局效果

    本篇文章主要介紹了Android實現(xiàn)快遞跟蹤布局效果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Android 百度地圖marker中圖片不顯示的解決方法(推薦)

    Android 百度地圖marker中圖片不顯示的解決方法(推薦)

    下面小編就為大家分享一篇Android 百度地圖marker中圖片不顯示的解決方法(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android頂欄定時推送消息

    Android頂欄定時推送消息

    在用安卓設(shè)備時,經(jīng)常會應(yīng)用到彈出推送消息。接下來通過本文給大家介紹Android頂欄定時推送消息,感興趣的朋友一起學(xué)習(xí)吧
    2016-04-04
  • Android編程實現(xiàn)基于BitMap獲得圖片像素數(shù)據(jù)的方法

    Android編程實現(xiàn)基于BitMap獲得圖片像素數(shù)據(jù)的方法

    這篇文章主要介紹了Android編程實現(xiàn)基于BitMap獲得圖片像素數(shù)據(jù)的方法,對比分析了兩種獲取圖片像素的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • android設(shè)備間實現(xiàn)無線投屏的示例代碼

    android設(shè)備間實現(xiàn)無線投屏的示例代碼

    Android提供了MediaProjection來實現(xiàn)錄屏,通過MediaProjection可以獲取當前屏幕的視頻流,而視頻流需要通過編解碼來壓縮進行傳輸,通過MediaCodec可實現(xiàn)視頻的編碼和解碼,這篇文章主要介紹了android設(shè)備間實現(xiàn)無線投屏,需要的朋友可以參考下
    2022-06-06
  • Android點擊事件之多點觸摸與手勢識別的實現(xiàn)

    Android點擊事件之多點觸摸與手勢識別的實現(xiàn)

    這篇文章主要介紹了Android點擊事件之多點觸摸與手勢識別的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Android清空編輯框內(nèi)容功能的實現(xiàn)實例代碼

    Android清空編輯框內(nèi)容功能的實現(xiàn)實例代碼

    本篇文章主要介紹了Android清空編輯框數(shù)據(jù)功能的實現(xiàn)實例代碼,非常具有實用價值,需要的朋友可以參考下。
    2017-03-03
  • Json 生成與解析詳解及實例代碼

    Json 生成與解析詳解及實例代碼

    這篇文章主要介紹了Json 生成與解析詳解及實例代碼的相關(guān)資料,這里附簡單實例幫助大家學(xué)習(xí)理解,需要的朋友可以參考下
    2016-11-11
  • Android仿微信5實現(xiàn)滑動導(dǎo)航條

    Android仿微信5實現(xiàn)滑動導(dǎo)航條

    這篇文章主要為大家詳細介紹了Android仿微信5實現(xiàn)滑動導(dǎo)航條,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08

最新評論

海原县| 吉林省| 体育| 迭部县| 兰州市| 扎赉特旗| 修武县| 新晃| 江城| 韶关市| 随州市| 将乐县| 额尔古纳市| 凉城县| 康马县| 陇西县| 洪江市| 长岭县| 湟中县| 武宣县| 惠东县| 九龙城区| 紫云| 山西省| 静海县| 拜城县| 赣州市| 宜都市| 泰州市| 秦皇岛市| 宣恩县| 定结县| 始兴县| 博客| 宁远县| 和田县| 苏尼特右旗| 阿拉尔市| 雷波县| 瑞安市| 安仁县|