実行時に選択できる 2 つのテーマ (ダークとライト) を持つアプリがあります。これは機能します。また、3 つの異なるレイアウトのいずれかを持つことができる行を持つ ListView もあり、それぞれにスタイル (たとえば、異なる色) があります。これも機能します。しかし、これら 2 つの機能を連携させることはできません。1 つのテーマ (暗い) に 3 つ、もう 1 つのテーマ (明るい) に 3 つの 6 つの異なるスタイルが本当に必要ですが、現在のテーマに基づいてリスト項目のスタイルを選択する方法がわかりません。 XML ファイルを使用する別の方法。私の 3 つのレイアウトはそれぞれ、色を設定するカスタム テーマを指していますが、それは私が設定したテーマをオーバーライドします。テーマには「スタイルを設定できる」アイテムのみを含めることができるため、独自のカスタム アイテムをそこに配置することはできません。プログラムでこれを行う方法があるかもしれませんが、しかし、私はそれを宣言的に行うことを望んでいました。何か案は?
2 に答える
ヒントをくれたwingmanに感謝します。私の状況はもう少し複雑な色に関係していたので、ここで解決策を書きます。
ユーザーが設定画面で選択できる2つのテーマ(明るい色と暗い色)があります。私はListView
2種類の行(プレーンとノート)を持つことができ、それぞれが独自のスタイルを持っています。まず、各レイアウトはスタイルを指す必要があります。
<TextView style="@style/PlainItemText" ... />
(またはNoteItemText
)そしてスタイルを定義する必要があります:
<style name="PlainItemText">
<item name="android:textSize">@dimen/list_item_font_size</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?plainTextColor</item>
</style>
選択したテーマによって異なるため、テキストの色を修正することはできません。上記のように、カスタム属性を作成し、疑問符で参照する必要があります。属性を次のように定義しますres/values/attrs.xml
:
<!-- Attributes we use to set the text color of the various list items. -->
<attr name="plainTextColor" format="reference|color"/>
<attr name="noteTextColor" format="reference|color"/>
次に、さまざまな色を定義できます。ここでは、2つのスタイルと2つのテーマがあるため、それぞれがの下の独自のファイルにある4つのカラー状態リストが必要ですres/color
。たとえば、ここにありますres/color/plain_text_color_dark.xml
:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:color="@android:color/white"/>
<item android:state_selected="true" android:color="@android:color/black"/>
<item android:state_focused="true" android:color="@android:color/black"/>
<item android:state_pressed="true" android:color="@android:color/black"/>
<item android:color="@android:color/white"/>
</selector>
選択/フォーカス/押された色は、ハイライト色の上にあるため、これらすべてのファイルで同じです。state_window_focused
バージョンに注意してください。宣伝どおりに動作しなかったため、すべての場合でデフォルトの色(上の最後の行)に設定する必要がありました。次に、テーマを作成し、属性をいずれかの色にバインドする必要があります。これらの行は次のようになりres/values/themes.xml
ます。
<style name="Theme.Dark" parent="android:Theme">
<item name="plainTextColor">@color/plain_text_color_dark</item>
<item name="noteTextColor">@color/note_text_color_dark</item>
</style>
<style name="Theme.Light" parent="android:Theme.Light">
<item name="plainTextColor">@color/plain_text_color_light</item>
<item name="noteTextColor">@color/note_text_color_light</item>
</style>
最後に、実行時に、ActivityのonCreate()
メソッドで、次を呼び出す前にsuper.onCreate()
テーマを選択します。
if (isDarkTheme) {
activity.setTheme(R.style.Theme_Dark);
} else {
activity.setTheme(R.style.Theme_Light);
}
Holoのような新しいテーマは考慮していないので、私のアプリはHoneycomb以降では古く見えます。いつか修正しますが、ここではリグレッションではありませんでした。
私の場合のひねりは、いくつかのボタンに合うようにいくつかのアクティビティがより大きなタイトルバーを持っているということです。原則として、狭いタイトルの場合は明暗、太いタイトルの場合は明暗の4つのテーマを作成する必要がありました。しかし、代わりに私はミックスインスタイルを作成しました:
<!-- Mix-in style for activities. -->
<style name="ButtonTitleBar">
<item name="android:windowTitleSize">44dp</item>
</style>
使用しているテーマに手続き的に追加します。setTheme()
このコードは、上記の呼び出しの直後に実行されます。
if (buttonTitleBar) {
// Mix in this other style.
Resources.Theme theme = activity.getTheme();
theme.applyStyle(R.style.ButtonTitleBar, true);
}
私はこれがどこにも文書化されているのを見ませんでした、そしてそれが合法であるかどうかはわかりませんが、のコードはActivity.getTheme()
それがうまくいくはずであることを意味し、それは私のすべてのテストで機能しました。これにより、標準のAndroidテーマリストにあるテーマの組み合わせ爆発を回避できます。