C#winform换肤问题:自己写了一个换肤的基类(SkinForm)是从Form继承的,如何能把所有的Form换成新的皮肤
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#winform换肤问题:自己写了一个换肤的基类(SkinForm)是从Form继承的,如何能把所有的Form换成新的皮肤相关的知识,希望对你有一定的参考价值。
注:除了把一个个Form的基类换成SkinForm外,还有没有其它方法???
是不是有什么系统钩子能做到?
Android一键换肤原理简述
简介
Android对应用进行换肤操作,首先要生成一个对应的皮肤包,在要换肤的应用中收集需要换肤的控件,获取皮肤包里的资源,一键换肤时遍历View树,对要换肤的控件进行换肤。下面总结为4个步骤
步骤
1 通过Activity.onCreateView()或 实现LayoutInfaltor.Factory2接口 创建收集可换肤控件
这项工作应该在YourActivity.class
或者BaseActivity.class
或者LifecycleObserver.class
中实现。这个步骤的实现自行搜索。
2 启动或触发换肤的时候加载皮肤包APK的资源
SkinManager.class
public void loaderSkinResources(skinPath)
//反射创建AssestManager并通过路径加载Apk的资源
//通过这个AssestManager获取Resource并用Map缓存
//创建资源管理器(此处不能用:application.getAssets())
AssetManager assetManager = AssetManager.class.newInstance();
// 由于AssetManager中的addAssetPath和setApkAssets方法都被@hide,目前只能通过反射去执行方法
Method addAssetPath = assetManager.getClass().getDeclaredMethod(ADD_ASSET_PATH, String.class);
// 设置私有方法可访问
addAssetPath.setAccessible(true);
// 执行addAssetPath方法
addAssetPath.invoke(assetManager, skinPath);
//==============================================================================
// 如果还是担心@hide限制,可以反射addAssetPathInternal()方法,参考源码366行 + 387行
//==============================================================================
// 创建加载外部的皮肤包(123456.skin,实质是APK)文件Resources(注:依然是本应用加载)
skinResources = new Resources(assetManager, appResources.getDisplayMetrics(), appResources.getConfiguration());
// 根据apk文件路径(皮肤包也是apk文件),获取该应用的包名。兼容5.0 - 9.0(亲测)
skinPackageName = application.getPackageManager().getPackageArchiveInfo(skinPath, PackageManager.GET_ACTIVITIES).packageName;
3 通过当前资源包的resourceId获取皮肤包里的资源
SkinManager.class
private int getSkinResourceIds(int resourceId)
// 优化:如果没有皮肤包或者没做换肤动作,直接返回app内置资源!
if (isDefaultSkin) return resourceId;
// 使用app内置资源加载,是因为内置资源与皮肤包资源一一对应(“netease_bg”, “drawable”)
String resourceName = appResources.getResourceEntryName(resourceId);
String resourceType = appResources.getResourceTypeName(resourceId);
// 动态获取皮肤包内的指定资源ID
// getResources().getIdentifier(“netease_bg”, “drawable”, “com.netease.skin.packages”);
int skinResourceId = skinResources.getIdentifier(resourceName, resourceType, skinPackageName);
4 通过applyViews(getWindow().getDecorView())遍历
这个是换肤过程
...........
SkinManager.getInstance().loaderSkinResources(skinPath);
if (themeColorId != 0)
int themeColor = SkinManager.getInstance().getColor(themeColorId);
StatusBarUtils.forStatusBar(this, themeColor);
NavigationUtils.forNavigation(this, themeColor);
ActionBarUtils.forActionBar(this, themeColor);
applyViews(getWindow().getDecorView());
..........................
/**
* 控件回调监听,匹配上则给控件执行换肤方法
*/
protected void applyViews(View view)
if (view instanceof ViewsMatch)
ViewsMatch viewsMatch = (ViewsMatch) view;
viewsMatch.skinnableView();
if (view instanceof ViewGroup)
ViewGroup parent = (ViewGroup) view;
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
applyViews(parent.getChildAt(i));
总结
文中所提及的4个步骤是实现换肤的基本原理,当然还有需要很多的优化,也还有兼容性问题,干货已给出啦~~
以上是关于C#winform换肤问题:自己写了一个换肤的基类(SkinForm)是从Form继承的,如何能把所有的Form换成新的皮肤的主要内容,如果未能解决你的问题,请参考以下文章