hongyangAndroid / ChangeSkin

基于插件式的Android换肤框架,支持app内和或者外部插件式提供资源的换肤方案,无需重启Activity。[仅供参考原理,暂不维护]
Apache License 2.0
1.15k stars 289 forks source link

某些场景下换皮肤不生效 #3

Open envyfan opened 9 years ago

envyfan commented 9 years ago

比如在作者提供DEMO MainActivity的DrawerLayout下,把background中的图片背景换成skin_开头的颜色资源(3个(skin_test,skin_test_red,skin_test_green)) 切换时 背景不变主题,listview背景也是有同样的问题。 另外Jcenter是否没有审核过呢?直接引入貌似不行

yilylong commented 9 years ago

发现几个小问题并修改了下

1、控件background 或者color 设置成@null 的形式的时候 加载布局的时候会报错

修改了下SkinAttrSupport下的getSkinAttrs(AttributeSet attrs, Context context)方法

public static List<SkinAttr> getSkinAttrs(AttributeSet attrs, Context context)
{
    List<SkinAttr> skinAttrs = new ArrayList<SkinAttr>();
    SkinAttr skinAttr = null;
    for (int i = 0; i < attrs.getAttributeCount(); i++)
    {
        String attrName = attrs.getAttributeName(i);
        String attrValue = attrs.getAttributeValue(i);

        SkinAttrType attrType = getSupprotAttrType(attrName);
        if (attrType == null) continue;

        if (attrValue.startsWith("@"))
        {
            int id = Integer.parseInt(attrValue.substring(1));
            if(id==0){// 资源设置成@null的形式的情况
                continue;
            }
            String entryName = context.getResources().getResourceEntryName(id);

            if (entryName.startsWith(SkinConfig.ATTR_PREFIX))
            {
                skinAttr = new SkinAttr(attrType, entryName);
                skinAttrs.add(skinAttr);
            }
        }
    }
    return skinAttrs;

}

2、background 只持者图片资源不支持color资源

修改了下SkinAttrType 下的BACKGROUD

BACKGROUD("background") {
    @Override
    public void apply(View view, String resName) {
        Drawable drawable = getResourceManager().getDrawableByName(resName);
        // TODO ZHL 添加一种background 设置成color的情况
        if (null!=drawable){
            view.setBackgroundDrawable(drawable);
        }else{
            int color = getResourceManager().getColor(resName);
            if(color==-1)
                return ;
            view.setBackgroundColor(color);
        }
    }
},

3、在使用最新的v7 包 23.0.1后无法换肤

这个问题没有去研究过 或许是23.0.1修改了一些方法

以上修改都只是暂时解决了问题。相信原作者会有更好解决方案

hongyangAndroid commented 9 years ago

非常感谢~~

envyfan commented 9 years ago

感谢

envyfan commented 9 years ago

刚刚发现了一个新问题@yilylong 恢复的时候 设置Background 设置成Color资源 的地方不会还原。!

WonShaw commented 9 years ago

@envyfan 对....是有这个问题....因为getDrawableByName是默认搜索drawable的...原生其实是可以用R.color这种形式, 也就是说getDrawable在drawable找不到时应该到color下去找

WonShaw commented 9 years ago

@envyfan 我fork的修了getDrawableByName获取不了颜色的问题. @hongyangAndroid 发PR了

yilylong commented 9 years ago

@envyfan 试了下 background设置成Color 调用removeAnySkin() 是可以恢复的哦,不知道你那边的具体情况。恢复时候传入的资源名就是布局文件中写的资源名。

envyfan commented 9 years ago

@yilylong 我后来用作者的Demo试的,我把ListView的background 我定义的颜色资源,恢复的时候确实不行。。我是的颜色资源定义如下: "skin_test" "skin_test_green" "skin_test_red" 然后刚刚用了@WonShaw PR的改正后确实可以了。! 谢谢@WonShaw

envyfan commented 9 years ago

listview 和pulltoRefreshListview 中的divider TextView中的drawableXXX设置了不会换皮肤。。估计在SkinAttrType 中加一个“divider“就好了。! 有空试试!

envyfan commented 9 years ago

imgeview android:src="@mipmap/xxx"如果用@mipmap 代替@drawable 换皮肤功能会失效

hongyangAndroid commented 9 years ago

首先感谢各位,目前对23.0.1进行了支持,代码、demo都已经更新为最新的依赖,欢迎查看~~ ps:顺便贴出原因,主要原因是23.0.1的v7在AppCompatDelegateImplV11该类中,将callActivityOnCreateView作为空实现了。

yilylong commented 9 years ago

发现在listview 的item 里面使用 严重影响性能啊,鸿洋大神能找找原因吗

hongyangAndroid commented 9 years ago

demo里面就是listview呀,没发现特别影响性能的~

yilylong commented 9 years ago

@hongyangAndroid 哦对的 那可能是我这边使用的不是原生listview 使用了一些下拉刷新的listview的原因吧 测试发现还是很大影响,尤其数据很多的情况。

yilylong commented 9 years ago

遇到一个新的需求 比如换肤的同时有夜间模式的情况。比如同一页面,控件A 需要换肤 控件B在夜间模式需要改变颜色但是A在夜间模式不需要。 也就是 两个控件的资源 不统一 A采用 skin_a_red 、skin_a_green 这样的 B采用 skin_b_day \ skin_b_night 换肤或者夜间模式切换后都没问题 但是重新启动应用 发现停留在最后一次操作(换肤或者夜间模式) 因为资源不统一 不同操作下只有 具有该资源的控件生效,没有该资源的控件在找不到资源的情况就使用的默认资源。所以不能同时满足两个控件不同资源的改变。

hongyangAndroid commented 9 years ago

恩,目前的代码默认是只有一套皮肤~~后续再考虑加入。大家如果有兴趣可以看看这个 https://github.com/hongyangAndroid/AndroidChangeSkin , 最近重新换了个思路。

KennethYo commented 8 years ago
<?xml version="1.0" encoding="utf-8"?>
<View
    android:id="@+id/line"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="1px"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:background="@color/skin_line_background"/>

如上,如果这样设置一条线,也不会更换这条线的颜色

KennethYo commented 8 years ago

# 在家里用基友的手机debug 了一下,在com.zhy.changeskin.base.BaseSkinActivity#createViewFromTag中判断 View 的方式,还是有点问题,View和其他控件不在一个包下,所以改成这样了。

 private View createViewFromTag(Context context, String name, AttributeSet attrs) {
        try {
            mConstructorArgs[0] = context;
            mConstructorArgs[1] = attrs;

            if (-1 == name.indexOf('.')) {
                // try the android.widget prefix first...
                String prefix = "android.widget.";
                if (TextUtils.equals(name, "View")) {
                    prefix = "android.view.";
                }
                return createView(context, name, prefix);
            } else {
                return createView(context, name, null);
            }
        } catch (Exception e) {
            // We do not want to catch these, lets return null and let the actual LayoutInflater
            // try
            return null;
        } finally {
            // Don't retain references on context.
            mConstructorArgs[0] = null;
            mConstructorArgs[1] = null;
        }
    }
yangyu5646 commented 8 years ago

不知道在实际项目中 是否有使用 , 洪洋大神是否会写一篇关于换肤原理的博客. 期待中