原本想直接写自定义VIew的,然后看到前面还有转场动画,就顺手学了。
先说下animator来实现的转场动画,xml布局如下:
<?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"
tools:context=".RevealActivity">
<CheckBox
android:text="Play animation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/checkBox" />
<View
android:id="@+id/view"
android:layout_centerInParent="true"
android:background="@color/colorAccent"
android:onClick="onClick"
android:visibility="invisible"
android:layout_width="300dp"
android:layout_height="300dp"/>
<Button
android:onClick="onClick"
android:id="@+id/buttonChangeVisibility"
android:layout_width="wrap_content"
android:text="switch"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
style="?android:buttonBarButtonStyle"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</RelativeLayout>
然后逻辑代码如下,里面每一步的都有解释的,仔细看:
class RevealActivity : AppCompatActivity() {
private lateinit var mView: View
private lateinit var mPlayAnimationCheckBox: CheckBox
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_reveal)
initView()
}
private fun initView() {
mPlayAnimationCheckBox = findViewById(R.id.checkBox)
mView = findViewById(R.id.view)
}
fun onClick(view: View) {
when (view.id) {
R.id.buttonChangeVisibility -> {
//获取checkbox的勾选状态
val state = mPlayAnimationCheckBox.isChecked
//返回true的话就使用转场效果,false就使用正常的控制显示与隐藏
if (state) {
if (mView.isShown) revealExite(mView) else revealEnter(mView)
}else{
if (mView.isShown) mView.visibility=View.INVISIBLE else mView.visibility=View.VISIBLE
}
}
}
}
private fun revealExite(view: View) {
val w = mView.width
val h = mView.height
//这个圆的半径哈
val r = hypot(w.toDouble(), h.toDouble()).toInt()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val animator = ViewAnimationUtils.createCircularReveal(mView, w, h, r.toFloat(), 0f)
animator.duration = 5000
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
mView.visibility = View.INVISIBLE
}
})
animator.start()
} else {
val revealAnimator = ObjectAnimator.ofFloat (view, "scaleX", w.toFloat(), 0f)
val revealAnimator1 = ObjectAnimator. ofFloat (view, "scaleY", h.toFloat(), 0f)
val set = AnimatorSet()
set.duration = 5000//设置播放时间
set.interpolator = LinearInterpolator()//设置播放模式,这里是平常模式
set.playTogether(revealAnimator, revealAnimator1)//设置一起播放
set.start()
}
}
private fun revealEnter(view: View) {
val width = view.width
val height = view.height
val r = hypot(width.toDouble(), height.toDouble()).toFloat()
//如果要在你的程序中使用它,必须要设置最低的 api 版本是 21,往下版本的,在运行程序的时候就会抛出 .createCircularReveal() not found
//异常,所以这里需要作出版本的判断
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val animator=ViewAnimationUtils.createCircularReveal(view, width, height, 0f, r)
//设置在多少时间内完成动画效果
animator.duration = 5000
//这一步十分关键,否则前面都设置都没有用了
animator.start()
} else {
//解决21版本以下没法运行效果
val revealAnimator = ObjectAnimator.ofFloat (view, "scaleX", 0f, width.toFloat())
val revealAnimator1 = ObjectAnimator. ofFloat (view, "scaleY", 0f, height.toFloat())
val set = AnimatorSet()
set.duration = 5000//设置播放时间
set.interpolator = LinearInterpolator()//设置播放模式,这里是平常模式
set.playTogether(revealAnimator, revealAnimator1)//设置一起播放
set.start()
}
mView.visibility = View.VISIBLE
}
}
嗯,就这样可以实现animator的场景转换效果了
第二种,通过transition实现的情景转换:
这个需要三个布局,第一个是activity中,另外两个是需要作用于FrameLayout中的:
activity中的
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_scene"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SceneActivity">
<FrameLayout
android:id="@+id/scene_root"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
另外两个布局切换的
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_scene"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:id="@+id/image"
android:layout_width="160dp"
android:layout_height="120dp"
android:src="@drawable/chang_bai" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<ImageButton
android:id="@+id/btnClose"
android:transitionName="@string/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="4dp"
android:background="?android:selectableItemBackground"
android:src="@drawable/ic_close_black_24dp" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/btnClose"
android:text="@string/title"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:id="@+id/tvAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvTitle"
android:layout_marginTop="8dp"
android:text="@string/address"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/tvInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tvAddress"
android:layout_marginTop="8dp"
android:text="@string/info" />
</RelativeLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_scene"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:id="@+id/image"
android:layout_height="0dp"
android:layout_weight="1"
android:src="@drawable/chang_bai"
android:transitionName="@string/pic"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<ImageButton
android:id="@+id/btnInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="4dp"
android:background="?android:selectableItemBackground"
android:src="@drawable/ic_info_black_24dp" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/btnInfo"
android:text="@string/title"
android:textAppearance="@style/TextAppearance.AppCompat.Headline" />
<TextView
android:id="@+id/tvAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvTitle"
android:layout_marginTop="8dp"
android:text="@string/address"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
</RelativeLayout>
</LinearLayout>
然后逻辑实现的代码如下:在这里提示下,如果出现某个按钮无法点击的情况下,请查看使用的上下文的是不是baseContext,个人不太建议滥用这个,因为你点击看的时候,就会发现他们俩返回的不是同一个对象,点击this的时候会跳到你的activity中,而点击baseContext会发现追到ContextWrapper类里面,这可能会导致你无法找到对应布局中控件!!!这血一样的教训啊!!
class SceneActivity : AppCompatActivity() {
private var mOverViewScene: Scene? = null
private var mInfoScene: Scene? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scene)
val sceneRoot = findViewById<ViewGroup>(R.id.scene_root)
mOverViewScene =
Scene.getSceneForLayout(sceneRoot, R.layout.scene_overview, baseContext)
mInfoScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_info, baseContext)
TransitionManager.go(mOverViewScene)
onCLickListener()
}
private fun onCLickListener() {
btnInfo.setOnClickListener {
val transition =
TransitionInflater.from(baseContext)
.inflateTransition(R.transition.transition)
TransitionManager.go(mInfoScene, transition)
}
btnClose?.setOnClickListener {
TransitionManager.go(mOverViewScene)
}
}
}
嗯,这就实现了的说!!!
第三种,就是实现activity之间的情景转换
xml如下:
<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=".FirstActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv1"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:onClick="onClick"
android:src="@drawable/pic1" />
<ImageView
android:id="@+id/iv2"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:onClick="onClick"
android:src="@drawable/pic2" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv3"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:onClick="onClick"
android:src="@drawable/pic3" />
<ImageView
android:id="@+id/iv4"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:onClick="onClick"
android:src="@drawable/pic4" />
</LinearLayout>
</LinearLayout>
第二个activity如下:
<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"
tools:context=".SecondActivity">
<ImageView
android:id="@+id/iv"
android:transitionName="img"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
实现逻辑如下:
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_first)
}
fun onClick(view: View) {
var resId = when (view.id) {
R.id.iv1 -> R.drawable.pic1
R.id.iv2 -> R.drawable.pic2
R.id.iv3 -> R.drawable.pic3
R.id.iv4 -> R.drawable.pic4
else -> null
}
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("resId", resId)
//设置情景转换效果
val transition: Transition = Explode()
//剔除状态栏跟随转换效果
transition.excludeTarget(android.R.id.statusBarBackground, true)
//设置进场的转换效果
window.enterTransition = transition
//设置离场的转换效果
window.exitTransition = transition
//设置再次进入此页面时的转场动画
window.reenterTransition = transition
//设置转场元素为共享元素
window.sharedElementEnterTransition = transition
//设置共享元素,需要在另一个activity中的 iv.transitionName = "img"设定transitionName为img,这样另一个activity也会实现转场效果
val shareElement =
Pair.create(view, "img")
val options =
ActivityOptions.makeSceneTransitionAnimation(this, shareElement)
startActivity(intent, options.toBundle())
}
}
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val resId = intent.extras!!.getInt("resId")
val iv =
findViewById<View>(R.id.iv) as ImageView
iv.transitionName = "img"
iv.setImageResource(resId)
val transition: Transition = Explode()
transition.excludeTarget(android.R.id.statusBarBackground, true)
window.enterTransition = transition
window.exitTransition = transition
}
}
这里面的注释都写得很清楚,他们的实现功能是啥,所以请各位看官慢看,不过反正你们看了也不会点赞什么的,那算了,哼
网友评论