【问题标题】:How to apply a theme / style in android without restarting the activity?如何在不重新启动活动的情况下在 android 中应用主题/样式?
【发布时间】:2016-06-14 22:34:57
【问题描述】:

我有一个应用程序,用户可以在其中从PreferenceActivity 中选择几个不同颜色的主题,从而更改整个应用程序的主题/颜色。但是PreferenceActivity 中选择的更改不会立即应用。仅当用户重新进入PreferenceActivity 时,才会应用更改。

我知道每次选择主题时我都可以致电recreate(),但我想知道是否存在更好的解决方案而无需重新创建整个活动。

这是一个关于它当前工作原理的视频: https://www.youtube.com/watch?v=oU8xIUi_48A

这是我从 PreferenceActivity 中的preferenceList 中设置所选值的地方:

@Override
public void onCreate(Bundle savedInstanceState) {
    setTheme();
    themecolorList.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            switch (themecolorList.getValue()) {

                case "grey":
                    themecolorList.getEditor().putString("grey", "green").apply();
                    break;
                case "green":
                    themecolorList.getEditor().putString("green", "green").apply();
                    setTheme(R.style.AppTheme_default);
                    break;
                case "blue":
                    themecolorList.getEditor().putString("blue", "green").apply();
                    break;
                case "yellow":
                    themecolorList.getEditor().putString("yellow", "green").apply();
                    break;
                case "red":
                    themecolorList.getEditor().putString("red", "green").apply();
                    break;
                case "pink":
                    themecolorList.getEditor().putString("pink", "green").apply();
                    break;

                default:
                    themecolorList.getEditor().putString("green", "green").apply();
                    break;
            }

            recreate();
            return true;


        }
    });
  }

方法setTheme();在我的PreferenceActivitysonCreate();方法中被调用

private void setTheme() {

   SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    switch (sharedPreferences.getString("THEME_KEY", "green")) {

        case "grey":
            setTheme(R.style.AppTheme_Grey);
            break;

        case "green":
            setTheme(R.style.AppTheme_default);
            break;

        case "blue":
            setTheme(R.style.AppTheme_Blue);
            break;

        case "yellow":
            setTheme(R.style.AppTheme_Yellow);
            break;

        case "red":
            setTheme(R.style.AppTheme_Red);
            break;

        case "pink":
            setTheme(R.style.AppTheme_Pink);
            break;

        default:
            getApplication().setTheme(R.style.AppTheme_default);
            setTheme(R.style.AppTheme_default);
            break;
    }
}

【问题讨论】:

    标签: android


    【解决方案1】:

    似乎最好的解决方案是使用recreate();因为没有其他方法可以刷新活动的整个布局:

    每次用户按下主题列表中的选项时 按下的键/值通过OnPreferenceChangeListener 保存在SharedPreference 中,然后调用recreate();

    themecolorList.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                recreate();
                return true;
            }
        });
    

    在我的PreferenceActivitys onCreate(); 中,我调用了一个自定义方法setTheme();,它在调用recreate(); 之后调用。 setTheme(); 只是从OnPreferenceChangeListener 中查找SharedPreference 中保存的内容并将主题设置为相应的值

     @Override
     public void onCreate(Bundle savedInstanceState) {
        setTheme();
        super.onCreate(savedInstanceState);
    }
    

    【讨论】:

    • recreate() 重新创建所有活动
    【解决方案2】:

    你不能。 您可以开始一个新的活动来选择主题,并在用户选择时完成该活动。

    【讨论】:

    • 使用recreate(); 将是一个更好的选择,而不是每次用户按下偏好列表中的选项时开始一个新的意图
    【解决方案3】:

    触发布局更新(通过旋转设备,或让应用认为它已旋转)通常会导致它重新加载其资源。

    目前我不记得具体该怎么做,但这是我上次研究如何做类似事情时的常见做法。 只需记住指定(在清单中?)您的活动将处理布局更改/屏幕旋转以避免完全重启(以及任何未保存的数据丢失)。

    【讨论】:

    • 听起来很酷的解决方案。唯一的问题是我让我的应用程序只能在肖像模式下工作,因为在横向模式下使用它是不切实际的。
    • 哈哈,我和你的问题一模一样! :p (stackoverflow.com/questions/11705963/…)。但是我认为你坚持重新创建活动,或者你可以进行预览(图像弹出,或将样式颜色应用于列表项,如果可能的话?)然后重新创建活动(使用 Bundle 提供当前如果需要,状态到新实例)当用户进行选择时。
    【解决方案4】:

    看起来有一个名为 invalidate() 的方法可以在需要重绘的视图上调用。

    Link

    这应该允许您调用只需要重绘的单个视图。不是整个活动。

    【讨论】:

    • PreferenceActivityAppCompatPreferenceActivity 中只有这些:invalidateOptionsMenu(); invalidateHeaders();这些都不起作用
    • 哦,我明白对不起。
    猜你喜欢
    • 2015-07-22
    • 2014-10-18
    • 1970-01-01
    • 2020-12-23
    • 2011-11-11
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多