博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 手游闪屏极简方案
阅读量:7213 次
发布时间:2019-06-29

本文共 3954 字,大约阅读时间需要 13 分钟。

逃离博客园,搬运一篇2015年做手游时期的旧文。

简约至上 少写代码

为什么需要闪屏

  1. 手机应用程序不应该有闪屏, Google Android 自家的 App 据说已经全面禁用闪屏。

  1. 中国大量手机应用程序,或者说相关从业人员依旧坚持必须存在一个闪屏图片的审美。

为什么需要原生实现

  1. UnrealEngine3 需要
    UE3 初始化和场景切换时,渲染线程暂停,因此需要使用原生方案显示图片或视频来过渡等待。
  2. cocos2d-x 需要
    cocos2d-x 论坛
  3. Unity3D
    大概类似,未考证。

为什么不应该使用 Splash Activity

“你搜到的都是错的”

网上搜索 Android 闪屏实现方案,99%的结果都是介绍如何使用一个简单的 Activity 实现,再过渡切换到真正的 GameActivity 。这种方案仅限教学,实际应用有很多弊端。

  1. 这种方案要求在 AndroidManifest.xml 中配置的 LaunchActivity 必须是 SplashActivity
    当需要实现带参数 Intent 启动时,SplashActivity 需要正确地传递参数(Intent)给 GameActivity。繁琐。
  2. 游戏使用 NDK 开发,OpenGL, UI View, thread 需要跟 GameActivity's SurfaceView 绑定。
    SplashActivity 显示期间,GameActivity 无法被加载,因此也无法并行加载游戏引擎相关实例。导致闪屏过后,GameActivity 仍需一个加载界面用于过渡等待 GameEngine 的启动耗时。
  3. 游戏需要接入各种 SDK。很多 SDK 要求在 GameActivity 的生命周期插入诸多 hook 事件代码。
    例如 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy() 等等,这些是常用 hook 位置。
    SplashActivity 方案使相关逻辑实现更复杂。

一种适合游戏的简单闪屏实现方案

  1. 使用一个全屏 Dialog
    Android Dialog 拥有独立的 Window ,与 GameView 无耦合。
  2. 屏蔽 User Input Event
    Dialog 默认接收所有User Input Event ,不需要传递给 GameView,因此与游戏逻辑无耦合。
  3. 实现动画
    可以很方便的使用各种原生 Android Animation ,实现可用的过渡动画呈现。
  4. 动画结束后自动消失
    Dialog 可以自我管理生命周期,再次与游戏无耦合。
  5. 并行加载游戏实例
    GameSurfaceView and GameEngine 可以在 Dialog 显示期间,后台并行加载,无耦合,且真正达到异步和节省时间的目标。

代码示例

  1. 创建全屏 Dialog
public class NSSplashDialog extends Dialog {    private PercentFrameLayout mLayout = null;    private ImageView mImageView = null;    public NSSplashDialog(Context context) {        super(context, android.R.style.Theme_NoTitleBar_Fullscreen);        setContentView(R.layout.splash);        mLayout = (PercentFrameLayout)findViewById(R.id.layout_splash);        mImageView = (ImageView)this.findViewById(R.id.iv_splash);    }}复制代码

2 . 屏蔽 User Input Event

setCanceledOnTouchOutside(false);setCancelable(false);复制代码

3 . 实现动画

private AlphaAnimation mAnimation = null;private int mBitmapIndex = 0;mAnimation = new AlphaAnimation(0.0f, 1.0f); //fade in, fade outmAnimation.setDuration(2000);//2 secondsmAnimation.setRepeatCount(3); //show 4 imagesmAnimation.setAnimationListener(new Animation.AnimationListener(){    @Override    public void onAnimationStart(Animation animation) {        mBitmapIndex = 0;        mLayout.setBackgroundColor(Color.WHITE);        mImageView.setImageDrawable(BitmapUtil.loadDrawable(getContext(), R.drawable.splash0));    }    @Override    public void onAnimationEnd(Animation animation) {        mBitmapIndex = 0;        kick(false);    }    @Override    public void onAnimationRepeat(Animation animation) {        mBitmapIndex++;        switch(mBitmapIndex) {        case 1:            mLayout.setBackgroundColor(Color.WHITE);            mImageView.setImageDrawable(BitmapUtil.loadDrawable(getContext(), R.drawable.splash1));            break;        case 2:            mLayout.setBackgroundColor(Color.BLACK);            mImageView.setImageDrawable(BitmapUtil.loadDrawable(getContext(), R.drawable.splash2));            break;        case 3:            mLayout.setBackgroundColor(Color.BLACK);            mImageView.setImageDrawable(BitmapUtil.loadDrawable(getContext(), R.drawable.splash3));            break;        default:            break;        }    }});mImageView.setAnimation(mAnimation);复制代码

4 . 动画结束后自动消失

onAnimationEnd()中调用kick(false),即关闭自己。

实测发现部分系统有bug:onAnimationEnd() 和 cancel() 可能会死循环,因此添加保护逻辑判断 hasEnded()

public void kick(boolean show) {    if(show) {        show();        mAnimation.start();    } else {        if(!mAnimation.hasEnded()) {            mAnimation.cancel();        }        dismiss();    }}复制代码

5 . 闪屏与游戏并行加载

GameActivity 生命周期中, 在 onCreate() 创建 SplashDialog 实例,在 onDestroy() 清除 SplashDialog 实例。

//Create    mSplashDialog = new NSSplashDialog(this);	mSplashDialog.kick(true);    //Destroy    if(mSplashDialog != null && mSplashDialog.isShowing()) {        mSplashDialog.kick(false);    }复制代码

Loading View

闪屏说完了,最后提一下 Loading View

上面说到 UE3 在场景切换时,需要使用平台原生界面做过渡展示。根据业务需求不同,可能有时候不便复用 SplashDialog,那可以使用一个独立 layout View 实现。

转载于:https://juejin.im/post/5cee10de51882512c54cad17

你可能感兴趣的文章
HBase存储剖析与数据迁移
查看>>
人工智能高考511分,未来有望考上东京大学!
查看>>
O2O业务都跳不出这五大领域
查看>>
呼之欲出的量子计算机和漫长的最后一公里
查看>>
“九”答不可 | 量子保密,完美无缺?
查看>>
VMware备份研究
查看>>
dotnet调用node.js写的socket服务(websocket/socket/socket.io)
查看>>
Nibiru Open Day,OZO 遇见 DigiArtist 国际数字艺术展
查看>>
MySQL · 引擎分析 · InnoDB行锁分析
查看>>
ARKit应用超300万次安装,排第一的是一款养成游戏
查看>>
C++ 对引用的深入理解
查看>>
vuejs v-for指令
查看>>
HTTP协议基础
查看>>
Android进阶笔记:Messenger源码详解
查看>>
MySQL的编译安装
查看>>
使用SSH连接CentOS步骤
查看>>
Elasticsearch 5 Ik+pinyin分词配置详解
查看>>
jsp实现简单的分页
查看>>
阿里云虚拟主机数据库主机怎么看
查看>>
[投稿]通过Web界面在多台服务器上批量创建文件
查看>>