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);