美文网首页
kotlin-转场动画基础

kotlin-转场动画基础

作者: jeffrey12138 | 来源:发表于2020-11-05 18:17 被阅读0次

    原本想直接写自定义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
        }
    }
    

    这里面的注释都写得很清楚,他们的实现功能是啥,所以请各位看官慢看,不过反正你们看了也不会点赞什么的,那算了,哼

    相关文章

      网友评论

          本文标题:kotlin-转场动画基础

          本文链接:https://www.haomeiwen.com/subject/owdavktx.html