仿IOS界面跳转翻转效果(Kotlin实现)

本文介绍了一种在Android应用中实现类似iOS的3D翻转界面过渡效果的方法,通过自定义动画而非系统提供的过渡效果,独立于两个Activity实现流畅的翻转动画。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在开头

项目中UI设计了一个仿IOS界面跳转3D翻转的效果,尼玛人家系统自带的啊。无奈只好找轮子了,看了看网上全是一个acitivity两个VIew或者两个Fragment的跳转,作为技术人的执着不想那么实现,本来没有关系的两个界面硬生生写在一个activity下不是我想要的。
下载链接在文末!!!

先看下效果吧,看是不是你想要的,背景大白,您可以设置你想要的默认背景。
这里写图片描述

实现思路思考

1.本来打算用系统提供的overridePendingTransition方法实现跳转,可无奈试了N种方法后我放弃了,如果您有好的方式可以沟通一下。
2.采用网上一个Activity两个VIew或者Fragment实现,我主动放弃了,如果符合你的要求可以自行Google。当时也考虑到了5.0以后加入的转场动画,最终也不能实现。
3.那为什么我不能单独给两个Activity的根View设置3D翻转动画,一个从-90度到0度,另一个从-270到-360度。那么,我们怎么实现View的3D翻转呢?Rotate3dAnimation,他能很轻松的帮助我们3D翻转的效果。

先撸一撸大体功能怎么实现

Activity1:
首先,在第一个Activity中我们先实现根View的翻转工作,在翻转结束后再实现界面的Intent跳转,我用Handler来实现这部分操作。看一下代码:我们首先得到屏幕的宽和高,然后确定中心翻转位置。

  val screenBounds = ScreenUtils.getScreenBounds(this)
        mWidth = screenBounds[0]
        mHeight = screenBounds[1]
        main_layout.setOnClickListener(View.OnClickListener {
            ll = findViewById<View>(R.id.main_layout)
            val animationSet = AnimationSet(true)
            val depthZ = 450f
            rotate3dAnimationX = Rotate3dAnimation()
            rotate3dAnimationX?.Rotate3dAnimation(0F, -90F, mWidth/2.0F, mHeight/2.0F, depthZ, true)
            animationSet.addAnimation(rotate3dAnimationX)
            animationSet.duration = 250
            animationSet.fillAfter = true
            animationSet.interpolator = AccelerateDecelerateInterpolator()
            ll?.startAnimation(animationSet)
            val mMessage = Message.obtain()
            mMessage.what = 1001
            // 使用sendEmptyMessageDelayed延时1s后发送一条消息
            mHandler.sendEmptyMessageDelayed(MainActivity.MESSAGE_WHAT, 240)
        })



 private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            when (msg?.what) {
                MainActivity.MESSAGE_WHAT -> {
                    gotoIntent()
                }
                else -> {
                }
            }
        }
    }

大家可以看到,我动画执行的时间为250ms,但是我在240ms就用handler实现界面的跳转了,这也是在调试的时候遇到的一个小问题吧,稍后会说明。在第一个界面,我逆向旋转了90度。

Activity2:

相同的,在第二个Activity中,我把View执行了从-270度到-360度的翻转,也就是视觉上从底下翻上来的效果,简单的看下代码:

  private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            when (msg?.what) {
                Main2Activity.MESSAGE_WHAT -> {
                    val ll = findViewById<View>(R.id.main2_layout)
                    //在此处练习了下动画集合的用法  可直接使用rotate3dAnimationX动画
                    val animationSet = AnimationSet(true)
                    val depthZ = 450f
                    val rotate3dAnimationX = Rotate3dAnimation()
                    rotate3dAnimationX.Rotate3dAnimation(-270F, -360F, mWidth/2.0F, mHeight/2.0F, depthZ, false)
                    animationSet.addAnimation(rotate3dAnimationX)
                    animationSet.duration = 250
                    animationSet.fillAfter = true
                    animationSet.interpolator = AccelerateDecelerateInterpolator()
                    ll?.startAnimation(animationSet)
                }
                else -> {
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.activity_main2)
        val screenBounds = ScreenUtils.getScreenBounds(this)
        mWidth = screenBounds[0]
        mHeight = screenBounds[1]
        val mMessage = Message.obtain()
        mMessage.what = 1001
        // 使用sendEmptyMessageDelayed延时1s后发送一条消息
        mHandler.sendEmptyMessageDelayed(Main2Activity.MESSAGE_WHAT, 0)
    }

就这样就实现了吗?未免太过分了,还有很多坑。

实现过程中遇到的问题和解决方法

(如果您有好的解决方法,烦请告知)

Tim1:我去除了Activity默认的跳转效果,但是在衔接的地方还是有明显的卡顿效果。
通过查阅资料,即使我们取消了默认的跳转效果,但是他是两个Activity,在转换的过程还是有一定的切换效果呢?那么我们就给它设置一个效果呗,只不过没有任何动画。例如:

在跳转时设置无动画效果:

  private fun gotoIntent() {
        val intent = Intent(this, Main2Activity().javaClass)
        this.startActivity(intent)
        //写两个空动画 去除两个activity间明显的卡顿效果
        this.overridePendingTransition(R.anim.fade_in, R.anim.fade_in)
    }

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="1.0" android:toXDelta="1.0"
        android:fromYDelta="1.0" android:toYDelta="1.0"
        android:duration="0" />
</set>

Tim2:第一个Activity跳转后在返回界面消失:
返回后界面消失了,我的天!!!翻转后状态没返回来?才疏学浅,找了找也没发现有方法可以重置状态,只能这么办了,自己看吧,太low了,哎!

        //在界面执行此方法时 把界面恢复原来的状态  暂时没想到其他好的方法
    override fun onStop() {
        val animationSet = AnimationSet(true)
        rotate3dAnimationX?.Rotate3dAnimation(-90F, 0F, mWidth/2.0F, mHeight/2.0F, 0F, true)
        animationSet.duration = 0
        animationSet.addAnimation(rotate3dAnimationX)
        ll?.startAnimation(animationSet)
        super.onStop()
    }

Tim3:之前的问题,在第一个界面我为什么提前10秒钟开始跳转逻辑呢?

哈哈,其实我也不知道,在时间同步的情况下,我发现在两个Activity的衔接处,还是有一点点的衔接效果,思考了下,我如果让下一个Activity提前开始动画呢,会不会好一点,事实证明了我的想法,至少在视觉上很好了。

写在最后

跌跌撞撞,反正效果实现了,如果您也有这样的需求,欢迎探讨更好的实现方式!!!

PS:下载链接:https://download.youkuaiyun.com/download/say_from_wen/10664221
github:https://github.com/loveAndroidAndroid/android-study

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值