之前有写过一个 简陋的 元素共享, https://blog.csdn.net/FlyPig_Vip/article/details/80961751
现在系统的学习一下关于 这类型的交互
有必要说一下这些 功能Api 都是在Api19 以后才可以使用的
这个有点类似 ConstraintLayout 的 变化前,变化后,MotionLayout 期间加上动画 跟这也差不多
Scene 这个
这是一个场景结合动画 的 中间者
它的实例 有俩种
简单使用
首先写俩个布局
Scene_start1
<?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:orientation="vertical">
<ImageView
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
然后是
Scene_end1
<?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:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic2" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:src="@drawable/ic1" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic4" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic3" />
</RelativeLayout>
主布局:Main1Activity.layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.Main1Activity">
<RelativeLayout
android:id="@+id/rela1"
android:layout_width="match_parent"
android:layout_height="300dp">
</RelativeLayout>
<Button
android:id="@+id/butToggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="切换场景动画" />
</LinearLayout>
MainAc代码
public class Main1Activity extends AppCompatActivity implements View.OnClickListener {
private RelativeLayout rela1;
private Button butToggle;
private boolean isStartState = true;
private Scene sceneStart;
private Scene sceneEnd;
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
initView();
initEvent();
TransitionManager.go(sceneStart);
}
/**
* 设置初始状态
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void initEvent() {
sceneStart = Scene.getSceneForLayout(rela1, R.layout.scene_start1, Main1Activity.this);
sceneEnd = Scene.getSceneForLayout(rela1, R.layout.scene_end1, Main1Activity.this);
}
private void initView() {
rela1 = (RelativeLayout) findViewById(R.id.rela1);
butToggle = (Button) findViewById(R.id.butToggle);
butToggle.setOnClickListener(this);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.butToggle:
isStartState = !isStartState;
TransitionManager.go(isStartState ? sceneStart : sceneEnd);
break;
default:
break;
}
}
}
瞬间感觉...原来Android 5.0 的时候就已经出了这些个
这个效果是简单的显隐效果 ,看到这里
TransitionManager.go(isStartState ? sceneStart : sceneEnd);
这个方法有点面熟,像是ConstranitLayout 那个
https://blog.csdn.net/FlyPig_Vip/article/details/99436229
这下加个动画进去
Transition transition1 = new AutoTransition();
Transition transition2 = new ChangeBounds();
Transition transition3 = new Fade();
Transition transition4 = new ChangeClipBounds();
Transition transition5 = new ChangeImageTransform();
Transition transition6 = new ChangeScroll();
Transition transition7 = new ChangeTransform();
Transition transition8 = new Explode();
Transition transition9 = new Slide();
Transition transition10 = new TransitionSet();
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition1);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition2);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition3);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition4);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition5);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition6);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition7);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition8);
// TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition9);
发现我的动画没有人家的 那么精准,于是仔细看了一下,发现我没有给布局字View 加 id,同理 一个图片对应一个id,一定要同步
类似Constraint 的 变化前后的id
效果图:
new Fade()
可以适当的加点View 自带的动画
<?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:orientation="vertical">
<ImageView
android:alpha="0.8"
android:id="@+id/iv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic4" />
<ImageView
android:id="@+id/iv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:src="@drawable/ic3" />
<ImageView
android:scaleX="0.5"
android:scaleY="0.5"
android:id="@+id/iv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic2" />
<ImageView
android:rotation="60"
android:id="@+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="@drawable/ic1" />
</RelativeLayout>
new ChangeBounds()
new ChangeClipBounds()
View startView = View.inflate(Main1Activity.this, R.layout.scene_start1, null);
View endView = View.inflate(Main1Activity.this, R.layout.scene_end1, null);
// 这里的宽高需要事先设置好
// 可以使用Diputil 转化
// startView.getWidth();
// startView.getHeight();
// 设置裁剪
startView.setClipBounds(new Rect(0, 0, 200, 200));
endView.setClipBounds(new Rect(600, 600, 900, 900));
sceneStart = new Scene(rela1, startView);
sceneEnd = new Scene(rela1, endView);
只是加了个背景色
new ChangeImageTransform()
总的来说 这个的差距并不大 这个一看就是针对图片的 先把 starView 的 布局 和endView 的 布局 改为一张大图
先是一个AutoTrans 然后是 ChangImageTrans
new Explode()
new Slide()
结合使用
我们具体调用这个场景切换动画的时候
TransitionManager.go(isStartState ? sceneStart : sceneEnd, transition9);
传入的是Transition ,具体看一下他的实例方法
1.
Transition transition1 = new AutoTransition();
2.
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.combine_transition);
那么我们自己写一个
TransitionManager.beginDelayedTransition
之前使用的
TransitionManager.go
go需要俩个布局 提前准备好 进行交替 ,beginDelayedTransition 可以直接对布局内View 进行改变
TransitionManager.beginDelayedTransition(rela1, new AutoTransition());
if (isStartState) {
iv.setScaleX(0.5f);
iv.setScaleY(0.5f);
} else {
iv.setScaleX(1.5f);
iv.setScaleY(1.5f);
}
之前也记了 Activity的 跳转动画 现在换一下
https://blog.csdn.net/FlyPig_Vip/article/details/80590316
首先是一个 左进左出的 跳转动画
fade_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000">
<alpha
android:fromAlpha="0.6"
android:toAlpha="1" />
</set>
fade_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000">
<alpha
android:fromAlpha="1"
android:toAlpha="0.6" />
</set>
left_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromXDelta="-100%p"
android:toXDelta="0" />
</set>
left_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
startActivity(new Intent(Main2Activity.this, Main3Activity.class));
overridePendingTransition(R.anim.left_in, R.anim.fade_out);
@Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(R.anim.fade_in, R.anim.left_out);
}
接下来看一下别的方法
ActivityOptions compat = ActivityOptions.makeCustomAnimation(Main2Activity.this, R.anim.left_in, R.anim.fade_out);
startActivity(new Intent(Main2Activity.this, Main3Activity.class), compat.toBundle());
效果是一样的
以布局内某一view 的某一点开始 做放大跳转
ActivityOptions compat = ActivityOptions.makeScaleUpAnimation(iv, iv.getWidth() / 2, iv.getHeight() / 2, 0, 0);
startActivity(new Intent(Main2Activity.this, Main3Activity.class), compat.toBundle());
这个看着像是没有作用的 ,也写上吧
ActivityOptions compat = ActivityOptions.makeThumbnailScaleUpAnimation(iv, BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher_round),
iv.getWidth() / 2, iv.getHeight() / 2);
startActivity(new Intent(Main2Activity.this, Main3Activity.class), compat.toBundle());
最后一个是看着可以的 交互了
ActivityOptions compat = ActivityOptions.makeSceneTransitionAnimation(Main2Activity.this);
startActivity(new Intent(Main2Activity.this, Main3Activity.class), compat.toBundle());
Main3
public class Main3Activity extends AppCompatActivity {
private View mViewBackgroundTop;
private View mViewBackgroundBottom;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initTransition();
setContentView(R.layout.activity_main3);
mViewBackgroundTop = findViewById(R.id.lltop);
mViewBackgroundBottom = findViewById(R.id.llbot);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void initTransition() {
// //资源文件指定过渡动画
// getWindow().setEnterTransition(TransitionInflater.from(this).inflateTransition(R.transition.transition_target));
//代码制定过渡动画
final TransitionSet transitionSet = new TransitionSet();
Slide slide = new Slide(Gravity.BOTTOM);
slide.addTarget(R.id.shareImage);
transitionSet.addTransition(slide);
Explode explode = new Explode();
explode.excludeTarget(android.R.id.statusBarBackground, true);
explode.excludeTarget(android.R.id.navigationBarBackground, true);
explode.excludeTarget(R.id.shareImage, true);
transitionSet.addTransition(explode);
// TransitionSet.ORDERING_SEQUENTIAL
transitionSet.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
getWindow().setEnterTransition(transitionSet);
transitionSet.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
mViewBackgroundTop.setVisibility(View.GONE);
mViewBackgroundBottom.setVisibility(View.GONE);
}
@Override
public void onTransitionEnd(Transition transition) {
mViewBackgroundTop.setVisibility(View.VISIBLE);
mViewBackgroundBottom.setVisibility(View.VISIBLE);
Animator animationTop = ViewAnimationUtils.createCircularReveal(mViewBackgroundTop, mViewBackgroundTop.getWidth() / 2,
mViewBackgroundTop.getHeight() / 2, 0,
Math.max(mViewBackgroundTop.getWidth() / 2,
mViewBackgroundTop.getHeight() / 2));
Animator animationBottom = ViewAnimationUtils.createCircularReveal(mViewBackgroundBottom, mViewBackgroundBottom.getWidth(),
mViewBackgroundBottom.getHeight(), 0,
(float) Math.hypot(mViewBackgroundBottom.getWidth(),
mViewBackgroundBottom.getHeight()));
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500L);
animatorSet.playTogether(animationTop, animationBottom);
animatorSet.start();
transitionSet.removeListener(this);
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".ui.Main3Activity">
<LinearLayout
android:layout_alignParentTop="true"
android:background="#f0f"
android:id="@+id/lltop"
android:gravity="center_horizontal"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic1" />
<ImageView
android:id="@+id/iv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:src="@drawable/ic2" />
</LinearLayout>
<ImageView
android:layout_centerInParent="true"
android:transitionName="shared_image"
android:id="@+id/shareImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic3" />
<LinearLayout
android:layout_alignParentBottom="true"
android:id="@+id/llbot"
android:background="@drawable/a"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:id="@+id/iv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:src="@drawable/ic4" />
</LinearLayout>
</RelativeLayout>
有点突然的就是那个揭露动画了
了解一下
https://blog.csdn.net/FlyPig_Vip/article/details/87798104
元素共享 差不多是 最重要的一环了
Intent intent = new Intent(Main4Activity.this, Main5Activity.class);
ActivityOptions compat = ActivityOptions.makeSceneTransitionAnimation(Main4Activity.this, shared_image,
shared_image.getTransitionName());
startActivity(intent, compat.toBundle());
监听返回
setExitSharedElementCallback(new SharedElementCallback() {
@Override
public void onSharedElementStart(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
super.onSharedElementStart(sharedElementNames, sharedElements, sharedElementSnapshots);
}
@Override
public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
super.onSharedElementEnd(sharedElementNames, sharedElements, sharedElementSnapshots);
for (int i = 0; i < sharedElementNames.size(); i++) {
System.out.println("sharedElementNames : " + sharedElementNames.get(i));
}
}
@Override
public void onRejectSharedElements(List<View> rejectedSharedElements) {
super.onRejectSharedElements(rejectedSharedElements);
}
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
super.onMapSharedElements(names, sharedElements);
}
@Override
public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, RectF screenBounds) {
return super.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix, screenBounds);
}
@Override
public View onCreateSnapshotView(Context context, Parcelable snapshot) {
return super.onCreateSnapshotView(context, snapshot);
}
@Override
public void onSharedElementsArrived(List<String> sharedElementNames, List<View> sharedElements, OnSharedElementsReadyListener listener) {
super.onSharedElementsArrived(sharedElementNames, sharedElements, listener);
}
});
动画进入的监听
private void initShareTransition() {
//直接在style里面设置了共享元素的Transition
// getWindow().setSharedElementEnterTransition(new ChangeBounds());
// getWindow().setSharedElementExitTransition(new ChangeBounds());
// getWindow().setSharedElementReenterTransition(new ChangeBounds());
// getWindow().setSharedElementReturnTransition(new ChangeBounds());
getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
mTextInfo.setVisibility(View.GONE);
mViewBackground.setVisibility(View.GONE);
}
@Override
public void onTransitionEnd(Transition transition) {
mTextInfo.setVisibility(View.VISIBLE);
mViewBackground.setVisibility(View.VISIBLE);
Animator animationBottom = ViewAnimationUtils.createCircularReveal(mTextInfo, mTextInfo.getWidth() / 2,
mTextInfo.getHeight() / 2, 0,
(float) Math.max(mTextInfo.getWidth() / 2,
mTextInfo.getHeight() / 2));
animationBottom.setDuration(500L);
animationBottom.start();
mViewBackground.animate().alpha(1).setDuration(500L).start();
getWindow().getSharedElementEnterTransition().removeListener(this);
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
如果是fragment->fragment
https://www.jianshu.com/p/05e3b99ce5ce
https://www.jianshu.com/p/e87c0086a3ae