首页 文章

如何在Android中运行时更改当前主题[重复]

提问于
浏览
126

这个问题在这里已有答案:

我创建了一个PreferenceActivity,允许用户选择他想要应用于整个应用程序的主题 .

当用户选择主题时,执行以下代码:

if (...) {
    getApplication().setTheme(R.style.BlackTheme);
} else {
    getApplication().setTheme(R.style.LightTheme);
}

但是,即使我已经使用调试器检查了代码是否正在执行,我也看不到用户界面的任何变化 .

主题在 res/values/styles.xml 中定义,Eclipse不显示任何错误 .

<resources>
    <style name="LightTheme" parent="@android:style/Theme.Light">
    </style>

    <style name="BlackTheme" parent="@android:style/Theme.Black">
    </style>    
</resources>

关于可能发生的事情以及如何解决问题的任何想法?我应该在代码中的任何特殊位置调用 setTheme 吗?如果有帮助,我的应用程序包含几个活动 .

13 回答

  • 18

    我也希望看到这个方法,你可以为你的所有活动设置一次 . 但据我所知,你必须在显示任何观点之前设置每个活动 .

    供参考检查:

    http://www.anddev.org/applying_a_theme_to_your_application-t817.html

    编辑(从该论坛复制):

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Call setTheme before creation of any(!) View.
         setTheme(android.R.style.Theme_Dark);
    
        // ...
        setContentView(R.layout.main);
    }
    
  • 2

    如果要更改现有活动的主题,请在setTheme()之后调用recreate() .

    注意:如果在 onCreate() 中更改主题,请不要调用recreate,以避免无限循环 .

  • 1

    recreate() (如TPReal所述)将仅重新启动当前活动,但之前的活动仍将在后台堆栈中,并且主题将不会应用于它们 .

    因此,此问题的另一个解决方案是完全重新创建任务堆栈,如下所示:

    TaskStackBuilder.create(getActivity())
                .addNextIntent(new Intent(getActivity(), MainActivity.class))
                .addNextIntent(getActivity().getIntent())
                .startActivities();
    

    编辑:

    在UI或其他地方执行主题更改后,只需输入上面的代码即可 . 您的所有活动都应该在 onCreate() 之前调用方法 setTheme() ,可能在某些父活动中 . 这也是存储在 SharedPreferences 中选择的主题,读取它然后使用 setTheme() 方法设置的常规方法 .

  • 2

    我遇到了同样的问题,但我找到了解决方案 .

    public class EditTextSmartPhoneActivity extends Activity implements DialogInterface.OnClickListener
    {
        public final static int CREATE_DIALOG  = -1;
        public final static int THEME_HOLO_LIGHT  = 0;
        public final static int THEME_BLACK  = 1;
    
        int position;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            position = getIntent().getIntExtra("position", -1);
    
            switch(position)
            {
            case CREATE_DIALOG:
                createDialog();
                break;
            case THEME_HOLO_LIGHT:
                setTheme(android.R.style.Theme_Holo_Light);
                break;
            case THEME_BLACK:
                setTheme(android.R.style.Theme_Black);
                break;
            default:
            }
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
        }
    
        private void createDialog()
        {
            /** Options for user to select*/
            String choose[] = {"Theme_Holo_Light","Theme_Black"};
    
            AlertDialog.Builder b = new AlertDialog.Builder(this);
    
            /** Setting a title for the window */
            b.setTitle("Choose your Application Theme");
    
            /** Setting items to the alert dialog */
            b.setSingleChoiceItems(choose, 0, null);
    
            /** Setting a positive button and its listener */
            b.setPositiveButton("OK",this);
    
            /** Setting a positive button and its listener */
            b.setNegativeButton("Cancel", null);
    
            /** Creating the alert dialog window using the builder class */
            AlertDialog d = b.create();
    
            /** show dialog*/
            d.show();
        }
    
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub
            AlertDialog alert = (AlertDialog)dialog;
            int position = alert.getListView().getCheckedItemPosition();
    
            finish();
            Intent intent = new Intent(this, EditTextSmartPhoneActivity.class);
            intent.putExtra("position", position);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }
    
  • 52

    我有类似的问题,我这样解决了..

    @Override
    public void onCreate(Bundle savedInstanceState) {
    
        if (getIntent().hasExtra("bundle") && savedInstanceState==null){
            savedInstanceState = getIntent().getExtras().getBundle("bundle");
        }
    
        //add code for theme
    
        switch(theme)
        {
        case LIGHT:
            setTheme(R.style.LightTheme);
            break;
        case BLACK:
            setTheme(R.style.BlackTheme);
            break;
    
        default:
        }
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //code
    
    }
    

    此代码用于重新创建活动保存包并更改主题 . 你必须编写自己的onSaveInstanceState(Bundle outState);从API-11开始,您可以使用recreate()方法

    Bundle temp_bundle = new Bundle();
    onSaveInstanceState(temp_bundle);
    Intent intent = new Intent(this, MainActivity.class);
    intent.putExtra("bundle", temp_bundle);
    startActivity(intent);
    finish();
    
  • 15

    我们必须在调用 'super.onCreate()''setContentView()' 方法之前设置主题 .

    查看此link,以便在运行时将新主题应用于整个应用程序 .

  • 9

    代替

    getApplication().setTheme(R.style.BlackTheme);
    

    使用

    setTheme(R.style.BlackTheme);
    

    我的代码:在onCreate()方法中:

    super.onCreate(savedInstanceState);
    
    if(someExpression) {
        setTheme(R.style.OneTheme);
    } else {
        setTheme(R.style.AnotherTheme);
    }
    
    setContentView(R.layout.activity_some_layout);
    

    某处(例如,点击按钮):

    YourActivity.this.recreate();
    

    你必须重新创建活动,否则 - 不会发生变化

  • 74

    这就是我为Material Design创建的 . 愿它对你有所帮助 .

    看看MultipleThemeMaterialDesign

  • 9

    我知道我迟到但我想在这里发布一个解决方案:检查完整的源代码here . 这是我在使用首选项更改主题时使用的代码 .

    SharedPreferences pref = PreferenceManager
            .getDefaultSharedPreferences(this);
    String themeName = pref.getString("prefSyncFrequency3", "Theme1");
    if (themeName.equals("Africa")) {
        setTheme(R.style.AppTheme);
    } else if (themeName.equals("Colorful Beach")) {
        //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
        setTheme(R.style.beach);
    } else if (themeName.equals("Abstract")) {
        //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
        setTheme(R.style.abstract2);
    } else if (themeName.equals("Default")) {
        setTheme(R.style.defaulttheme);
    }
    
  • 0

    这种方式对我有用:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(GApplication.getInstance().getTheme());
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.activity_main);
    }
    

    然后你想要改变一个新主题:

    GApplication.getInstance().setTheme(R.style.LightTheme);
    recreate();
    
  • 3

    您可以完成Acivity并在之后重新创建它,这样您的活动将再次创建,所有视图将使用新主题创建 .

  • 0

    在setTheme()之后调用SetContentView(Resource.Layout.Main) .

  • 2

    这对我没有影响:

    public void changeTheme(int newTheme) {
        setTheme(newTheme);
        recreate();
    }
    

    但这有效:

    int theme = R.style.default;
    
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(this.theme);
        super.onCreate(savedInstanceState);
    }
    
    public void changeTheme(int newTheme) {
        this.theme = newTheme;
        recreate();
    }
    

相关问题