C#winform换肤问题:自己写了一个换肤的基类(SkinForm)是从Form继承的,如何能把所有的Form换成新的皮肤

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#winform换肤问题:自己写了一个换肤的基类(SkinForm)是从Form继承的,如何能把所有的Form换成新的皮肤相关的知识,希望对你有一定的参考价值。

注:除了把一个个Form的基类换成SkinForm外,还有没有其它方法???
是不是有什么系统钩子能做到?

参考技术A 把你实现换肤功能的所有实现,封装为一个组件,到时候在需要换肤的窗体上放入一个该组件不就行了? 参考技术B 还现有一些现成的皮肤控件,用起来很简单,大部分要收费,也有破解版的本回答被提问者和网友采纳

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换成新的皮肤的主要内容,如果未能解决你的问题,请参考以下文章

插件式换肤框架搭建 - 资源加载源码分析

winform 自已做皮肤

在HTML中。怎么样才能实现换肤的功能?

插件化换肤方案

Android一键换肤原理简述

Android一键换肤原理简述