Android實現app主題動態切換的兩種方式

TestTheme

這是一個實現app主題動態切換的例子程序,示例了兩種方式:
1、通過切換app的Theme屬性;
2、通過安裝主題apk包實現切換;

通過切換app的Theme屬性實現主題動態切換的核心邏輯:

在Style中創建兩套Theme(如appTheme和appThemeLight),在attr文件中創建需要的動態改變的屬性(如backgroundStyle),
然後在前面以創建的Theme(appTheme和appThemeLight)中使用自定義的屬性(backgroundStyle);
最後在代碼中通過context.setTheme(int resId)動態設置主題爲自己創建某個主題(appTheme或appThemeLight);
注意:context.setTheme(int resId)必須在Activity的setContentView()之前調用;

**XML佈局文件中的調用方法**:
style="?backgroundStyle"

**代碼中的調用方法**:
    某些情況下,有些組件的屬性需要在代碼中進行動態設置,這個時候只依靠上面的做法無法完成主題的切換;,
    此時需要在代碼中動態讀取當前的Theme對象,並通過該Theme對象與在attr中定義的屬性(如drawableStyle),
    獲取當前Theme下自定義屬性(drawableStyle)所鏈接的ResourceId,並將該ResourceId設置給對應的組件;
    TypedArray array = getActivity().getTheme()
                .obtainStyledAttributes(new int[] {R.attr.drawableStyle});
    int drawableResId = array.getResourceId(0, 0);
    ivImage.setImageResource(drawableResId);

通過安裝主題apk包實現切換核心代碼邏輯是:

1、查找所有與規定的主題apk包名相同的apk:
PackageManager pm = getActivity().getPackageManager();
            List<PackageInfo> listPackages = pm.getInstalledPackages(PackageManager.PERMISSION_GRANTED);
            List<PackageInfo> listSkins = new ArrayList<PackageInfo>();
            for (PackageInfo packageInfo : listPackages) {
                if(packageInfo.packageName.startsWith(SKIN_PACKAGE_PREFIX)){
                    listSkins.add(packageInfo);
                }
            }
2、根據包名,獲得包名所對應的apk的resource資源文件
public void onThemeChanged(String newThemePackageName){
        if(TextUtils.isEmpty(newThemePackageName)) return;
        try {
            Context con = this.getActivity().createPackageContext(newThemePackageName, CONTEXT_IGNORE_SECURITY);
            Resources res = con.getResources();
            changeStyle(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

public void changeStyle(Resources res){
    mListView.setBackgroundColor(res.getColor(R.color.bg_listview));
}

由於該程序只是主程序,(主程序本身的resource可以理解爲默認主題),並沒有提供主題apk程序,特在此說明一下:

主題apk不需要實現任何功能,只需要對照主程序的resource完成主題apk的resource;
已color文件爲例,在主程序的color文件中有bg_listview這個顏色(且主程序代碼中以該顏色爲listView的主題背景),
那麼在主題apk的color文件中同樣指定一個名爲bg_listview的顏色,那麼在主程序將主題切換爲該主題apk時,會自動
讀取該主題apk下的這個bg_listview作爲listView的主題背景;

源碼地址:github

程序截圖:

image1
image2
image3
image4
image5
image6

發佈了45 篇原創文章 · 獲贊 16 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章