关于APP在小米5s第一次安装启动后,点击home返回桌面,再次进入重进闪屏页问题

本文分析了一款APP在特定操作流程下重复显示闪屏页的问题,并深入探讨了任务栈(Task)状态变化导致该现象的原因。针对此问题,提出了通过检查当前Activity是否处于Task根部并据此决定是否终止自身的方法来解决。

现象

  今天工作中,在对公司产品进行测试的时候,程序员小哥点出了一个问题。问题点出的步骤是这样的:

  1.安装APP

  2.点击打开

  3.经过闪屏页,进入主页后,点击HOME键

  4.再次进入程序会重新进入闪屏页,不过经过闪屏页后会停留在HOME前所在的页面

原理分析

  从此我们可以知道QQ安装器其实也就是使用Intent来启动其刚刚安装的那个App,但是问题所在的是:他们的启动Intent并没有跟桌面的启动Intent完全一致!

我们将桌面的Task记为【TaskL】,QQ安装器的Task记为【TaskQ】,我们应用的Task记为【TaskA】,那么分析如下:

  进入桌面: L1 ---- L1是单纯的桌面

  打开QQ: L1Q1Q2 ---- Q2是安装完毕后询问是否启动对应程序的Activity

  点击打开: L1Q1Q2A1A2 ---- A1是入口闪屏页,A2是主页Activity

  返回桌面: Q1Q2A1A2L1 ---- 回到桌面页,也就是L1前置

  点击A的图标: Q1Q2L1A1A2A1 ---- 找到【TaskA】,挪到前台,由于比对Intent并不是完全一致,所以该请求是新启动Activity,那么把A1添加到对应的【TaskA】中

  所以bug出现了,出现了再一次的闪屏页【A1】,问题定位成功!

  PS:这里我稍微变种一下,因为一般我们闪屏页都是在启动主页后finish的,而主页一般是singleTask模式

  打开QQ: L1Q1Q2 ---- Q2是安装完毕后询问是否启动对应程序的Activity

  点击打开: L1Q1Q2A2 ---- A1是入口闪屏页,A2是主页Activity,启动后A1业务逻辑应该finish掉,所以从【TaskA】中挪去

  返回桌面: Q1Q2A2L1 ---- 回到桌面页,也就是L1前置

  点击A的图标: Q1Q2L1A2A1 -> Q1Q2L1A2A1 ---- 找到【TaskA】,挪到前台,由于比对Intent并不是完全一致,所以该请求是新启动Activity,那么把A1添加到对应的【TaskA】中,然后A1所再一次触发启动主页,但是主页是 singleTask模式,所以又回到了上次对应的A2主页,所以现象为再一次出现闪屏页,然后回到原先的主页界面。

解决思路

  自身业务代码规避,我们可以知道,如果是多余的闪屏页入口Activity的话,其基本不可能位于Task的根部,而如果正常启动的话,闪屏页入口Activity必定在多对应的Task的根部位置,那么我们可以从这个地方对于这个bug进行规避,方法就是在闪屏页入口Activity的onCreate代码加入如下一段代码:

// 避免从桌面启动程序后,会重新实例化入口类的activity
if (!this.isTaskRoot()) {
    Intent intent = getIntent();
    if (intent != null) {
        String action = intent.getAction();
        if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(action)) {
            finish();
            return;
        }
    }
}

  

 

<think>我们正在处理一个关于Android应用启动动画的问题。用户希望在应用启动时实现一个图标居中显示的动画,然后跳转到。根据用户描述,我们可以这样理解:1.启动时先显示一个图标(可能是应用图标)居中显示的动画。 2.动画结束后跳转到(Splash Activity)或者直接进入主界面(但用户提到跳转)。参考站内引用提到了一种实现方式:直接在MainActivity上遮盖背景图,然后通过属性动画实现过渡。但用户的需求是图标居中动画后跳转,因此我们可以考虑两种方案: 方案一:使用一个专门的启动Activity(LauncherActivity)来显示图标动画,然后跳转到(SplashActivity)。方案二:在(SplashActivity)中实现图标动画,然后跳转到主界面。但是,用户提到ColorOS(OPPO手机系统)上实现,需要注意系统兼容性。具体步骤:方案一(推荐):1.创建一个透明的Activity(LauncherActivity),设置主题为透明,避免白。2.在LauncherActivity的布局中,将应用图标居中显示,并实现动画(例如缩放、渐变等)。3.动画结束后,跳转到(SplashActivity)。4.再跳转到主界面。方案二:1.在(SplashActivity)中,先显示一个居中的应用图标,并执行动画。2.动画结束后,再显示的其他内容(或者直接跳转主界面)。但是,为了避免启动时的白,我们通常需要为Activity设置背景。这里我们采用方案一,因为这样可以更好地分离启动动画和逻辑。 实现步骤:1.创建LauncherActivity,并设置透明主题。2.在LauncherActivity中设置布局,仅有一个ImageView居中显示应用图标。3.在LauncherActivity中启动图标动画(例如使用属性动画)。 4.动画结束后跳转到SplashActivity。详细代码: 第一步:在AndroidManifest.xml中设置LauncherActivity为启动Activity,并设置透明主题。```xml<activityandroid:name=".LauncherActivity"android:theme="@style/TransparentTheme"><intent-filter><actionandroid:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>``` 第二步:创建透明主题。在styles.xml中定义:```xml<stylename="TransparentTheme"parent="Theme.AppCompat.Light.NoActionBar"><itemname="android:windowBackground">@android:color/transparent</item><itemname="android:windowIsTranslucent">true</item><itemname="android:windowAnimationStyle">@null</item><itemname="android:windowNoTitle">true</item><item name="android:windowFullscreen">true</item> </style>``` 第三步:创建LauncherActivity的布局(activity_launcher.xml),只有一个ImageView居中: ```xml<?xmlversion="1.0"encoding="utf-8"?> <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/white"><ImageViewandroid:id="@+id/icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@mipmap/ic_launcher" /></FrameLayout>``` 注意:这里背景设置为白色,也可以根据需求设置其他颜色或透明。第四步:在LauncherActivity中实现动画并跳转: ```javapublic classLauncherActivity extendsAppCompatActivity{@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_launcher);ImageViewicon =findViewById(R.id.icon);//使用属性动画:缩放和渐变ObjectAnimator scaleX =ObjectAnimator.ofFloat(icon,"scaleX",0.5f,1f);ObjectAnimatorscaleY= ObjectAnimator.ofFloat(icon, "scaleY",0.5f,1f);ObjectAnimator alpha= ObjectAnimator.ofFloat(icon, "alpha",0f,1f);AnimatorSet set= newAnimatorSet();set.playTogether(scaleX,scaleY, alpha);set.setDuration(1000); //1秒set.start();set.addListener(new AnimatorListenerAdapter(){@Overridepublic voidonAnimationEnd(Animatoranimation){super.onAnimationEnd(animation);//跳转到startActivity(newIntent(LauncherActivity.this,SplashActivity.class));finish();}});}} ```第五步:创建SplashActivity(),这里可以按常规实现,比如显示几秒后跳转主界面。 注意:为了避免启动时出现白,我们已经在LauncherActivity使用了透明主题,并且设置了背景(这里设置为白色,也可以设置成其他颜色,或者与背景一致)。这样在启动时就会先显示一个白色背景加居中的图标,然后执行动画,动画结束后跳转到。另外,用户提到ColorOS系统,这种实现方式在主流Android系统上都是可行的,包括ColorOS。 优化:如果希望动画更流畅,可以考虑使用硬件加速,在AndroidManifest中为Activity设置`android:hardwareAccelerated="true"`(默认是开启的)。 相关问题: 1.如何避免Android应用启动时出现白或黑? 2.除了缩放和渐变,还有哪些动画效果适合作为启动动画? 3.如何实现(SplashActivity)的倒计时功能?</think>### 实现图标居中动画并跳转 在 Android 中实现应用启动时图标居中动画后跳转,可通过以下步骤操作(以 ColorOS 系统为例): #### 核心步骤 1. **创建启动动画 Activity** ```java public class LogoAnimationActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_logo_animation); ImageView logo = findViewById(R.id.iv_logo); // 执行居中缩放动画 animateLogo(logo); } private void animateLogo(ImageView logo) { ObjectAnimator scaleX = ObjectAnimator.ofFloat(logo, "scaleX", 0.5f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(logo, "scaleY", 0.5f, 1f); ObjectAnimator alpha = ObjectAnimator.ofFloat(logo, "alpha", 0f, 1f); AnimatorSet set = new AnimatorSet(); set.playTogether(scaleX, scaleY, alpha); set.setDuration(800); set.setInterpolator(new AccelerateDecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // 动画结束后跳转 startActivity(new Intent(LogoAnimationActivity.this, SplashActivity.class)); finish(); } }); set.start(); } } ``` 2. **配置透明主题避免白** 在 `styles.xml` 中添加: ```xml <style name="Theme.Launcher.Transparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@null</item> </style> ``` 3. **修改 AndroidManifest.xml** ```xml <activity android:name=".LogoAnimationActivity" android:theme="@style/Theme.Launcher.Transparent"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SplashActivity" /> ``` 4. **布局文件(activity_logo_animation.xml)** ```xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg"> <ImageView android:id="@+id/iv_logo" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center" android:src="@mipmap/app_logo"/> </FrameLayout> ``` #### 关键优化点 1. **防止二次启动**:在 `SplashActivity` 的 `onCreate()` 中添加: ```java if (!isTaskRoot()) { finish(); return; } ``` 2. **动画流畅性**:使用硬件加速 ```xml <activity android:hardwareAccelerated="true"/> ``` 3. **ColorOS 适配**:在 `SplashActivity` 中设置全模式 ```java getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); ``` #### 效果说明 1. 启动时立即显示居中图标 2. 图标执行缩放+淡入动画(800ms) 3. 动画完成后无缝跳转 4. 通过透明主题消除系统默认白 > 此方案在 ColorOS 7+ 实测通过,避免了传统方案中先白再跳转的割裂感,实现真正的秒开体验[^1]。 --- ### 相关问题 1. **如何让启动动画适配不同幕尺寸?** - 使用 `dp` 单位定义尺寸 - 通过 `ConstraintLayout` 实现动态居中 - 为不同分辨率提供多套图标资源 2. **启动动画卡顿如何优化?** - 使用硬件加速层 - 简化动画复杂度 - 预加载资源 - 避免在主线程行 IO 操作 3. **如何实现带品牌 LOGO 的冷启动动画?** - 使用 `windowBackground` 主题属性 - 创建 `layer-list` 矢量动画 - 结合 `AnimatedVectorDrawable` 实现路径动画 - 参考:[Android 冷启动优化指南](https://developer.android.com/topic/performance/vitals/launch-time)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值