android:background="?android:attr/selectableItemBackground"
android:background="?android:attr/selectableItemBackgroundBorderless"
private void doCircle(View myView)
{
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim.setDuration(3000);
myView.setVisibility(View.VISIBLE);
anim.start();
}
private void hideCircle(final View myView)
{
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int finalRadius = myView.getWidth();
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, finalRadius, 0);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation)
{
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
anim.setDuration(3000);
anim.start();
}
android:windowContentTransitions
屬性啓用窗口內容轉換Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(FirstActivity.this).toBundle());
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//TODO 淡入淡出
getWindow().setEnterTransition(new Fade().setDuration(2000));
getWindow().setExitTransition(new Fade().setDuration(2000));
setContentView(R.layout.activity_second);
linearLayout = (LinearLayout) this.findViewById(R.id.secondLayout);
}
slide:從場景的邊緣移入或移出
getWindow().setAllowEnterTransitionOverlap(true);
staticActivityOptions |
makeClipRevealAnimation(View source,
int startX, int startY, int width, int height)
Create an ActivityOptions specifying an animation where the new activity is revealed from a small originating area of the screen to its final full representation.
|
tiaozhuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeClipRevealAnimation(v,0,0,v.getRight(),v.getBottom()).toBundle());
}
});
staticActivityOptions |
makeCustomAnimation(Context context,
int enterResId, int exitResId)
Create an ActivityOptions specifying a custom animation to run when the activity is displayed.
|
tiaozhuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeCustomAnimation(FirstActivity.this,R.anim.bottom_to_center,R.anim.center_to_left).toBundle());
}
});
staticActivityOptions |
makeScaleUpAnimation(View source,
int startX, int startY, int width, int height)
Create an ActivityOptions specifying an animation where the new activity is scaled from a small originating area of the screen to its final full representation. |
makeClipRevealAnimation
在參數上沒有變化,效果上也很相似tiaozhuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeScaleUpAnimation(v,v.getLeft(),v.getTop(),v.getRight(),v.getBottom()).toBundle());
}
});
staticActivityOptions |
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail,
int startX, int startY)
Create an ActivityOptions specifying an animation where a thumbnail is scaled from a given position to the new activity window that is being started.
|
tiaozhuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
v.setDrawingCacheEnabled(true);
bitmap=v.getDrawingCache();
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeThumbnailScaleUpAnimation(v,bitmap,10,10).toBundle());
}
});
slide:從場景的邊緣移入或移出
fade:淡入淡出的效果
Transition
對象調用這些方法:Window.setEnterTransition()//開始進入時動畫
Window.setExitTransition()//結束退出時動畫
Window.setSharedElementEnterTransition()//共享元素開始進入時動畫
Window.setSharedElementExitTransition()//共享元素結束時動畫
staticActivityOptions |
makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)
Create an ActivityOptions to transition between Activities using cross-Activity scene animations. |
staticActivityOptions |
makeSceneTransitionAnimation(Activity activity, Pair...<View, String>
sharedElements)
Create an ActivityOptions to transition between Activities using cross-Activity scene animations. |
Public methods |
|
---|---|
void |
add(Drawable drawable)
Adds a |
void |
clear()
Removes all content from the overlay. |
void |
remove(Drawable drawable)
Removes the specified |
tiaozhuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(FirstActivity.this, v, "button").toBundle());
}
});
Activity.finishAfterTransition()
這個方法。 img.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(View v)
{
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
Pair<View, String> pairOne = new Pair<View, String>(img, "img");
Pair<View, String> pairTwo = new Pair<View, String>(button1, "button1");
Pair<View, String> pairThreee = new Pair<View, String>(button2, "button2");
Pair<View, String> pairFour = new Pair<View, String>(button3, "button3");
Pair<View, String> pairFive = new Pair<View, String>(button4, "button4");
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(FirstActivity.this, pairOne, pairTwo, pairThreee, pairFour, pairFive);
startActivity(intent, activityOptions.toBundle());
}
getWindow().setEnterTransition(new Explode().setDuration(2000).setInterpolator(new BounceInterpolator()));
getWindow().setExitTransition(new Explode().setDuration(2000));
ViewCompat.setTransitionName(img,"img");
ViewCompat.setTransitionName(button1,"button1");
……
//TODO 共享元素實現方式
private void ShareElements_Two(Intent intent)
{
TransitionSet transitionSet=new TransitionSet();
transitionSet.addTransition(new ChangeImageTransform());
getWindow().setSharedElementEnterTransition(transitionSet);
getWindow().setSharedElementExitTransition(transitionSet);
Pair<View,String> pairOne=new Pair<View, String>(meinv,"meinv");
Pair<View,String> pairTwo=new Pair<View, String>(tiaozhuan,"button");
ActivityOptions activityOptions=ActivityOptions.makeSceneTransitionAnimation(FirstActivity.this,pairOne,pairTwo);
startActivity(intent,activityOptions.toBundle());
}
ChangeBounds | This transition captures the layout bounds of target views before and after the scene change and animates those changes during the transition. |
ChangeClipBounds |
ChangeClipBounds captures the getClipBounds() before
and after the scene change and animates those changes during the transition. |
ChangeImageTransform | This Transition captures an ImageView's matrix before and after the scene change and animates it during the transition. |
ChangeScroll | This transition captures the scroll properties of targets before and after the scene change and animates any changes. |
ChangeTransform | This Transition captures scale and rotation for Views before and after the scene change and animates those changes during the transition. |
CircularPropagation | A propagation that varies with the distance to the epicenter of the Transition or center of the scene if no epicenter exists. |
void |
captureEndValues(TransitionValues transitionValues)
Captures the values in the end scene for the properties that this transition monitors. |
void |
captureStartValues(TransitionValues transitionValues)
Captures the values in the start scene for the properties that this transition monitors. |
Animator |
createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues)
This method creates an animation that will be run for this transition given the information in the startValues and endValues structures captured earlier for the start and end scenes.
|
通過設置TransitionValues來定義我們的初始場景值,包括view,和剪裁區域Rect,他是通過map集合去設置值的,另外captureEndValues()設置動畫值之前必須調用setClipBounds()方法,否則會報空指針
//TODO 這兩個方法都調用了captureValues()方法,不同的是一個傳的是初始值,一個是結束值
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
//具體這個方法是做什麼的呢?因爲transitionValues封裝了我們要操作的view,所以我們要將他剪裁的區域也封裝起來,看標紅部分,所以在
這個方法之前我們必須剪裁視圖的可視區域,即setClipBounds(),否則將不起作用
private void captureValues(TransitionValues values) {
View view = values.view;
if (view.getVisibility() == View.GONE) {
return;
}
Rect clip = view.getClipBounds();
values.values.put(PROPNAME_CLIP, clip);
if (clip == null) {
Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
values.values.put(PROPNAME_BOUNDS, bounds);
}
}
public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
//可以看出在這之前一定要先設置captureStartValues和captureEndValues方法,否則就會返回null
if (startValues == null || endValues == null
|| !startValues.values.containsKey(PROPNAME_CLIP)
|| !endValues.values.containsKey(PROPNAME_CLIP)) {
return null;
}
//獲取開始和剪裁區域
Rect start = (Rect) startValues.values.get(PROPNAME_CLIP);
Rect end = (Rect) endValues.values.get(PROPNAME_CLIP);
if (start == null && end == null) {
return null; // No animation required since there is no clip.
}
if (start == null) {
start = (Rect) startValues.values.get(PROPNAME_BOUNDS);
} else if (end == null) {
end = (Rect) endValues.values.get(PROPNAME_BOUNDS);
}
if (start.equals(end)) {
return null;
}
//這句話很關鍵,因爲我們這個方法最主要操作的對象是endValues中封裝的view,也就是下面我們屬性動畫真正要作用的對象
endValues.view.setClipBounds(start);
//我們屬性動畫是按照矩形拓展的方式演變
RectEvaluator evaluator = new RectEvaluator(new Rect());
return ObjectAnimator.ofObject(endValues.view, "clipBounds", evaluator, start, end);
}
private void ShareElements_Two(Intent intent)
{
ChangeClipBounds changeClipBounds=new ChangeClipBounds();
TransitionValues values_start = new TransitionValues();
TransitionValues values_end = new TransitionValues();
values_start.view=tiaozhuan;
values_end.view=meinv;
//TODO setClipBounds(Rect rect),直接指定當前view的可視區域,當前的Rect使用的view的自身的座標系。
//TODO startView原始大小200*200,endView原始大小600*600
values_start.view.setClipBounds(new Rect(0, 0, 0, 0));
//TODO 通過分析源碼我們知道這個方法雖然可省,但是之建立在要擴展的視圖顯示區域是本身大小的基礎上
values_end.view.setClipBounds(new Rect(0, 0, 600, 600));
changeClipBounds.captureStartValues(values_start);
changeClipBounds.captureEndValues(values_end);
changeClipBounds.createAnimator(layout, values_start, values_end).setDuration(3000).start();
TransitionSet set=new TransitionSet();
set.addTransition(changeClipBounds);
set.addTransition(new Slide());
set.addTransition(new Fade());
set.setDuration(3000);
//TODO 順序播放時1,同時播放是0
set.setOrdering(0);
// //TODO 普通轉場動畫進入效果
// getWindow().setEnterTransition(set);
// //TODO 普通轉場動畫退出效果
// getWindow().setExitTransition(set);
//TODO 共享元素進入效果
// getWindow().setSharedElementEnterTransition(set);
//TODO 共享元素退出效果
// getWindow().setSharedElementExitTransition(set);
//TODO 我們的動畫是建立在硬件加速的基礎上的,如果關閉你會看到慘不忍睹的畫面
Pair<View,String> pairOne=new Pair<View, String>(meinv,"meinv");
Pair<View,String> pairTwo=new Pair<View, String>(tiaozhuan,"button");
ActivityOptions activityOptions=ActivityOptions.makeSceneTransitionAnimation(FirstActivity.this,pairOne,pairTwo);
startActivity(intent,activityOptions.toBundle());
}
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
//TODO 使用曲線運動
private void doCurdAnimation(View view)
{
ObjectAnimator objectAnimator;
PathInterpolator pathInterpolator=new PathInterpolator(0.5f,0.9f);
Path path=new Path();
path.arcTo(1f,1f,400f,800f,0,120,false);
objectAnimator=ObjectAnimator.ofFloat(view,View.X,View.Y,path);
objectAnimator.setInterpolator(pathInterpolator);
objectAnimator.setDuration(3000);
objectAnimator.start();
}
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<set>
<objectAnimator android:duration="500" android:propertyName="scaleX" android:valueTo="1.5" android:valueType="floatType" />
</set>
</item>
<item android:state_pressed="false">
<set>
<objectAnimator android:duration="500" android:propertyName="scaleX" android:valueTo="1" android:valueType="floatType" />
</set>
</item>
</selector>
<Button
android:id="@+id/state_animte"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳轉"
android:stateListAnimator="@drawable/click_selector"
/>
StateListAnimator stateListAnimator= AnimatorInflater.loadStateListAnimator(this,R.drawable.click_selector);
state_animte.setStateListAnimator(stateListAnimator);