39

ユーザーにいくつかの異なるテーマから選択できるようにしたいのですが、これが適切な方法であるかどうか疑問に思っていました。この方法で少しテストを行ったところうまくいきましたが、もっと良い方法があると思いますし、後で問題が発生する可能性があると思うので、質問したいと思いました.

テーマごとに異なるレイアウトを作成し、メソッドonCreateのスイッチだけを作成することを考えていました。setContentView()最初に保存されたSharedPreference値 (整数) を読み込み、その値に応じて対応するレイアウトを表示します。明らかに、ユーザーはSharedPreferenceボタンなどで値を変更できます。

TextViewsこれらのレイアウトは基本的に同じですが、色が異なるため、各レイアウト ファイルの自分のビューと他のビューに同じ ID を使用したいと考えています。私の主な質問は、これにより問題が発生するかどうかです。

コードのないテキストの壁で申し訳ありません。この状況での良い実践方法の一般的なアイデアを得たいと思います。前もって感謝します。

4

4 に答える 4

51

私は実際に私のアプリケーションにこの機能を持っており、さらに、ユーザーが実行時にテーマを変更できるようにしています。設定から値を読み取るには時間がかかるため、キャッシュされた値を保持するグローバルにアクセス可能な関数を介してテーマIDを取得しています。

すでに指摘したように、このガイドを使用して、いくつかのAndroidテーマを作成します。ファイルには少なくとも2つの<style>アイテムが含まれますstyles.xml。例えば:

<style name="Theme.App.Light" parent="@style/Theme.Light">...</style>
<style name="Theme.App.Dark" parent="@style/Theme">...</style>

ここで、これらのスタイルの1つをアクティビティに適用する必要があります。onCreate他の呼び出しの前に、私はactivitieのメソッドでこれを行っています:

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

リスナーオブジェクトへの参照を保持することを忘れないでください。そうしないと、ガベージコレットされます(そして機能しなくなります)。

于 2012-01-10T23:13:19.787 に答える
2

このようにすれば機能しますし、何の問題もないと思いますが、面倒なようです (すべてのレイアウトに追加したいすべてのテーマを掛ける必要があります。レイアウト内のリソースを変更したい場合は、すべてのテーマでそれを変更する必要があります.1 つを忘れることは間違いありません)

Androidのスタイルとテーマ機能を使用しないのはなぜですか?

それらはアクティビティ全体に簡単に適用できます。

<activity android:theme="@style/my_theme">

SharedPreferencesそのため、使用する値 (設定アクティビティのボタンなど)の変更を検出すると、スタイルを切り替えることができます。または、実行時 (アクティビティの作成時) に設定値を読み取るようにスタイルを設定し、それに応じて正しいスタイル/テーマを適用することもできます。

于 2012-01-10T22:45:05.490 に答える