You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现启动页TextView从中心显示2秒后动画移至顶部并固定?

实现启动页TextView的延迟移动动画

嘿,这个启动页的动画需求很常见,咱们一步步来拆解实现,保证效果丝滑又贴合你的要求👇

第一步:布局文件设置

先把TextView初始放在屏幕中心,用ConstraintLayout能轻松实现精准定位:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_app_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="你的应用名称"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

第二步:实现延迟移动动画

核心逻辑是:让TextView在中心停留2秒,然后执行Y轴平移动画到顶部,最后固定位置避免布局刷新后回退。这里用ObjectAnimator更简洁,能直接操作View属性。

Kotlin 实现

import android.animation.ObjectAnimator
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_splash.*

class SplashActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        // 延迟2秒触发动画
        Handler(Looper.getMainLooper()).postDelayed({
            // 计算移动距离:从中心到顶部 = 屏幕半高 - TextView自身半高,避免文字被顶出屏幕
            val moveDistance = (resources.displayMetrics.heightPixels / 2 - tv_app_name.height / 2).toFloat()
            // 创建Y轴向上平移的动画
            val animator = ObjectAnimator.ofFloat(tv_app_name, "translationY", 0f, -moveDistance)
            animator.duration = 800 // 动画时长可按需调整,800ms是比较自然的速度
            animator.start()

            // 动画结束后修改布局约束,固定TextView在顶部
            animator.addListener(object : android.animation.Animator.AnimatorListener {
                override fun onAnimationStart(animation: android.animation.Animator?) {}
                override fun onAnimationEnd(animation: android.animation.Animator?) {
                    tv_app_name.layoutParams.apply {
                        (this as androidx.constraintlayout.widget.ConstraintLayout.LayoutParams).run {
                            topToTop = androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID
                            bottomToBottom = androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.UNSET
                        }
                        tv_app_name.requestLayout()
                    }
                }
                override fun onAnimationCancel(animation: android.animation.Animator?) {}
                override fun onAnimationRepeat(animation: android.animation.Animator?) {}
            })
        }, 2000) // 2000毫秒 = 2秒延迟
    }

    // Activity销毁时取消动画,避免内存泄漏
    override fun onDestroy() {
        super.onDestroy()
        tv_app_name.animate().cancel()
    }
}

Java 实现

import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;

public class SplashActivity extends AppCompatActivity {

    private TextView tvAppName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        tvAppName = findViewById(R.id.tv_app_name);

        // 延迟2秒执行动画
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            // 计算移动距离
            float moveDistance = (getResources().getDisplayMetrics().heightPixels / 2 - tvAppName.getHeight() / 2);
            // 创建Y轴平移动画
            ObjectAnimator animator = ObjectAnimator.ofFloat(tvAppName, "translationY", 0f, -moveDistance);
            animator.setDuration(800);
            animator.start();

            // 动画结束后固定位置
            animator.addListener(new android.animation.Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(android.animation.Animator animation) {}

                @Override
                public void onAnimationEnd(android.animation.Animator animation) {
                    androidx.constraintlayout.widget.ConstraintLayout.LayoutParams params =
                            (androidx.constraintlayout.widget.ConstraintLayout.LayoutParams) tvAppName.getLayoutParams();
                    params.topToTop = androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID;
                    params.bottomToBottom = androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.UNSET;
                    tvAppName.setLayoutParams(params);
                }

                @Override
                public void onAnimationCancel(android.animation.Animator animation) {}

                @Override
                public void onAnimationRepeat(android.animation.Animator animation) {}
            });
        }, 2000);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        tvAppName.animate().cancel();
    }
}

关键细节提醒

  • 移动距离必须考虑TextView自身高度,不然文字可能会被顶出屏幕外;
  • 动画结束后修改布局约束是为了防止屏幕旋转、布局刷新等场景下,TextView回到中心位置;
  • 在onDestroy中取消动画,避免Activity销毁后动画仍在运行导致内存泄漏。

内容的提问来源于stack exchange,提问作者Satyaraj Moily

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:44:14