代码之家  ›  专栏  ›  技术社区  ›  Guido

如何在Android运行时更改当前主题[duplicate]

  •  131
  • Guido  · 技术社区  · 14 年前

    我创建了一个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 回复  |  直到 12 年前
        1
  •  94
  •   Mehdi Yari Pentium10    4 年前

    我也想看看这个方法,你为所有的活动设置一次。但据我所知,在显示任何视图之前,您必须在每个活动中进行设置。

    参考检查:

    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);
        }
    


    编辑
    如果你打电话 setTheme super.onCreate(savedInstanceState); 你的活动重新创建,但如果你打电话 设置主题 之前 不再重现

      protected void onCreate(Bundle savedInstanceState) {
         setTheme(android.R.style.Theme_Dark);
         super.onCreate(savedInstanceState);
    
    
        // ...
        setContentView(R.layout.main);
    }
    
        2
  •  66
  •   TPReal    7 年前

    如果要更改已存在活动的主题,请致电 recreate() 之后 setTheme() .

    注意:如果在中更改主题,请不要调用“重新创建” onCreate() ,以避免无限循环。

        3
  •  23
  •   Community c0D3l0g1c    7 年前

    recreate() TPReal )只会重新启动当前活动,但以前的活动仍将在后堆栈中,并且主题不会应用于它们。

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

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

    setTheme() 之前打过电话 onCreate() SharedPreferences ,读取它,然后使用 设置主题()

        4
  •  16
  •   Monty    12 年前

    我也遇到同样的问题,但我找到了解决办法。

    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);
        }
    }
    
        5
  •  11
  •   Francesco Ditrani    11 年前

    我有一个类似的问题,我就这样解决了。。

    @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();
    
        6
  •  10
  •   LarsH    9 年前

    打电话之前我们得先定好主题 '设置内容视图()' 方法。

    看看这个 link

        7
  •  5
  •   Vitaly Zinchenko    9 年前

    而不是

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

    使用

    setTheme(R.style.BlackTheme);
    

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

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

    YourActivity.this.recreate();
    

        8
  •  3
  •   Pratik Butani Umesh N    9 年前

    这是我为材料设计所做的。愿它对你有帮助。

    找一找 MultipleThemeMaterialDesign

        9
  •  2
  •   Artjom B.    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);
    }
    
        10
  •  2
  •   duongnx    8 年前

    这种方法对我有用:

      @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();
    
        11
  •  1
  •   Sumit Dhaniya    12 年前

    您可以完成活动,然后重新创建它,这样您的活动将再次创建,所有视图都将使用新主题创建。

        12
  •  0
  •   MohammadReza Moradi    8 年前

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

        13
  •  0
  •   arlomedia    8 年前

    这对我没有影响:

    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();
    }