Android纯文本渐变启动页:自定义Splash Screen
2025-03-05 21:16:21
Android 原生启动页:打造纯文本渐变效果
开发 App 时,启动页(Splash Screen)是给用户的第一印象。很多时候,我们会看到带应用图标的启动页。但是,如果你想玩点不一样的,比如纯文本、带动画效果的启动页呢?这篇文章就来帮你搞定它!别担心,虽然原帖的问题关闭了,但是问题可以分析解决.
一、问题拆解:不走寻常路
一般启动页都是显示个图标或者图片。 这次的需求比较特别:
- 不要图标,只要文字。
- 文字最好能逐个显示(类似打字机效果)。
- 文字颜色还要是渐变的。
- 用原生 Android 代码实现 (因为提问者用的 Flutter,想用原生方式定制启动页)。
二、原因分析:为什么不能直接用?
Android 12 (API 级别 31) 之后,系统引入了全新的 SplashScreen
API。 这套 API 简化了启动页的实现,但同时也带来了一些限制:
- 默认行为:新 API 倾向于使用应用图标,直接设置纯文本可能不那么直观。
- 自定义限制:虽然可以自定义,但要实现逐字显示、渐变等效果,需要更多底层操作。
直接用现成的方案,可能满足不了这么个性化的需求。所以,我们得自己动手,丰衣足食。
三、解决方案:步步为营,逐个击破
1. 基础启动页:先让它显示出来
不管怎样,先搞个能显示的启动页。
原理:
- 利用
SplashScreen
API(兼容旧版本)。 - 创建一个专门的 Theme 给启动页用。
- 在
AndroidManifest.xml
中指定这个 Theme。
步骤:
-
创建 Theme: 在
res/values/styles.xml
(或themes.xml
) 中添加:<style name="AppTheme.Starting" parent="Theme.SplashScreen"> <item name="windowSplashScreenBackground">@color/white</item> </style>
如果你的项目已经针对夜间模式配置了深色背景,那新建一个文件
res/values-night/styles.xml
,并将其中windowSplashScreenBackground
设置为深色背景色. -
AndroidManifest.xml: 找到你的启动 Activity(通常是
MainActivity
),修改它的android:theme
:<activity android:name=".MainActivity" android:theme="@style/AppTheme.Starting"> </activity>
-
MainActivity.kt (或 .java): 在
onCreate
方法的最前面,调用installSplashScreen()
:import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { installSplashScreen() super.onCreate(savedInstanceState) // ... 其他代码 ... } }
或者,如果你是Java:
import androidx.core.splashscreen.SplashScreen; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { SplashScreen.installSplashScreen(this); super.onCreate(savedInstanceState); // ... 其他代码 ... } }
这样设置主题会使Android 12 及以上版本的启动页使用纯白色填充.
在之前的版本上,我们接下来设置.这一步确保了在 App 内容加载前,能看到一个基本的启动页(现在是纯色背景)。
2. 去掉图标,换成文本
接下来,干掉图标,换上我们想要的文本。
原理:
- 自定义
windowSplashScreenAnimatedIcon
:虽然名字里有 "Icon",但我们可以用TextView
把它替换掉。 - 自定义
postSplashScreenTheme
,应用原本的主题.
步骤:
继续编辑res/values/styles.xml
:
```xml
<style name="AppTheme.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/white</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen_text</item>
<item name="postSplashScreenTheme">@style/Theme.YourOriginalTheme</item>
</style>
```
注意替换Theme.YourOriginalTheme
为你应用原本的主题。
创建文本 Drawable:
-
新建
res/drawable/splash_screen_text.xml
:<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <solid android:color="@android:color/transparent" /> </shape> </item> <item android:gravity="center"> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mathoria" android:textSize="48sp" android:textStyle="bold" android:textColor="@android:color/black"/> </item> </layer-list>
这里,我们用一个透明背景的
layer-list
包裹TextView
,实现居中显示文本。
旧版本兼容:
如果你需要兼容比 Android 12 更老的设备,需要额外进行设置
新建 res/layout/activity_splash.xml
:
<androidx.constraintlayout.widget.ConstraintLayout 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=".SplashActivity"
android:background="@android:color/white">
<TextView
android:id="@+id/tv_splash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mathoria"
android:textSize="48sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
新建 SplashActivity.kt
:
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(Intent(this@SplashActivity,MainActivity::class.java))
finish()
}
}
修改 AndroidManifest.xml
,启动 Activity 改为SplashActivity
:
<activity
android:name=".SplashActivity"
android:theme="@style/AppTheme.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
</activity>
现在旧版本也可看到文本启动页
3. 渐变色:给文字上色
静态文本有点单调,来给它加个渐变色。
原理:
- 使用
Shader
(着色器)来实现渐变效果。 - 在
TextView
的paint
上应用Shader
。
步骤:
-
修改之前的
res/drawable/splash_screen_text.xml
: 去掉android:textColor
属性, 因为我们要在代码里实现.<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mathoria" android:textSize="48sp" android:textStyle="bold" />
代码实现渐变:
需要的话,为旧版本修改res/layout/activity_splash.xml
,做相同处理。
我们需要重写一个 TextView
:
-
新建
GradientTextView.kt
:import android.content.Context import android.graphics.LinearGradient import android.graphics.Shader import android.util.AttributeSet import androidx.appcompat.widget.AppCompatTextView class GradientTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AppCompatTextView(context, attrs, defStyleAttr) { override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) if (changed) { paint.shader = LinearGradient( 0f, 0f, width.toFloat(), height.toFloat(), intArrayOf( context.getColor(R.color.pink), // 你的粉色 context.getColor(R.color.blue) // 你的蓝色 ), null, Shader.TileMode.CLAMP ) } } }
别忘了在
res/values/colors.xml
里添加你需要的颜色定义:<color name="pink">#FFC0CB</color> <color name="blue">#0000FF</color>
-
替换 TextView: 把上面所有的
TextView
, 替换为GradientTextView
。res/drawable/splash_screen_text.xml
:<com.yourpackage.GradientTextView </com.yourpackage.GradientTextView>
- 如果你创建了
activity_splash.xml
:
<com.yourpackage.GradientTextView </com.yourpackage.GradientTextView>
(记得把
com.yourpackage
换成你自己的包名)。
这样,文本就有了从粉色到蓝色的渐变效果。
4. 逐字显示:让文字动起来
最后,来实现逐字显示的动画效果。
原理:
- 使用
Handler
和Runnable
来定时更新TextView
的内容。 - 每次更新只显示文本的一部分,模拟打字机效果。
步骤:
对于 Android 12+, 因为我们修改了windowSplashScreenAnimatedIcon
属性,SplashScreen
API 不再处理动画, 我们可以在 MainActivity
中实现:
-
修改
MainActivity.kt
:override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //设置布局文件,其中包含一个GradientTextView. val textView = findViewById<GradientTextView>(R.id.tv_splash) splashScreen.setKeepOnScreenCondition{true}//保持启动页显示. val text = "Mathoria" var index = 0 val handler = Handler(Looper.getMainLooper()) val runnable = object : Runnable { override fun run() { if (index <= text.length) { textView.text = text.substring(0, index) index++ handler.postDelayed(this, 100) // 每 100 毫秒更新一次 } else{ splashScreen.setKeepOnScreenCondition{false}// 隐藏启动画面. } } } handler.post(runnable) // ... 其他代码 ... }
注意设置setContentView(R.layout.activity_main)
,和 GradientTextView
的 id。
对于旧版安卓,我们修改SplashActivity
:
- 修改
SplashActivity.kt
:
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
val textView = findViewById<GradientTextView>(R.id.tv_splash)
val text = "Mathoria"
var index = 0
val handler = Handler(Looper.getMainLooper())
val runnable = object : Runnable {
override fun run() {
if (index <= text.length) {
textView.text = text.substring(0, index)
index++
handler.postDelayed(this, 100) // 每 100 毫秒更新一次
}else
{
startActivity(Intent(this@SplashActivity,MainActivity::class.java))
finish()
}
}
}
handler.post(runnable)
}
}
现在,启动 App 时,就能看到文本逐字显示,并带有渐变效果的启动页了。
四、一点补充
如果你不想要动画效果,只是想要静态显示文本。你可以省掉很多自定义的东西:
- 直接创建
res/drawable/splash_screen_text.xml
: 使用<TextView>
,通过android:textColor
来处理颜色。 - 新版本, 通过 Theme 的
windowSplashScreenAnimatedIcon
引用这个 Drawable,并正确设置postSplashScreenTheme
。 - 旧版本, 使用上文中旧版本的方案, 通过一个
SplashActivity
的布局文件,直接放置TextView
, 然后启动你的MainActivity
.
通过上面的几个步骤,你就完成了目标,做到了纯文本,带渐变,还带动画的启动页。