2012-10-29 342 views
4

我有一個可以在運行時選擇的兩個主題(黑暗和光明)的應用程序。這工作。我也有一個列表視圖行可以有三種不同的佈局之一,每種佈局都有一種風格(比如不同的顏色)。這也適用。但是我不能讓這兩個功能一起工作。我真的需要六種不同的風格,三個爲一個主題(黑色),另外三個爲另一個(淺色),但我無法弄清楚如何根據當前主題爲列表項目選擇風格,或者獲得任何效果通過使用XML文件的其他方式。我的三個佈局都指向一個設置顏色的自定義主題,但是它覆蓋了我設置的任何主題。主題只能包含「風格化」的項目,所以我不能將自己的自定義項目放在那裏。可能有一種方法可以通過編程來實現,但我希望能夠以聲明方式進行。有任何想法嗎?動態主題和自定義樣式

+1

看看[這個答案](http://stackoverflow.com/q/12338244/1531054)。 –

回答

7

感謝wingman對於the hint。我的情況涉及顏色,這有點複雜,所以我會在這裏寫下我的解決方案。

我有兩個主題(光明和黑暗),用戶可以從設置屏幕中選擇。我有一個ListView,它可以有兩種類型的行(plain和note),每個行都有自己的樣式。首先每個佈局必須指向一個風格:

<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"/> 

然後我們可以定義各種顏色。這裏我們有兩個樣式和兩個主題,所以我們需要四個顏色狀態列表,每個列表在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> 

選定/聚焦/按顏色在所有這些文件相同的,因爲他們是在高亮顏色。請注意0​​版本。它的行爲並不像廣告一樣,在所有情況下,我都必須將其設置爲默認顏色(上面的最後一行)。現在我們需要創建主題並將屬性綁定到其中一種顏色。這些線路進入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> 

最後我們選擇在運行時一個主題,在活動的onCreate()方法,調用super.onCreate()

if (isDarkTheme) { 
    activity.setTheme(R.style.Theme_Dark); 
} else { 
    activity.setTheme(R.style.Theme_Light); 
} 

請注意,我沒有考慮到像Holo這樣的新主題,所以我的應用在Honeycomb和更高版本上看起來很老。我會在某個時候解決這個問題,但這不是一個迴歸。


在我的情況扭曲是,一些活動有一個更大的標題欄,以適應一些按鈕。原則上,我應該創造出四個主題,一個狹窄的標題是明暗的,一個是肥胖的標題是明暗的。但是,我創建了混合風格:

<!-- 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主題列表中找到的主題的組合爆炸。

+2

很遺憾,我們無法在樣式中定義樣式,所以您可以在明暗樣式/主題中使用不同版本的「PlainItemText」(等)樣式。最終,我發現風格僅適用於只有1個主題的應用程序,而attrs更適合在一個應用程序中實現多個主題。 – Tom

+0

是的:我必須使用attrs,因爲我有多個主題。 –

1

這是很久以前的事勞倫斯Kesteloot在2012年出版了他的解決方案現在是六年之後,在Android的新的一個上午,並嘗試解決類似的問題:

我如何可以交換整體風格通過交換一個主題的應用程序?

這是勞倫斯問題如何組織兩個可交換主題的概括。

我想出了一個基於勞倫斯的解決方案,並且更進一步。

(不是說這是完美的解決方案,但有所改善。)

勞倫斯想通了的用戶定義的功率屬性來達到這個目標。他使用它們根據當前選定的主題來處理顏色。

雖然這是工作,它仍然需要爲每個屬性定義屬性。它不能很好地擴展。那麼爲什麼不將這些屬性捆綁到樣式和主題中並使用相同的機制呢?

這會導致主題,即定義子主題和樣式。

RES /值/ attrs.xml

<resources> 
    ... 
    <attr name="mainViewTheme" format="string"/> 
    <attr name="asideViewTheme" format="string"/> 
    ... 
</resources> 

當定義設置主題屬性,對於它沒有特殊的格式。格式字符串做它。

RES /價值/ styles.xml

<style name="MasterTheme"> 
    ... 
    <item name="mainViewTheme">@style/MainViewTheme</item> 
    <item name="asideViewTheme">@style/AsideViewTheme</item> 
    ... 
</style> 

<style name="MainTextTheme"> 
    ... 
</style> 

<style name="MainViewTheme"> 
    ... 
</style> 

RES /佈局/ main.xml中

<TextView 
    android:theme="?mainViewTheme" 
    ... 

通過交換主主題的所有樣式進行調整。它仍然需要定義一些主題屬性,然後做一個強大的工作。爲每個屬性設置屬性不再需要。

+1

這不提供問題的答案。你可以[搜索類似的問題](// stackoverflow.com/search),或者參考頁面右側的相關和鏈接問題來找到答案。如果你有一個相關但不同的問題,[問一個新問題](// stackoverflow。com/questions/ask),幷包含一個鏈接以幫助提供上下文。請參閱:[問問題,獲得答案,沒有分心](// stackoverflow.com/tour) – LW001

+1

我認爲,它給出了一個問題的答案。這是勞倫斯解決方案的改進,他肯定認爲他的解決方案是一個答案。 – Blcknx

+0

如果您有新問題,請點擊[Ask Question](問問題)(https://stackoverflow.com/questions/ask)按鈕。如果有助於提供上下文,請包含此問題的鏈接。 - [來自評論](/ review/low-quality-posts/18784562) –

相關問題