android 5.0主题风格研究

虽然关于Material Design开发的文章已经很多了,我也转载和翻译了一些,但是在实际应用过之后才感叹,“实践才是检验真理的唯一标准”。

通常,我们使用5.0的主题风格是利用appcompat,参见 AppCompat 21实现低版本手机使用Material Design 一文。 但是我在运行文章所给出的demo之后才发现,运行的界面效果跟文中所描述的效果差别很大,可以明显的感受到在平板上分辨率是有问题的。溢出菜单的图标和ToolBar上的文字是非常模糊的。在手机上虽然没有这么明显,但是也不够清晰。而且流畅度和动画效果一不理想。

遗憾的是在网上没有看到有人反映这个问题。

我初步的猜想是这样的,appcompat的资源文件有问题。

既然这样我就先研究不使用appcompat,直接使用sdk 5.0中的主题好了。所以这篇文章叫做android 5.0主题风格研究。

牛吃南瓜找不到开头,搞笑的是我发现使用appcompat 21兼容5.0的文章很多,但关于不使用兼容包的文章反倒几乎绝迹,只看到这篇官方的文章:Using the Material Theme 

但是这篇文章介绍的过于简单,按照这篇文章的说明我这样定义主题:

    -->
    <style name="AppBaseTheme" parent="android:Theme.Material.Light">
         <!-- Main theme colors -->
        <!--   your app branding color for the app bar -->
        <item name="android:colorPrimary">@color/primary</item>
        <!--   darker variant for the status bar and contextual app bars -->
        <item name="android:colorPrimaryDark">@color/primary_dark</item>
        <!--   theme UI controls like checkboxes and text fields -->
        <item name="android:colorAccent">@color/accent</item>
 
        <item name="android:windowActionBar">false</item>
    </style>

activity

package com.example.materialdemo;
 
import android.app.Activity;
import android.os.Bundle;
 
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.Toolbar;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            //setActionBar(toolbar);
              toolbar.inflateMenu(R.menu.main);
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

布局

<RelativeLayout 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"
 
    tools:context="com.example.materialdemo.MainActivity" >
    <Toolbar  
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="@color/primary"/>
</RelativeLayout>

我实际试了下效果感觉和4.0的holo主题没有区别:

QQ图片20150111135606.jpg

从上图中我们可以看出几个问题:

(1)toolbar并没有代替actionbar

(2)不管是toolbar还是还是actionbar上的溢出菜单图都是矩形小点,而我们看到的5.0应用都是圆点。

(3)似乎statusbar状态栏的颜色并没有效果。因为android:statusBarColor 是继承自 android:colorPrimaryDark的。

对于第一个问题,这是因为在代码中我们没有设置

setActionBar(toolbar);

而是设置

toolbar.inflateMenu(R.menu.main);

并不是我不想这么做,而是如果不使用appcompat,在定义主题发时候没法使用

<item name="windowActionBar">false</item>

于是在调用setActionBar(toolbar);的时候会报错。换成

<item name="android:windowActionBar">false</item>

倒是可以,但是根本不起作用,还是会报错。

对于第二个第三个问题,就完全是无厘头了。

不过有点改进的是没有模糊的现象。

看来使用原生sdk还是不行的,必须使用appcompat,不然连基本的特性都没有了。当然也有可能是我没设置对,但是考虑到基本没有人这样用,我也就放弃原生的做法了。依然转向appcompat。

于是又运行了一下AppCompat 21实现低版本手机使用Material Design 一文中的demo,这回我注意到,在eclipse上头警告:

[2015-01-11 14:16:50 - MaterialEverywhere] WARNING: Application does not specify an API level requirement!
[2015-01-11 14:16:50 - MaterialEverywhere] Device API version is 21 (Android 5.0.1)

难道是因为没有设置targetSdkVersion的原因,这是从android studio转过来的,一般在AndroidManifest.xml中是不会有这个设置的,于是我在AndroidManifest.xml中加上了

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

运行出来的界面和项目描述一模一样,动画效果也ok了。

 

总结


现在使用Material主题的话请一定使用appcompat实现。

一定要注意设置targetSdkVersion