作者:李旺成###
時間:2016年4月9日###
前兩天稍微整理了下 Android4.x 中提供的一些新技術汰寓,當時就想著趕緊把 Android5.x 中的也整理一下口柳。這兩天整理資料的時候才發(fā)現(xiàn),當時就關注了下新控件有滑,而沒有注意其他的更新跃闹。一整理,嚇一跳 —— 內(nèi)容很多呢(最新的思維導圖里面砍了不少內(nèi)容俺孙,顧不過來辣卒,挑重點的介紹下吧)。所以這里打算分成幾篇文章分別介紹一下 Android 5.x 中的新 API (兩篇)以及 Android 5.x 中的新控件(兩到三篇)睛榄。
這是 Android 5.x 系列的第一篇荣茫,以介紹 5.x 中提供的新 API (比較有意思的)為切入點進行展開,關于 Android 5.x 的新特性這里就不多說了场靴,感興趣的可以下載思維導圖啡莉,里面稍微整理了點內(nèi)容(作為大致了解應該夠了)港准。
好了,入正題咧欣,今天打算介紹幾個值得注意的新 API浅缸。
一、elevation 和 translationZ
Android 5.0 之前 View 通過 x魄咕,y 確定其大小和位置衩椒,Android 5 引入了 Z 軸的概念,而這個 Z 軸的值就是 View 的高度(elevation)哮兰,有了高度就帶來了陰影毛萌。于是就出現(xiàn)這種風格 —— Material Design(這不是今天的重點,以后會安排專題闡述)喝滞。如下圖所示:
View 的 z 值包括兩部分阁将,就是標題上的 elevation 和 translationZ。
eleavation:設置該組件“浮”起來的高度右遭,通過設置該屬性可以讓該組件呈現(xiàn)3D效果
translationZ:設置該組件在Z方向(垂直屏幕方向)上的位移做盅,可用來做動畫(回憶下屬性動畫中用過的 translationX 和 translationY)。
使用方法:
Layout:
android:elevation
android:translationZ
Java 代碼:
setElevation(float)
setTranslationZ(float)
提示:
新的 ViewPropertyAnimator.z 和 ViewPropertyAnimator.translationZ 方法可以設置視圖的 elevation 值窘哈。(參考自:ANDROID L——Material Design詳解(視圖和陰影))
看效果:
上代碼:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<!-- 通過屬性設置 elevation -->
<TextView
android:id="@+id/tv_testeleavation1"
android:layout_width="60dp"
android:layout_height="60dp"
android:elevation="0dp"
android:gravity="center"
android:text="@string/text_0dp"
android:textColor="#000000"
android:textSize="20sp"
android:textAllCaps="false"
android:background="@drawable/bg_text"/>
<TextView
android:id="@+id/tv_testeleavation2"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_toRightOf="@+id/tv_testeleavation1"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:elevation="15dp"
android:gravity="center"
android:onClick="onClick"
android:text="@string/text_15dp"
android:textColor="#000000"
android:textSize="20sp"
android:textAllCaps="false"
android:background="@drawable/bg_text"/>
<TextView
android:id="@+id/tv_testeleavation3"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_toRightOf="@+id/tv_testeleavation2"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:elevation="30dp"
android:gravity="center"
android:onClick="onClick"
android:text="@string/text_30dp"
android:textColor="#000000"
android:textSize="20sp"
android:textAllCaps="false"
android:background="@drawable/bg_text"/>
<TextView
android:id="@+id/tv_testeleavation4"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_toRightOf="@+id/tv_testeleavation3"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:elevation="45dp"
android:gravity="center"
android:onClick="onClick"
android:text="@string/text_45dp"
android:textColor="#000000"
android:textSize="20sp"
android:textAllCaps="false"
android:background="@drawable/bg_text"/>
<View
android:id="@+id/view_test1"
android:layout_width="70dp"
android:layout_height="70dp"
android:background="#00ff00"
android:layout_centerInParent="true"
android:clickable="true"
android:onClick="onClick"/>
<View
android:id="@+id/view_test2"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_toRightOf="@+id/view_test1"
android:layout_marginLeft="-15dp"
android:background="#ff0000"
android:layout_centerInParent="true"/>
<View
android:id="@+id/view_test3"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="50dp"
android:translationZ="20dp"
android:background="#ff00ff"/>
<!-- 通過屬性設置 translationZ -->
<View
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_toLeftOf="@+id/view_test3"
android:layout_alignBottom="@+id/view_test3"
android:translationZ="0dp"
android:background="#000000"/>
</RelativeLayout>
在 Java 代碼中設置吹榴,上代碼:
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_testeleavation1:
changeElevation(v);
break;
case R.id.tv_testeleavation2:
changeElevation(v);
break;
case R.id.tv_testeleavation3:
changeElevation(v);
break;
case R.id.tv_testeleavation4:
changeElevation(v);
break;
case R.id.view_test1:
changeTranslationZ(v);
break;
}
mFlag = !mFlag;
}
private void changeElevation(View v) {
v.setElevation(100.0f);
}
private void changeTranslationZ(View v) {
if (mFlag) {
v.setTranslationZ(120);
} else {
v.setTranslationZ(0);
}
}
二、tint
Tint:著色宵距,對就是給背景著色腊尚,正式點的說法就是對視圖進行顏色渲染吨拗。下面我們使用 tint 屬性給背景調(diào)整不同顏色满哪。
Layout:
android:tint
android:backgroundTint
android:foregroundTint
android:drawableTint
Java 代碼:
setImageTintList(ColorStateList tint)
提示:
有不少介紹 tint 屬性原理的文章,感興趣的劝篷,可以去看看哨鸭。如: Andorid-Tint使用與原理解析
先看效果圖:
ImageView 擁有 tint 這個屬性,它可以給 ImageView 的 src 設置娇妓。除了tint 之外像鸡,還有 backgroundTint, foregroundTint, drawableTint,它們分別對應對背景、前景哈恰、drawable 進行著色處理只估。 如上圖所示,分別用src/background 與 這些屬性進行了組合着绷。
上源碼(為縮短篇幅源碼做了節(jié)選蛔钙,具體請下載 Demo 項目):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/tv_test1_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_test1_tip"/>
<!-- src + tint 演示-->
<ImageView
android:id="@+id/iv_test1"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_below="@+id/tv_test1_tip"
android:src="@mipmap/ic_tint_demo"/>
<ImageView
android:id="@+id/iv_test2"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_below="@+id/tv_test1_tip"
android:layout_toRightOf="@+id/iv_test1"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:src="@mipmap/ic_tint_demo"
android:tint="#2C3E50"/>
<ImageView
android:id="@+id/iv_test3"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_below="@+id/tv_test1_tip"
android:layout_toRightOf="@+id/iv_test2"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:src="@mipmap/ic_tint_demo"
android:tint="#ffcc00"/>
...
</RelativeLayout>
三、setClipToOutline
View.setClipToOutline 方法可以去剪切一個視圖的 outline 區(qū)域荠医。
要注意的是只有 rectangle, circle 和 round rectangle outlines 支持裁剪吁脱,可以調(diào)用 Outline.canClip 方法來判斷是否支持裁剪桑涎。
裁剪可以分為如下三步:
- 創(chuàng)建一個 ViewOutlineProvider
- 調(diào)用 setOutlineProvider 設置 ViewOutlineProvider
- 調(diào)用 View.setClipToOutline 方法,實現(xiàn)裁剪
先看效果圖:
注意:
這里面有坑兼贡,中興有些機器竟然沒有裁剪效果攻冷,沒效果,沒效果...
上述效果為 小米 Note 更新到最新系統(tǒng)上實現(xiàn)遍希。
不用多解釋等曼,都在代碼里,看代碼:
private void clip1() {
ViewOutlineProvider outlineProvider = new CircleOutlineProvider();
mViewTest1.setOutlineProvider(outlineProvider);
mViewTest1.setClipToOutline(true);
}
private void clip2() {
ViewOutlineProvider outlineProvider = new RoundRectOutlineProvider();
mViewTest2.setOutlineProvider(outlineProvider);
mViewTest2.setClipToOutline(true);
}
private void clip3() {
ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int margin = 20;
int size = view.getHeight();
outline.setRect(margin, margin, size - margin, size - margin);
}
};
mViewTest3.setOutlineProvider(viewOutlineProvider);
mViewTest3.setClipToOutline(true);
}
四凿蒜、Activity Transitions 動畫#
android L 增加了一些 Activity 的轉(zhuǎn)場動畫 —— 爆炸涉兽、滑動、淡入淡出篙程,讓應用更加平滑枷畏。使用這些動畫,需要在進入和退出 Activity 都使用這些內(nèi)容轉(zhuǎn)場特效虱饿,并且在 setOncontent() 方法之前拥诡。當然,也支持通過樣式設置轉(zhuǎn)換動畫氮发。
Activity Transitions 有兩類
Enter(進入):進入一個 Activity 的效果
Exit(退出):退出一個 Activity 的效果
這每種類型又可以分為普通 Transition 和共享元素 Transition:
普通 Transition:
explode:從場景的中心移入或移出
slide:從場景的邊緣移入或移出
fade:調(diào)整透明度產(chǎn)生漸變效果
共享元素 Transition:
作用是共享兩個 Acitivity 中共同的元素渴肉,在 Android L 中支持如下效果:
changeBounds - 改變目標視圖的布局邊界
changeClipBounds - 裁剪目標視圖邊界
changeTransform - 改變目標視圖的縮放比例和旋轉(zhuǎn)角度
changeImageTransform - 改變目標圖片的大小和縮放比例
看效果:
Activity Transition 使用簡介
通過如下兩步,即可使用 Activity Transition:
Step1: 修改 Theme爽冕,設置允許使用 transition仇祭,當然還需要設置 transition
<style name="diygreenTheme" parent="android:Theme.Material">
<!-- 設置允許使用 transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- 指定進入和退出 transitions -->
<item name="android:windowEnterTransition">@anim/explode</item>
<item name="android:windowExitTransition">@anim/explode</item>
</style>
transition 動畫定義:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode/>
<changeBounds/>
<changeTransform/>
<changeClipBounds/>
<changeImageTransform/>
</transitionSet>
當然,也可以在代碼中實現(xiàn)上述功能(還是代碼中簡單靈活):
// 允許使用 transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// 設置一個 exit transition
getWindow().setExitTransition(new Explode());
代碼設置 transition 效果:
Window.setEnterTransition():普通transition的進入效果
Window.setExitTransition():普通transition的退出效果
Window.setSharedElementEnterTransition():共享元素transition的進入效果
Window.setSharedElementExitTransition():共享元素transition的退出效果
Step2: 啟動目標 Activity
通過上述的 Step1颈畸,我們已經(jīng)設置了允許使用 Transition乌奇,并設置了Transition 動畫。現(xiàn)在就可以通過調(diào)用 ActivityOptions.makeSceneTransitionAnimation() 方法來啟動一個新的Activity 來激活這個 Transition眯娱。
注意: 啟用共享元素 Transition 和普通 Transition 稍有不同礁苗。
啟用普通的 Transition:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
啟用共享元素 Transition:
要在所有需要共享視圖的 Activity 中,使用 android:transitionName 屬性給需要共享的元素分配一個通用的名字徙缴。如下:
Intent intent = new Intent(this, Activity2.class);
// shareView: 需要共享的視圖
// "shareName": 設置的android:transitionName="shareName"
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, shareView, "shareName");
startActivity(intent, options.toBundle());
如有多個 View 需要共享试伙,可通過 Pair.create() 方法創(chuàng)建多個匹配對,然后傳入 ActivityOptions.makeSceneTransitionAnimation于样。代碼如下:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(shareView1, "shareName1"), Pair.create(shareView2, "shareName2"));
說明:
如果不想使用 Transition 可以將 options bundle 置為 null疏叨。
當需要結束當前Activity并回退這個動畫時調(diào)用finishAfterTransition()方法,代碼如下:
@Override
public void onBackPressed() {
super.onBackPressed();
finishAfterTransition();
}
說明:關于轉(zhuǎn)場動畫在這里就不多做介紹了穿剖,在 AndroidStudyDemo 系列中會專門有一個專題講解各種動畫效果蚤蔓。
五、setTaskDescription
使用android:persistableMode 屬性携御,可以將“最近用過”屏幕中的任務設置為在重新啟動過程中保持不變昌粤。
也可以通過調(diào)用 setTaskDescription() 方法既绕,來更改“最近用過”屏幕中活動的視覺屬性,如活動的顏色涮坐、標簽和圖標凄贩。
看效果:
代碼:
private void setDIYTaskDescription() {
String label = "DIY-green";
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_logo);
int colorPrimary = Color.parseColor("#666600");
ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(label, bitmap, colorPrimary);
setTaskDescription(taskDescription);
bitmap.recycle();
bitmap = null;
}
注意:這里拋磚引玉,ActivityManager 里面與 Task 相關的還有不少好玩的袱讹,有興趣的可以自行試試疲扎。
說明:這里有個坑,在小米 Note 上捷雕,miui 定制了活動預覽圖椒丧,所以使用上述代碼設置之后,無效救巷。
六壶熏、MediaBrowser 和 MediaSession
android.media.browse API 能讓 Android 5.0 應用在運行過程中瀏覽其他應用的媒體內(nèi)容庫。MediaBrowserService 代碼能使內(nèi)容顯示在原應用上浦译“艏伲總而言之,此 API 旨在實現(xiàn)不同應用間更好的融合——在視覺上呈現(xiàn)同樣的用戶界面精盅,在操作上免除重復的麻煩帽哑。(引自:盤點最受開發(fā)者喜愛的Android 5.0 Lollipop API)
除此之外,上圖所示的 MediaSession 代替已被棄用的 RemoteControlClient叹俏,提供一組傳輸控制和 Media Button 的回調(diào)函數(shù)妻枕。
下面看一下這兩個類所在包,和類圖:
本來想提供一些示例代碼粘驰,在網(wǎng)上查找資料的時候發(fā)現(xiàn)一個使用了這兩個類的項目屡谐,代碼量不是很小,所以做了一半就不打算繼續(xù)寫了晴氨。感興趣的童鞋康嘉,可以參考一下這個項目:MediaBrowserService 音樂播放項目
七、Camera2 API
從5.0開始(API Level 21)籽前,可以完全控制安卓設備相機的新api Camera2 (android.hardware.Camera2)被引入了進來。在以前的 Camera api(android.hardware.Camera)中敷钾,對相機的手動控制需要更改系統(tǒng)才能實現(xiàn)枝哄,而且 api 也不友好。這些老的 Camera API 在 5.0 上已經(jīng)過時阻荒,在以后的 app 開發(fā)中推薦的是 Camera2 API挠锥。
有哪些改進:
- 支持30fps的全高清連拍
- 支持幀之間的手動設置
- 支持RAW格式的圖片拍攝
- 支持快門0延遲以及電影速拍
- 支持相機其他方面的手動控制包括噪音消除的級別
相機的基本使用被分成了5個主要部分
- CameraManager
提供構建,列出以及鏈接相機設備的接口 - CameraDevice
代表和安卓設備相連的單個相機 - CameraCaptureSession
提供一套輸出目標的 - CaptureRequest
請求從相機獲取照片 - CaptureResult
從圖像傳感器獲得的單個圖片拍攝的結果
Camera 2 API 使用步驟:(參考自:Android 5.0 Lollipop新的攝像頭API)
- 獲取 CameraManager 實例侨赡,然后就可以遍歷蓖租、查詢和打開一個 Camera 對象
- 通過 CameraManager 對象的 getCameraCharacteristics() 方法來獲得 CameraCharacteristics 對象粱侣,該對象包含設備的設置信息和輸出參數(shù)
- 調(diào)用 camera.createCaptureSession() 可獲得 CameraCaptureSession 對象,該對象為每個預覽對象進行預設置蓖宦,如大小和格式(當然這些格式得是設備所支持的)
- 創(chuàng)建 SurfaceView 或 TextureView 渲染圖像
- 構造一個 CaptureRequest 對象齐婴,來描述每次捕獲圖片的具體設置
- 調(diào)用 capture() 方法完成圖像的捕獲
相機沒有過多研究,這里就不貼代碼了稠茂,推薦幾個使用 Camera API 2 開發(fā)的開源項目:
-
Camera2 Basic
演示如何使用 Camera2 API 基本功能的 demo柠偶。你可以從中學會如何遍歷相機設備的所有特性,顯示預覽照片睬关,以及拍照诱担。 -
Camera2 Video
這個 demo 演示如何使用 Camera2 API 錄制視頻。 -
Camera2 master
使用Android L Camera2 API開發(fā)的示例應用程序电爹,具備拍照蔫仙,AWB,F(xiàn)lash丐箩,連拍功能 -
LCamera
L Camera 是一個開源的實驗性質(zhì)的 Camera 應用程序匀哄,基于 Android L 提供的新 API android.hardware.camera2,目前只支持在 Andorid 5.0 Lollipop 版本的 Nexus 5 和 Nexus 6上運行
今天的進度比我的預期慢了很多雏蛮,主要是因為相機這一塊很不熟悉涎嚼,今天先到這里,明天有時間繼續(xù)挑秉,希望會做得更好...
示例代碼:GitHub
Android 5.x 介紹第二篇來了法梯!
AndroidStudyDemo之Android5.x新API介紹(二)
附錄
Android 5.x 思維導圖
Android 5.x 思維導圖.png
參考
盤點最受開發(fā)者喜愛的Android 5.0 Lollipop API
Android 5.0新增5000多個API
Android 5.0 API新增和改進
ANDROID L——Material Design詳解(視圖和陰影)
Android Tint使用
Andorid-Tint使用與原理解析
ANDROID L——Material Design詳解(動畫篇)
淺析Android 5.0中多媒體相關的新特性
Android -- Camera2(Android5.0)
使用Camera2 替代過時的Camera API
Android實戰(zhàn)技巧之三十三:android.hardware.camera2使用指南