Android 主题与style概述

前言:
很多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的主要代码如下:

@Override
protected 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值