編輯:關於Android編程
動畫在Material Design設計中給用戶反饋放用戶點擊時,並且在程序用戶界面中提供連貫的視覺。Material主題為按鈕(Button)和activity的轉換提供了一些默認的動畫,在android5.0(api 21)和更高的版本,你可以自定義這些動畫和創建一個新動畫:
觸摸反饋在Material Design中在觸摸點提供了一個即時視覺確認當用戶作用在UI元素。按鈕的默認觸摸反饋動畫是使用了新的RippleDrawable類,它會是波紋效果在不同狀態間變換。
大多數情況下,我們可以使用這個功能通過在xml文件中定義背景:
?android:attr/selectableItemBackground 有界限的波紋
?android:attr/selectableItemBackgroundBorderless 可以超出視圖區域的波紋
?android:attr/selectableItemBackgroundBorderless 是21新添加的api
另外,還以使用ripple
元素定義RippleDrawable
作為一個xml資源。
你可以給RippleDrawable對象分配一個顏色。使用主題的android:colorControlHighlight
屬性可以改變默認的觸摸反饋顏色。
更多信息,查看RippleDrawable類的api指南。
揭露動畫為用戶提供視覺上的持續性擋顯示或者隱藏一組界面元素。ViewAnimationUtils.createCircularReveal()
方法使你可以使用動畫效果來揭露或者隱藏一個視圖。
這樣揭露一個先前隱藏的視圖:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int
cx = (myView.getLeft() + myView.getRight()) /
2
;
int
cy = (myView.getTop() + myView.getBottom()) /
2
;
// get the final radius for the clipping circle
int
finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy,
0
, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
這樣隱藏一個先前顯示的視圖:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25// previously visible view
final
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int
cx = (myView.getLeft() + myView.getRight()) /
2
;
int
cy = (myView.getTop() + myView.getBottom()) /
2
;
// get the initial radius for the clipping circle
int
initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius,
0
);
// make the view invisible when the animation is done
anim.addListener(
new
AnimatorListenerAdapter() {
@Override
public
void
onAnimationEnd(Animator animation) {
super
.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
activity間轉換在Material Design程序中提供不同狀態間的視覺連接通過在公用元素上動作或者轉換。你可以為進入或退出的轉換自定義動畫,共享元素在不同的activity之間的轉換效果。
進入過渡決定activity中的視圖怎樣進入場景。比如在爆裂進入過渡效果中,視圖從屏幕外面飛向屏幕中間進入場景。
退出過渡決定activity中的視圖怎樣退出場景。比如,在爆裂退出過渡效果中,視圖從中間向遠處退出場景。
共享元素過渡決定兩個activity之間共享的視圖怎麼在兩個activity之間過渡。比如,兩個activity有一個相同的圖片,在不同的位置和不同的大小,changeImageTransform(圖片變換變化)讓共享元素平滑的平移和縮放圖片在兩個activity之間。
android 5.0(api 21)提供以下進入和退出效果:
所有過渡效果都繼承Visibility
類,因此支持作為一個進入或者退出過渡效果。
更多細節,看Transition
類的api指南。
Android5.0(api 21)也支持共享元素過渡效果:
當你在程序中開啟activity間的過渡動畫時,默認的交叉淡入淡出效果會在兩個activity之間激活。
一個共享元素過渡效果
首先,使用在從material theme繼承的樣式中,使用android:windowContentTransitions
屬性開啟窗口內內容過渡效果。也可以在樣式定義中第一進入,退出,共享元素的效果:
<
style
name
=
BaseAppTheme
parent
=
android:Theme.Material
>
<
item
name
=
android:windowContentTransitions
>trueitem
>
<
item
name
=
android:windowEnterTransition
>@transition/explodeitem
>
<
item
name
=
android:windowExitTransition
>@transition/explodeitem
>
<
item
name
=
android:windowSharedElementEnterTransition
>
@transition/change_image_transformitem
>
<
item
name
=
android:windowSharedElementExitTransition
>
@transition/change_image_transformitem
>
style
>
示例中的過渡change_image_transform
定義如下:
<
transitionSet
xmlns:android
=
http://schemas.android.com/apk/res/android
>
<
changeImageTransform
/>
transitionSet
>
changeImageTransform
元素對應ChangeImageTransform
類。更多信息,查看Transition
的api指南。
在代碼中啟用窗口內容過渡效果,使用Window.requestFeature()
方法:
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an exit transition
getWindow().setExitTransition(
new
Explode());
在代碼中定義過渡效果,使用下面的方法,並傳一個Transition
對象:
setExitTransition()
和setSharedElementExitTransition()
方法為調用的activity定義退出過渡效果,setEnterTransition()
和setSharedElementEnterTransition()
方法為調用的activity定義進入過渡效果。
為了達到完整的過渡效果,必須在進入的和退出的兩個activity上都啟用window內容過渡。否則,正調用的activity會開始退出過渡,你就會看到窗口過渡效果(比如縮放,或者淡出)。
更快的開始一個進入過渡,使用Window.setAllowEnterTransitionOverlap()
方法在被調用的activity。這讓你有更加激動人心的進入過渡效果。
如果你為一個activity開啟過渡並且設置了一個退出過渡效果,過渡效果會在你打開其他activity的時候激活,像這樣:
? 1 2startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(
this
).toBundle());
如果你給第二個activity設置了進入過渡動畫,過渡也會在第二個activity啟動的時候激活。當你啟動其他的activity時,如果需要禁用過渡效果,提供一個為null
的bundle選項。
使用一個場景過渡動畫在兩個activity之間包括一個共享元素:
android:transitionName
屬性ActivityOptions.makeSceneTransitionAnimation()
方法。 ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// get the element that receives the click event
final
View imgContainerView = findViewById(R.id.img_container);
// get the common element for the transition in this activity
final
View androidRobotView = findViewById(R.id.image_small);
// define a click listener
imgContainerView.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View view) {
Intent intent =
new
Intent(
this
, Activity2.
class
);
// create the transition animation - the images in the layouts
// of both activities are defined with android:transitionName=robot
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(
this
, androidRobotView,
robot
);
// start the new activity
startActivity(intent, options.toBundle());
}
});
對於在代碼中生成的動態共享視圖,使用`View.setTransitionName()方法在兩個activity中給指定相同的名字。
當完成第二個activity的時候,如果需要逆轉該過渡動畫,使用Activity.finishAfterTransition()方法代替Activity.finish()
使用一個場景過渡動畫在兩個activity之間包括多於一個共享元素,在兩個activity中定義所有的的共享元素使用android:transitionName
屬性(或使用View.setTransitionName()方法在所有的activity中),並且創建一個像下面這樣的ActivityOptions對象:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(
this
,
Pair.create(view1,
agreedName1
),
Pair.create(view2,
agreedName2
));
Material Design中,動畫依賴時間插值和空間移動模式曲線。在android5.0(api 21)和更高版本,你可以為動畫自定義時間曲線和移動曲線。
PathInterpolator
類是一個新的基於貝塞爾曲線或Path對象的插值器。這個插值器在1*1的正方形上定義了曲線運動,以(0,0)和(1,1)點作為錨點,根據夠照參數控制點。你也可以使用xml文件的定義一個路徑插值器,如:
<
pathInterpolator
xmlns:android
=
http://schemas.android.com/apk/res/android
android:controlX1
=
0.4
android:controlY1
=
0
android:controlX2
=
1
android:controlY2
=
1
/>
Material Design設計規范中,系統提供了三個基本曲線的xml資源:
我們可以給Animator.setInterpolator()
傳一個PathInterpolator
對象來設置。
ObjectAnimator
類有新的構造方法,你可以一次使用兩個或者屬性使用path獨立於坐標動畫。比如,下面的動畫使用一個Path對象去動作一個視圖的x和y屬性:
ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();
StateListAnimator
定義動畫當視圖的狀態改變的時候運行,下面的例子是怎麼在xml中定義一個StateListAnimator動畫:
<
selector
xmlns:android
=
http://schemas.android.com/apk/res/android
>
<
item
android:state_pressed
=
true
>
<
set
>
<
objectAnimator
android:propertyName
=
translationZ
android:duration
=
@android:integer/config_shortAnimTime
android:valueTo
=
2dp
android:valueType
=
floatType
/>
set
>
item
>
<
item
android:state_enabled
=
true
android:state_pressed
=
false
android:state_focused
=
true
>
<
set
>
<
objectAnimator
android:propertyName
=
translationZ
android:duration
=
100
android:valueTo
=
0
android:valueType
=
floatType
/>
set
>
item
>
selector
>
給視圖附加自定義的視圖狀態動畫,使用selector
元素在xml文件中定義一個動畫祥例子中這樣,給視圖分配動畫使用android:stateListAnimator
屬性。在代碼中使用,使用AnimationInflater.loadStateListAnimator()
方法,並且使用View.setStateListAnimator()
方法。
當你的主題是繼承的Material主題,按鈕默認有一個Z動畫。如果需要避免這個動畫,設置android:stateListAnimator
屬性為@null
即可。
AnimatedStateListDrawable
類讓你創建可繪制圖在相關聯的視圖狀態改變。android5.0的一些系統組件默認使用這些動畫。下面的例子是如何在xml文件中定義一個AnimatedStateListDrawable
:
<
animated-selector
xmlns:android
=
http://schemas.android.com/apk/res/android
>
<
item
android:id
=
@+id/pressed
android:drawable
=
@drawable/drawableP
android:state_pressed
=
true
/>
<
item
android:id
=
@+id/focused
android:drawable
=
@drawable/drawableF
android:state_focused
=
true
/>
<
item
android:id
=
@id/default
android:drawable
=
@drawable/drawableD
/>
<
transition
android:fromId
=
@+id/default
android:toId
=
@+id/pressed
>
<
animation-list
>
<
item
android:duration
=
15
android:drawable
=
@drawable/dt1
/>
<
item
android:duration
=
15
android:drawable
=
@drawable/dt2
/>
...
animation-list
>
transition
>
...
animated-selector
>
可繪制矢量圖在拉伸時不會失真。AnimatedVectorDrawable
類讓你可以在可繪制矢量圖上面作用動畫。
通常需要在三個xml文件中定義可動的矢量圖:
一個矢量圖使用
元素,放在res/drawable/
下。
一個可動的矢量圖使用元素,放在
res/drawable/
下。
一個或更多個動畫對象使用元素,放在
res/anim/
下。
可動矢量圖可以使用
和
元素。
元素定義一系列路徑或者子組,
元素定義可繪圖的路徑。
當你定義了一個想要作用動畫的矢量可繪制圖,使用android:name
屬性給每個group和path指定一個唯一的名字,這樣你可以從動畫的定義中找到他們。比如:
<
vector
xmlns:android
=
http://schemas.android.com/apk/res/android
android:height
=
64dp
android:width
=
64dp
android:viewportHeight
=
600
android:viewportWidth
=
600
>
<
group
android:name
=
rotationGroup
android:pivotX
=
300.0
android:pivotY
=
300.0
android:rotation
=
45.0
>
<
path
android:name
=
v
android:fillColor
=
#000000
android:pathData
=
M300,70 l 0,-70 70,70 0,0 -70,70z
/>
group
>
vector
>
可動的矢量繪制通過剛剛說到定義的名字,來找到這些path和group:
? 1 2 3 4 5 6 7 8 9 10
<
animated-vector
xmlns:android
=
http://schemas.android.com/apk/res/android
android:drawable
=
@drawable/vectordrawable
>
<
target
android:name
=
rotationGroup
android:animation
=
@anim/rotation
/>
<
target
android:name
=
v
android:animation
=
@anim/path_morph
/>
animated-vector
>
動畫的定義表現在ObjectAnimator和AnimatorSet對象中。第一個動畫在這個例子中是讓目標組旋轉360度:
? 1 2 3 4 5 6
<
objectAnimator
android:duration
=
6000
android:propertyName
=
rotation
android:valueFrom
=
0
android:valueTo
=
360
/>
第二個動畫例子是把矢量可繪圖從一個形狀變成另一種。所有的路徑必須兼容變換:他們必須有相同數量的命令,每個命令要有相同的參數。
? 1 2 3 4 5 6 7 8 9
<
set
xmlns:android
=
http://schemas.android.com/apk/res/android
>
<
objectAnimator
android:duration
=
3000
android:propertyName
=
pathData
android:valueFrom
=
M300,70 l 0,-70 70,70 0,0 -70,70z
android:valueTo
=
M300,70 l 0,-70 70,0 0,140 -70,0 z
android:valueType
=
pathType
/>
set
>
更多的信息,看AnimatedVectorDrawable
的api指南。
這個系列終於寫完了,說實話基本上大部分都是翻譯的谷歌的官方文檔。因為時間問題,再加上自己的英語夠爛,最近越來慢。不過,這樣一下來,加上自己的一些代碼練習,對於Material設計算是能夠基本使用了。可惜,大部分的style還都不能向下兼容,只好等5了。
網上有一些大神進來已經開源了一些開源組件,大家可以借此曲線救國,下次有空在專門整理一下。
由於gif圖太大的原因,我將圖放在了github,如果博客中顯示不出來圖,傳送門 由於我是事先寫在md上的,導致代碼的可讀性差,大家將就著看吧。 1. 前言 在
前言 SQLite是一種輕量級的小型數據庫,雖然比較小,但是功能相對比較完善,一些常見的數據庫基本功能也具有,在現在的嵌入式系統中使用該數據庫的比較多,因為它占用系統
Device Administration對於這個應用,市場上很多,但是看一下評論就知道效果有多差了,因為99%一鍵鎖屏應用沒辦法卸載。今天就開發一個小應用,實現輕松點擊
1 背景去年有很多人私信告訴我讓說說自定義控件,其實通觀網絡上的很多博客都在講各種自定義控件,但是大多數都是授之以魚,卻很少有較為系統性授之於漁的文章,同時由