官术网_书友最值得收藏!

2.6 樣式和主題的使用

Android中,樣式(Style)是一種用于描述一組屬性的機制,可以應用于控件(View)或者窗口。

樣式通常有兩種使用方法:

(1)在布局文件中將其應用于控件標簽,此時通常依然稱之為樣式(style)。

(2)在AndroidManifest.xml中將其應用于一個Activity或者一個application,此時通常稱之為主題(Theme)。此時相當于將這個樣式應用于其中的所有控件。

樣式可以使用系統的預置的定義,也可以自定義。預定義使用R.style類,自定義樣式通常在一個XML文件中使用<style>標簽來描述。

2.6.1 控件中的樣式

控件的樣式讓布局文件中的眾多控件擁有相同的屬性,使用樣式不僅可以減少布局文件中重復的內容,也有利于全局控制控件的外觀等公共屬性。

Android中預定義的樣式,使用R.style類中的各個成員來表示。樣式的本質是對各個XML屬性進行定義,這些XML屬性在Android中使用R.attr類來表示。

每個控件的style屬性可以用于設置它的樣式,在布局文件中可以使用類似style="@android:style/MediaButton"的方式。

例如,在某個布局文件中一個控件的定義如下所示:

        <TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#00FF00"         android:typeface="monospace"
            android:text="@string/hello" />

此時如果認為除了android:text之外的屬性都是作為公共的內容實現的,可以利用樣式將這個控件寫成如下方式:

        <TextView  style="@style/CodeFont" android:text="@string/hello" />

此時的style屬性被設置為名稱為CodeFont的樣式。可以使用res/values/目錄中的styles.xml文件進行定義,內容如下所示。

        <?xml version="1.0" encoding="utf-8"?>
        <resources>
            <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
              <item name="android:layout_width">fill_parent</item>
              <item name="android:layout_height">wrap_content</item>
              <item name="android:textColor">#00FF00</item>
              <item name="android:typeface">monospace</item>
            </style>
        </resources>

這里進行的自定義樣式CodeFont繼承了Android預置的樣式TextAppearance.Medium,并且定義了android:textColor等幾個屬性。定義完成后可以在各個布局文件中使用。

2.6.2 全局性質的主題

在AndroidManifest.xml中使用android:theme屬性來表示設置一種樣式作為全局性的內容。<application>和<activity>標簽具有這個屬性。此時應用的樣式中的內容,對其中的所有內容都起作用。

Android預置的主題來自android.R.style中的Theme_*等常量。除了預置的主題,可以繼承預定義樣式實現自定義主題,也可以生成完全的自定義主題。

提示:主題和樣式在本質上是相同的,都是對XML文件中的一組屬性進行默認的定義。在Android中,應用于控件時稱之為樣式(Style),應用于活動和應用時稱之為主題(Theme),后者通常比前者多了一些和窗口屬性相關的定義。

主題的設置也可以在代碼中使用,這種方式并不常用。Activity的父類ContextThemeWrapper中具有如下的方法:

        public void setTheme (int resid)

1.預定義主題

android.R.style類中有屬性常量名稱為Theme_Light_NoTitleBar_Fullscreen,那么在AndroidManifest.xml使用的就是如下的格式:

需要將“_”替換成“.”,然后可以在AndroidManifest.xml中使用。大多數預定義樣式都有子類,Theme.<style>.NoTitleBar表示使用該樣式加無標題欄的效果,Theme.<style>.NoTitleBar.Fullscreen表示使用該樣式加全屏的效果。

使用不同樣式示例程序:Controls(ApiDemo=>Views=>Controls)

源代碼:

              com/example/android/apis/view/Controls1.java
              com/example/android/apis/view/Controls2.java

布局文件:controls_1.xml

使用不同樣式的示例程序如圖2-19所示。

圖2-19 使用不同樣式的示例程序(左:Theme.Light樣式;右:默認樣式)

兩個活動使用同樣的布局文件,兩個活動的內容基本是相同的,運行的效果卻是一個白底色一個黑底色。它們的主要區別體現在AndroidManifest.xml中,如下所示:

        <activity android:name=".view.Controls1"
              android:label="Views/Controls/1. Light Theme"
              android:theme="@android:style/Theme.Light">
            <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.SAMPLE_CODE" />
            </intent-filter>
        </activity>
        <activity android:name=".view.Controls2"
                  android:label="Views/Controls/2. Default Theme">
            <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.SAMPLE_CODE" />
            </intent-filter>
        </activity>

第二個程序使用了默認樣式,而第一個程序使用了"@android:style/Theme.Light",表示使用的是Theme.Light樣式,在這種情況下底色變成了淺色的效果。

在Activity的代碼中進行的樣式設置如下所示:

        protected void onCreate(Bundle savedInstanceState) {
            setTheme(android.R.style.Theme_NoTitleBar);
            super.onCreate(savedInstanceState);
            // ......省略活動的創建過程
        }

對于代碼中的樣式設置,由于執行場合不同,因此即使將設置的代碼放在Activityd的onCreate()方法的最前面,也不能保證和在AndroidManifest.xml中設置的效果相同。

2.自定義主題

根據預定義樣式,可以通過繼承的方法實現自定義的樣式。這種自定義樣式通常只改變預定義樣式的部分屬性,一般可以在res/values/styles.xml文件中通過<style>標簽來完成定義,然后將其設置到AndroidManifest.xml中的android:theme屬性。此時使用的是類似android:theme="@style/MyTheme"的格式。

參考程序為一個對話框樣式的活動和一個自定義對話框樣式的活動。

示例程序:

                    DialogActivity(ApiDemo=>App=>Activity=> DialogActivity)
                    CustomDialogActivity(ApiDemo=>App=>Activity=>CustomDialogActivity)

源代碼:com/example/android/apis/app/DialogActivity.java

布局文件:custom_dialog_activity.xml

樣式文件:res/values/styles.xml

兩個活動運行結果如圖2-20所示。

圖2-20 預定樣式和自定義樣式實現類似對話框的活動運行結果

上述兩個程序本質上都是活動,但是顯示的效果卻類似于一個對話框。透過對話框透明的部分,可以看到下面的活動。

這兩個程序的布局文件和源代碼都并無特別的地方。效果是通過在AndroidManifest.xml中設置其樣式android:theme來完成的。

AndroidManifest.xml中的定義如下所示:

        <activity android:name=".app.DialogActivity"
              android:label="@string/activity_dialog"
              android:theme="@android:style/Theme.Dialog" >
              <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.SAMPLE_CODE" />
              </intent-filter>
        </activity>
        <activity android:name=".app.CustomDialogActivity"
              android:label="@string/activity_custom_dialog"
              android:theme="@style/Theme.CustomDialog“ >
            <intent-filter>
                  <action android:name="android.intent.action.MAIN" />
                  <category android:name="android.intent.category.SAMPLE_CODE" />
            </intent-filter>
        </activity>

DialogActivity將樣式設置為“@android:style/Theme.Dialog”,表示使用預定義的樣式Theme.Dialog。

CustomDialogActivity將樣式設置為“@style/Theme.CustomDialog”,表示使用名稱為Theme.CustomDialog的自定義樣式。

CustomDialog是一個自定義樣式,在res/values/styles.xml中進行定義,如下所示:

        <style name="Theme.CustomDialog" parent="android:style/Theme.Dialog">
              <item name="android:windowBackground">@drawable/filled_box</item>
        </style>

使用“parent”表示由CustomDialog本身繼承的預定義樣式,重新定義了窗口的背景為drawable中的filled_box。這里引用了filled_box.xml文件,這個文件在res/drawable中,其中定義了相關內容。在定義的樣式中,通過設置更多的值來獲得不同的窗口效果。通過自定義樣式文件可以獲得復用效果。

提示:類似的對話框場景,前臺的程序沒有覆蓋住整個屏幕,此時后面依然處于可見狀態的活動是onPause()狀態,通常情況下,活動是完全被遮擋的,處于onStop()狀態。

3.完全自定義樣式作為主題

樣式可以在程序中全新定義,通過定制各個屬性進行定義。這些屬性來自于R.attr類中的內容進行定義。具體每一個屬性可以使用的值,可以從R.attr類的幫助文檔中找到。

由于繼承主題的方式實際上使用的是“單繼承”,因此如果想組合主題,隨心所欲地設置效果,最終的方式還是直接設置屬性。

例如,如果在res/values/styles.xml中定義如下內容:

        <style name="Theme.WindowTranslucent ">
            <item name="android:windowIsTranslucent">true</item>
        </style>

定義名稱為Theme.WindowTranslucent的樣式,表示背景透明的效果。這里進行自定義的windowIsTranslucent就是R.attr類的一個成員。雖然主題只能繼承一個,但是可以進行多數量屬性的設置。

在Android程序中,當某一個活動啟動之后,可能需要使用背景透明的效果,本例用于描述背景透明的應用。

參考示例程序:

                  TranslucentActivity(ApiDemo=>App=>Activity=>Translucent)
                  TranslucentBlurActivity(App=>Activity=>TranslucentBlur)

源代碼:

              com/example/android/apis/app/TranslucentActivity.java
              com/example/android/apis/app/TranslucentBlurActivity.java

樣式文件:values/styles.xml

透明程序的運行結果如圖2-21所示。

圖2-21 TranslucentActivity和TranslucentBlurActivity程序的運行結果

AndroidManifest.xml中的定義如下所示:

        <activity android:name=".app.TranslucentActivity"
              android:label="@string/activity_translucent"
              android:theme="@style/Theme.Translucent“ >
            <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.SAMPLE_CODE" />
            </intent-filter>
        </activity>
        <activity android:name=".app.TranslucentBlurActivity"
              android:label="@string/activity_translucent_blur"
              android:theme="@style/Theme.Transparent“ >
            <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.SAMPLE_CODE" />
            </intent-filter>
        </activity>

兩個活動分別使用Theme.Translucent和Theme.Transparent主題,它們都是自定義的主題,內容在values/styles.xml中。

Theme.Translucent主題如下所示:

        <style name="Theme.Translucent" parent="android:style/Theme.Translucent">
            <item name="android:windowBackground">
                  @drawable/translucent_background</item>
            <item name="android:windowNoTitle">true</item>
            <item name="android:colorForeground">#fff</item>
        </style>

Theme.Transparent主題如下所示:

        <style name="Theme.Transparent">
            <item name="android:windowIsTranslucent">true</item>
            <item name="android:windowAnimationStyle">
                        @android:style/Animation.Translucent</item>
            <item name="android:windowBackground">
                        @drawable/transparent_background</item>
            <item name="android:windowNoTitle">true</item>
            <item name="android:colorForeground">#fff</item>
        </style>

Theme.Transparent實際上是一個沒有繼承預定義主題的主題,在其中自定義了windowIsTranslucent和windowAnimationStyle屬性,取得了和繼承Theme.Translucent類似的效果,并且使用了windowNoTitle表示設置為沒有標題欄。

兩個主題使用的背景數值在colors.xml中定義,如下所示:

        <drawable name="translucent_background">#e0000000</drawable>
        <drawable name="transparent_background">#00000000</drawable>

除此之外,TranslucentBlurActivity之所以能夠獲得背景模糊的效果,是因為在源代碼中進行了進一步的設置,如下所示:

        public class TranslucentBlurActivity extends Activity {
            protected void onCreate(Bundle icicle) {
              super.onCreate(icicle);
              getWindow().       // 獲得窗口,用以設置其中的特性
                  setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
                                  WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
              setContentView(R.layout.translucent_background);
            }
        }

設置模糊效果是通過窗口管理器設置參數來完成的,這種設置只有在背景設置為透明后才能顯示效果。

主站蜘蛛池模板: 宁德市| 巨鹿县| 勐海县| 宜良县| 灵璧县| 五家渠市| 长沙市| 江川县| 万全县| 西丰县| 罗城| 泗水县| 峨山| 进贤县| 陕西省| 勃利县| 剑阁县| 临猗县| 莱阳市| 宁明县| 双柏县| 乡城县| 湟中县| 富民县| 江口县| 瓦房店市| 彭泽县| 临朐县| 德兴市| 南乐县| 红原县| 盈江县| 贞丰县| 济源市| 黑龙江省| 木兰县| 东乡族自治县| 抚顺县| 康平县| 临沧市| 营山县|