Android 主题与style概述

来源:互联网 发布:怎么成为算法工程师 编辑:程序博客网 时间:2024/05/01 15:39

前言:
很多Android应用都提供不同的主题供用户选择。切换主题后,应用的背景,字体等会相应发生改变。这样的功能是怎么做的的呢?
在同一个界面,字体大小,颜色,背景等也可以有所不同,怎么设置和应用这些不同样式?

接下来,就让我们一起大概了解一下Android的主题。

一、Android主题(Theme)和样式(Style)简介

在Android应用资源目录下,res/values/目录有style.xml和theme.xml文件,在这两个xml中我们可以自定义需要的主题和样式,如果工程中没有这两个文件的话我们可以自己创建。

比如在styles.xml中自定义一个样式。文件完整代码如下:

<resources><style name="MyTheme" parent="@android:style/Theme.NoTitleBar">          <item name="android:layout_width">fill_parent</item>        <item name="android:layout_height">wrap_content</item>          <item name="android:textColor">#ffff00</item>          <item name="android:typeface">monospace</item>         <item name="stringValue">"hello"</item>        <item name="colorBackground">@android:color/holo_blue_light</item></style></resources>

这样一个简单的样式就定义好了。themes.xml中自定义样式的规则和styles.xml是一样的。
下面解释下这段代码:

1.style name=”MyTheme”` 指明了这个样式的名字为”MyTheme”。

2.parent="@android:style/Theme.NoTitleBar" 指明我们自定义的这个样式是继承自”Theme.NoTitleBar”这个系统预置样式。

注:我们自定义的样式必须继承自某个系统预置样式,即使不指明继承的是哪个样式,也会默认继承系统标准根样式。标准根样式视API的不同而有差别,比如API 14的默认根样式为Theme.DeviceDefault。

系统预置的样式定义位置为Android源码的frameworks/base/core/res/res/values目录下以下几个文件:
themes.xml,themes_device_defaults.xml,styles.xml,styles_device_defaults.xml
这几个文件中定义了各种系统Theme,Style。

3.fill_parent` 定义了在这个样式里,属性layout_width的值为fill_parent。也就是说,谁用了这个样式,谁的layout_width的属性值就是fill_parent, 其余的属性以类似方式定义。

其中有两个我自定义的属性“stringValue”和”colorBackground”,。
如何自定义属性呢?在res/values/目录有attrs.xml文件,用于自定义属性。
比如一个attrs.xml文件实例如下:

<?xml version="1.0" encoding="utf-8"?>  <resources>      <attr name="colorValue" format="color" />      <attr name="floatValue" format="float" />      <attr name="integerValue" format="integer" />      <attr name="booleanValue" format="boolean" />      <attr name="dimensionValue" format="dimension" />      <attr name="stringValue" format="string" />      <attr name="colorBackground" format="reference" />  </resources>

这里面自定义了多种格式的属性,我上面用到的是后两个,一个是String类型,一个引是用类型的属性。

二、style.xml和theme.xml有什么区别?
1、使用的地方不同

1).theme.xml:应用于整个application或Activity,不能用于单独的View。2) style.xml:用于单独的View。

2、在R.attr定义中以window开头的一些属性只对theme有效。
3、如果一个应用使用了theme,同时应用下的view也使用了style,那么当theme与样式style发生冲突时,style的优先级高于theme。

三、theme和style的用法:
1、AndroidManifest中的用法

    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@android:style/Theme.Black">        <activity            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application>

2、Activity的用法

<activity      android:theme="@style/styleTheme"      android:label="@string/app_name"      android:name=".HelloTietuActivity" >      <intent-filter >          <action android:name="android.intent.action.MAIN" />          <category android:name="android.intent.category.LAUNCHER" />      </intent-filter>  </activity> 

3、Android控件的用法

<EditText android:layout_height="wrap_content"   android:text="EditText"   style="@style/Title"   android:layout_width="fill_parent"   android:id="@+id/editText1"/><TextView      android:id="@+id/text"      android:layout_width="wrap_content"      android:layout_height="wrap_content"       android:text="?attr/stringValue"/>

4、代码中动态设置:
如果使用setTheme()来动态设置主题,那么setTheme()应该在初始化任何View之前调用。比如在setContentView(View) 和inflate(int, ViewGroup)方法前调用。
如果要使用动态切换主题,那么就必须调用actvity.finish()。然后再重新加载setTheme()。
例子如下:

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... setTheme(android.R.style.Theme_Light); setContentView(R.layout.linear_layout_3);}

四、apk主题
很多手机提供了主题商城,还有很多第三方主题可以下载安装。这些下载的主题一般也都是apk包,安装后可以在data/app/主题包名/目录下找到。
我们自己如何制作并应用这样一个apk主题包呢?下面用一个例子简单说明。

首先要建立两个工程,一个要切换主题的主应用MainAPP,另一个是主题包工程MyTheme。

1、新建android工程MyTheme,package为:com.test.mytheme,在MyTheme工程的drawable文件夹下放入back.png文件,用作背景图。然后打包成apk安装。
2、MainAPP工程的drawable文件夹下也放入一个图片back.png,与MyTheme工程的同名但不是同一个图。
布局文件layout_main.xml内容如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:id="@+id/layout"    android:background="@drawable/back"    tools:context="com.example.androidtest.MainActivity" >    <Button        android:id="@+id/btn"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></LinearLayout>

可以看到我们给布局设置了背景图为back.png。

MainActivity的主要代码如下:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    final LinearLayout layout = (LinearLayout)this.findViewById(R.id.layout);    btn = (Button)findViewById(R.id.btn);    btn.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View v) {            // TODO Auto-generated method stub            try {                 Context appTheme = createPackageContext("com.test.mytheme", Context.CONTEXT_IGNORE_SECURITY);                Resources res = appTheme.getResources();                layout.setBackground(res.getDrawable(R.drawable.back,appTheme));            } catch (NameNotFoundException e) {                  e.printStackTrace();              }         }    });}

这样就实现了点击Button切换背景图的功能。
注意,上面我们用layout.setBackground(res.getDrawable(R.drawable.back,appTheme))设置新的背景,这个方法的参数在不同API中是不同的,如果这样不成功的话,可以改为layout.setBackground(res.getDrawable(R.drawable.back))。

在实际应用中,内置主题和apk主题一般是结合起来进行应用。在资源文件中预置几个主题,同时在代码中可以动态扩展更多主题。这样灵活性大,也易于维护。

0 0