setTheme无法更改主题颜色

17

我知道这个问题已经被问了几次,但是在我的情况下我找不到问题所在。 我想要改变应用程序的主题,但是我的colorPrimary、colorAccent等等都没有改变。

我的MainActivity扩展自BasicActivity,看起来像这样:

public class MainActivity extends BasicActivity {
    public static String MY_PREFS = "MY_PREFS";
    private SharedPreferences mySharedPreferences;
    int prefMode = Activity.MODE_PRIVATE;

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private ViewPagerAdapter adapter;
    private TextView tabOne, tabTwo, tabThree;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

}
}

这是我的BasicActivity(在这种情况下,我使它更简单以展示主题是从R.style中获取的):

public class BasicActivity extends AppCompatActivity {

    public static String MY_PREFS = "MY_PREFS";
    int prefMode = Activity.MODE_PRIVATE;



    protected void onCreate(Bundle savedInstanceState) {


        JsonParser parser = new JsonParser(getApplicationContext());

        int resourceId = this.getResources().getIdentifier(parser.getThemeID(), "style", this.getPackageName());
        setTheme(R.style.c_2ecc71_BC6C2B);


        if (android.os.Build.VERSION.SDK_INT >= 19) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        }

        super.onCreate(savedInstanceState);

    }

}

和我的 XML:

<style name="c_2ecc71_BC6C2B" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">#2ecc71</item>
    <item name="colorPrimaryDark">#1ebc61</item>
    <item name="colorAccent">#BC6C2B</item>
</style>
根据先前的问题,这段代码应该可以工作,但在我的情况下,在其XML中具有colorPrimary属性的视图仍然加载旧主题的颜色,尽管我在调用setContentView(R.layout.activity_main);之前设置了新主题。
谢谢!

1
你在 BaseActivity 中硬编码了主题,而不是获取引用资源 ID。你需要使用 setTheme(value_from_resourceId)。BaseActivity 总是调用 setTheme(R.style.c_2ecc71_BC6C2B); 然后运行时的值。 - Sreehari
7个回答

14
如果您使用片段,它们将忽略您在onCreate()中设置的值。如果您覆盖getTheme()方法,则该值也将在片段中使用:
在不同的问题上回答:以编程方式更改Activity的主题
@Override
public Resources.Theme getTheme() {
    Resources.Theme theme = super.getTheme();
    theme.applyStyle(R.style.c_2ecc71_BC6C2B, true);
    return theme;
}

将其用于您的MainActivity或BasicActivity中,具体取决于您希望将其应用于何处。您将不再需要在onCreate中更改它。


1
这正是我所需要的。 - Maor Veitsman

7

2
为了在运行时设置主题,您可以使用以下代码行:
setTheme(android.R.style.Theme_Name);
并将其写在 onCreate() 方法中的 setContentView() 和 super.onCreate() 方法之前。

2

不确定您是否真的想以编程方式设置它,但您可以尝试这样做:如何在运行时将主题设置为活动?在onCreate和setContentView之前调用setTheme不起作用

如果您想为整个应用程序设置它,那么在AndroidManifest.xml文件中设置可能更容易/更清洁。

<application android:theme="@style/CustomTheme">

另外,我强烈建议避免使用带有值的样式名称。使用样式的目的是避免硬编码值,并允许它们可配置和可重用。如果你想改变colorPrimary,那么你也要改变你的样式名称吗?


我希望能够在运行时动态地更改它。 - Max
是的,这就是答案中第一个链接所解释的内容。你应该能够像这样编写代码:public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(android.R.style.Theme_Translucent_NoTitleBar); // 在这里设置 setContentView(...) } - Scott Merritt

2

如果您想在运行时更改这种类型的内容,必须将所有这些“setTheme(android.R.style.Theme_Name);”方法插入到runOnUiThread中,如下所示:

public class BasicActivity extends AppCompatActivity {

public static String MY_PREFS = "MY_PREFS";
int prefMode = Activity.MODE_PRIVATE;



protected void onCreate(Bundle savedInstanceState) {


    JsonParser parser = new JsonParser(getApplicationContext());

    int resourceId = this.getResources().getIdentifier(parser.getThemeID(), "style", this.getPackageName());

    runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                     setTheme(R.style.c_2ecc71_BC6C2B);
                    }
                });

    recreate();
    if (android.os.Build.VERSION.SDK_INT >= 19) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    }

    super.onCreate(savedInstanceState);

}

}

并在此之后调用recreate()函数!

根据Android -

void recreate () 使该Activity被重新创建为一个新实例。这将导致与由于配置更改而创建Activity时基本相同的流程 - 当前实例将经过其生命周期直到onDestroy(),然后在其之后创建一个新实例。


2

请将您的BasicActivity和MainActivity按照下面所示进行修改,并创建适当的主题。您可以使用共享首选项来检查应用程序启动期间的主题状态。

BasicActivity .java

public abstract class BasicActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    try {
        if (getLayoutID() != 0) {
            setContentView(getLayoutID());
        }
    } catch (Exception ex) { /* ... */ }

    final boolean THEME_DARK = true;// read appropriate value from SP or any other storage

    Toolbar toolbar;
    if ((toolbar = getToolbar()) != null) {
        if (THEME_DARK/*  check theme type here*/) {
            toolbar.setPopupTheme(R.style.c_2ecc71_BC6C2B);
        }
        try {
            setSupportActionBar(toolbar);
        } catch (NoClassDefFoundError e) {
            // Toast
            finish();
        }
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.setStatusBarColor(getResources().getColor(R.color.colorPrimary));
    }
}

public abstract Toolbar getToolbar();

public abstract int getLayoutID();

}     

MainActivity.java

    public class MainActivity extends BasicActivity {

    private Toolbar toolbar;

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

    @Override
    public Toolbar getToolbar() {
        return toolbar == null ? toolbar = (Toolbar) findViewById(R.id.toolbar) : toolbar;
    }

    @Override
    public int getLayoutID() {
        return R.layout.activity_main;
    }
   }

2

您在BaseActivity中硬编码了主题,而不是获取目标资源ID。

您需要放置setTheme(value_from_resourceId);

目前,无论您解析的值如何,BaseActivity总是会调用它。

setTheme(R.style.c_2ecc71_BC6C2B);

与引用运行时的值相比


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接