AppCompat 21实现低版本手机使用Material Design

来自: http://www.jcodecraeer.com//a/anzhuokaifa/androidkaifa/2014/1028/1856.html


Android5.0 Lollipop sdk发布以后,我就希望兼容包中也包含了新的Material Design主题,幸运的是的确如此。

这个新的主题包含在AppCompat 21中,所以需要注意的是如果你要将Material Design运用到以前的项目中,需要做点额外的工作。

本文演示用最基本的工具创建一个以Material作为主题的应用。我这里并不会详细的介绍如何应用这个主题,而是重点介绍如何向前兼容以及使用Lollipop中的transitions(过度效果)。

注:到目前位置Lollipop中的transitions仍然不能做到兼容非5.0系统的手机。

 

项目设置:

gradle项目中,你需要将compile sdk版本设置成21,如下:

android {      compileSdkVersion 21      buildToolsVersion "21.0.0"      defaultConfig {          applicationId "com.antonioleiva.materialeverywhere"          minSdkVersion 14          targetSdkVersion 21          versionCode 1          versionName "1.0"      }       ...  }  dependencies {      compile fileTree(dir: 'libs', include: ['*.jar'])      compile 'com.android.support:appcompat-v7:21.+'  }

 

指定Material Theme主题

你需要将自己的主题继承自Theme.AppCompat,新的AppCompat有你所需要的支持Material Design的兼容代码与资源文件。在values-v21中我用自定义的base thmeme代了原始主题,这是因为我要在里面使用5.0的各种transitions过度)效果。

values/themes.xml

 

<?xml version="1.0" encoding="utf-8"?>  <resources>      <style name="AppTheme" parent="AppTheme.Base"/>      <style name="AppTheme.Base" parent="Theme.AppCompat">          <item name="colorPrimary">@color/colorPrimary</item>          <item name="colorPrimaryDark">@color/colorPrimary</item>          <item name="android:windowNoTitle">true</item>          <item name="windowActionBar">false</item>      </style>  </resources>

 

values-v21/themes.xml

 

<?xml version="1.0" encoding="utf-8"?>  <resources>  <style name="AppTheme" parent="AppTheme.Base">      <item name="android:windowContentTransitions">true</item>      <item name="android:windowAllowEnterTransitionOverlap">true</item>      <item name="android:windowAllowReturnTransitionOverlap">true</item>      <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>      <item name="android:windowSharedElementExitTransition">@android:transition/move</item>  </style>  </resources>

在上面的代码中 我们设置了primary colors,同时去掉了actionbar,这是因为我们要使用一种新的工具替代它:ToolBar。后面我们将谈到ToolBar。

 

设置ToolBar

ToolBar基本上就是我们熟知的ActionBar,他们最主要的区别是ToolBar是我们所能控制的布局的一部分, 所以我们可以随意的实现一些自定义的效果,比如在ToolBar上使用动画、设定其高度之类的。

如下:

<android.support.v7.widget.Toolbar      xmlns:android="http://schemas.android.com/apk/res/android"      android:id="@+id/toolbar"      android:layout_width="match_parent"      android:layout_height="wrap_content"  android:background="?attr/colorPrimaryDark"/>

 

Toolbar使用的时候就跟一般的控件一样,但是我们得告诉activity,这里的ToolBar是ActionBar的替代者。

@Override      protectedvoidonCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(getLayoutResource());          Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);          if(toolbar != null) {              setSupportActionBar(toolbar);          }      }

 

如上所示当调用了setSupportActionBar(toolbar)之后toolbar就有了特殊的地位,虽然他只是activity布局中的一个元素,但是他能像actionbar那样直接显示menu目录中的菜单资源。 需要注意的是使用setSupportActionBar要求你的activity继承ActionBarActivity

 

Lollipop系统Activity之间的切换效果

上面我们提到了在5.0以下的系统中没法看到Lollipop中的那些生动的切换效果,所以我们得想法解决这个问题。兼容包为我们提供了以下方法:

ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(       activity, transitionView, DetailActivity.EXTRA_IMAGE);  ActivityCompat.startActivity(activity, newIntent(activity, DetailActivity.class),  options.toBundle());

ActivityCompat让我们连判断版本的代码都省了。

下面是我实现的一个demo app的效果,代码已经放在了github上。this project in my Github.

纠正:

ActivityOptionsCompat.makeSceneTransitionAnimation只能在5.0上才可以看到效果,在5.0以下只能确保程序不出错,但没有效果,其中的原因估计是这样的:

ActivityOptionsCompat的确支持makeSceneTransitionAnimation方法,但是没法开启Window.FEATURE_CONTENT_TRANSITIONS(不管是代码还是xml中),在本文的demo中开启FEATURE_CONTENT_TRANSITIONS的代码如下:

    <item name="android:windowContentTransitions">true</item>

这是21以上才有的属性。

当然也有可能ActivityOptionsCompat能开启FEATURE_CONTENT_TRANSITIONS,只是我们不知道而已。至少本文的demo是没有能够在5.0以下开启FEATURE_CONTENT_TRANSITIONS的。就差这一步 很无赖。