美文网首页
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-转场动画基础

    原本想直接写自定义VIew的,然后看到前面还有转场动画,就顺手学了。 先说下animator来实现的转场动画,xm...

  • 动画

    CABasicAnimation基础核心动画 缩放动画 图片抖动 根据圆形的路径做移动的效果. 转场动画 创建转场...

  • CAAnimation常用属性一览表

    动画基础知识 动画的属性和解释 常用KeyPath总结 场景间过渡属性 转场动画

  • iOS-核心动画

    前言:核心动画的基础知识,包括基本动画、帧动画、转场动画相关知识。 一、核心动画(Core Animation) ...

  • iOS-Core Animation动画详解

    目录 一 Core Animation 二 核心动画2.1 基础动画2.2 关键帧动画2.3 动画组2.4 转场动...

  • iOS-自定义控制器转场动画(present/dismiss)

    一、转场动画类型 iOS控制器转场动画类型可以分为非交互式转场动画和交互式转场动画。 二、转场动画分析 2.1、转...

  • 聊聊Android的转场动画

    Android的转场动画包括:场景动画,页面的转场动画,页面元素间共享动画。 Android转场动画[https:...

  • iOS Core Animation (一) 基础动画

    iOS核心动画Core Animation分为几类:基础动画、关键帧动画、动画组、转场动画。关系大致如下图: CA...

  • iOS - 转场动画

    参考文章:iOS 转场动画一张图看懂 iOS 转场动画iOS自定义转场动画 iOS 转场动画探究(一)

  • iOS开发——登录页面动画、转场动画

    iOS开发——登录页面动画、转场动画 iOS开发——登录页面动画、转场动画

网友评论

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

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