ユーザーにいくつかの異なるテーマから選択してもらいたいのですが、これが問題のない方法であるかどうか疑問に思いました。私はこの方法で少しテストをして、それはうまくいきましたが、もっと良い方法があるかもしれないし、後でいくつかの問題を引き起こすかもしれないと思うので、尋ねたいと思いました。
テーマごとに異なるレイアウトを作成することを考えていました。onCreate
では、setContentView()
メソッドのスイッチを用意するだけでした。保存したSharedPreference
値(整数)を最初にロードし、その値に応じて、対応するレイアウトを表示します。明らかに、ユーザーはボタンなどでSharedPreference
値を変更できます。
これらのレイアウトは基本的に同じですが色が異なるため、各レイアウトファイルのTextViews
と他のビューに同じIDを使用したいと思います。私の主な質問は、これが問題を引き起こすでしょうか?
コードのないテキストの壁でごめんなさい。この状況でのグッドプラクティスの概要を知りたいと思います。前もって感謝します。
私は実際にアプリケーションにこの機能を持っており、さらに、ユーザーが実行時にテーマを変更できるようにしています。設定から値を読み取るには時間がかかるため、キャッシュされた値を保持するグローバルにアクセス可能な関数を介してテーマIDを取得しています。
すでに指摘したように、 このガイド を使用していくつかのAndroidテーマを作成します。<style>
ファイルには少なくとも2つのstyles.xml
アイテムがあります。 例えば:
<style name="Theme.App.Light" parent="@style/Theme.Light">...</style>
<style name="Theme.App.Dark" parent="@style/Theme">...</style>
ここで、これらのスタイルの1つをアクティビティに適用する必要があります。これは、他の呼び出しの前に、activitieのonCreate
メソッドで実行しています。
setTheme(MyApplication.getThemeId());
getThemeId
は、キャッシュされたテーマIDを返すメソッドです。
public static int getThemeId()
{
return themeId;
}
このフィールドは別の方法で更新されています:
public static void reloadTheme()
{
themeSetting = PreferenceManager.getDefaultSharedPreferences(context).getString("defaultTheme", "0");
if(themeSetting.equals("0"))
themeId = R.style.Theme_Light;
else
themeId = R.style.Theme_Dark;
}
これは、設定が変更されるたびに(そしてもちろん起動時に)呼び出されます。これらの2つのメソッドは、MyApplication
を拡張するApplication
クラスにあります。プリファレンス変更リスナーは、この投稿の最後に説明されており、メインアクティビティクラスにあります。
最後の非常に重要なこと-アクティビティが開始されるときにテーマが適用されます。テーマは設定画面でのみ変更でき、そこに到達する方法は1つしかないと仮定します。つまり、1つの(メイン)アクティビティからのみ、設定画面を終了してもこのアクティビティは再開されません。古いテーマは引き続き表示されます。中古。これを修正します(メインアクティビティを再開します)。
@Override
protected void onResume() {
super.onResume();
if(schduledRestart)
{
schduledRestart = false;
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
scheduledRestart
はブール変数で、最初はfalseに設定されています。このリスナーによってテーマが変更されると、trueに設定されます。これにより、前述のキャッシュされたテーマIDも更新されます。
private class themeListener implements OnSharedPreferenceChangeListener{
@Override
public void onSharedPreferenceChanged(SharedPreferences spref, String key) {
if(key.equals("defaultTheme") && !spref.getString(key, "0").equals(MyApplication.getThemeSetting()))
{
MyApplication.reloadTheme();
schduledRestart = true;
}
}
sp = PreferenceManager.getDefaultSharedPreferences(this);
listener = new themeListener();
sp.registerOnSharedPreferenceChangeListener(listener);
リスナーオブジェクトへの参照を保持することを忘れないでください。そうしないと、ガベージコレットされます(そして機能しなくなります)。
以下を使用して、テーマを動的に変更することもできます。
ContextThemeWrapper w = new ContextThemeWrapper(this, <newTHEMEId>);
getTheme().setTo(w.getTheme());
各アクティビティのonCreateの前。
このようにすれば機能し、問題はないと思いますが、面倒なようです(すべてのレイアウトに追加したいすべてのテーマを掛ける必要があります。後でレイアウト内のリソースを変更したい場合は、すべてのテーマでリソースを変更する必要があります。間違いなく1つを忘れる必要があります)
Androidの スタイルとテーマ 機能を使用しないのはなぜですか?
それらはアクティビティ全体に簡単に適用できます。
<activity Android:theme="@style/my_theme">
そのため、使用するSharedPreferences
値(設定アクティビティのボタンなど)の変更を検出すると、スタイルを切り替えることができます。または、実行時に(アクティビティの作成時に)プリファレンス値を読み取るようにスタイルを設定し、それに応じて正しいスタイル/テーマを適用することもできます。