Android 启动黑屏优化(Cocos Creator 游戏)
一 Android 显示结构
cocos creator 在打包成 Android 之后,首先启动一个标准 Android 应用。因此需要先弄清楚 Android 应用的显示逻辑。
每个 Android 应用显示由 Activity、Window、View 等组成。每个 Android 应用至少有一个 Activity;Activity 可以包含多个 Window,有一个 PhoneWindow 是根;
在每个 Window 中,Acitivity 通过 setContentView 设置将 View 设置到 PhoneWindow;View一般是一个布局 xml 文件。在 setContentView 之前,显示的是应用的主题 Theme。
二 黑屏原因
1 Theme
Cocos Creator 生成了一个 AppActivity,在 app 的 AnroidManifest.xml 中可以看到 :
<activity
android:name="org.cocos2dx.javascript.AppActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
...>
...
</activiy>
AppActivity 在主题被设置为了 Theme.NoTitleBar.Fullscreen,该主题没有背景,显示出来的是黑屏。
为了减少黑屏事件,就需要重新指定一个有背景的主题。首先,在文件 app/res/values/styles.xml 中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyTheme" parent="@android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@drawable/图片名</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
新建一个主题,集成自之前指定的主题,设置一个背景图片,注意图片名没有后缀。然后修改 AnroidManifest.xml 中的主题为刚刚新键的主题:
<activity
android:name="org.cocos2dx.javascript.AppActivity"
android:theme="@styles/MyTheme"
...>
...
</activiy>
2 View
AppActivity 集成自 Cocos2dxActivity,在 Cocos2dxActivity 中可以看到:
public void init() {
ViewGroup.LayoutParams frameLayoutParams =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(frameLayoutParams);
Cocos2dxRenderer renderer = this.addSurfaceView();
this.addDebugInfo(renderer);
// Should create EditBox after adding SurfaceView, or EditBox will be hidden by SurfaceView.
mEditBox = new Cocos2dxEditBox(this, mFrameLayout);
// Set frame layout as the content view
setContentView(mFrameLayout);
...
}
设置的 view 没有任何内容,显示出来的就是黑色,因此需要给 view 上添加一些内容。添加一个方法 showSplash 在 AppActivity 的 onCreate 方法中调用。等到游戏场景加载完成之后,再将其因此即可。
public class AppActivity extends Cocos2dxActivity {
private static Cocos2dxActivity sCocos2dxActivity;
private static ImageView sSplashBgImageView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 显示 Activity 背景
sCocos2dxActivity = this;
showSplash();
...
}
...
private static void showSplash() {
// 创建一张图片作为 Activity 的背景
sSplashBgImageView = new ImageView(sCocos2dxActivity);
// 纯色背景
// sSplashBgImageView.setBackgroundColor(sCocos2dxActivity.getResources().getColor(R.color.splash_bg));
// 图片背景
// sSplashBgImageView.setImageResource(R.drawable.splash);
// 纯色背景 + 图片
sSplashBgImageView.setImageResource(R.drawable.图片名);
sSplashBgImageView.setScaleType(ImageView.ScaleType.FIT_XY);
sCocos2dxActivity.addContentView(sSplashBgImageView,
new WindowManager.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
);
}
// OpenGL 线成调用 UI 线成中执行操作
public static void hideSplash() {
sCocos2dxActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (sSplashBgImageView != null) {
sSplashBgImageView.setVisibility(View.GONE);
}
}
});
}
}
3 scene
在场景加载之前,因为 OpenGL 还没有开始绘制内容,因此也是黑屏的。前面 View 中添加了背景图片,是覆盖在游戏内容之上,因此需要登录场景加载完成,游戏内容显示出来之后,再调用 hideSplash 方法将 View 中的图片隐藏。