自定义Unity闪屏ForAndroid

来源:互联网 发布:ps软件培训班 编辑:程序博客网 时间:2024/04/30 18:09

嗯,工作中遇到策划提了一个小需求:酷炫的闪屏。。
我们知道unity自带的闪屏。。。真·一张图片,其实没有任何的动画效果,所以来看一下怎么定义自己的闪屏方案吧。

基本思路就是用Android的闪屏内嵌到Unity中,通过jar包和Android资源以及程序启动Activity设置,实现自定义的闪屏。

首先使用Eclipse或Android Studio新建一个Library工程,新建闪屏Activity及布局文件,布局文件很简单,一张match_parent的图片就可以了,闪屏代码包含两个动画,缩放和透明度变化,可以自己定制别的效果,比如旋转动画什么的。

源码:

public class Splash extends Activity {    final String TAG = "Splash";    private final int maxSupport = 5;    AnimationListenerBack animationListener;    //  AlphaAnimation alphaAni;    ImageView splashView;    Class<?> next;    private boolean ispause;    private long splashDur = 3000;    private float fromAlpha = 0.1f;    private float toAlpha = 1.0f;    private float fromScale = 1.0f;    private float toScale = 1.2f;    private int splashCount = 1;    private int currentIndex = 1;    private WeakReference<Drawable> splash;//弱引用防止OOM    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        setondraweble();        setContentView(R.layout.activity_splash1);        splashView = this.findViewById(R.id.splash);        getSplashCount();        initView();    }    private void getSplashCount() {        // TODO Auto-generated method stub        String count = getString(R.string.splash_count);        splashCount = Integer.parseInt(count);        if(splashCount > maxSupport)            splashCount = maxSupport;        nextLoader(getString(R.string.main_activity));    }    private void nextLoader(String className) {        ClassLoader loader = this.getClassLoader();        try {            ;            Log.i(TAG, "loadClass: ===> " + className);            next = loader.loadClass(className);        } catch (ClassNotFoundException e) {            e.printStackTrace();            Log.e("Splash", String.format("not find main entry, please check strings setting main_activity"));        }    }    private void initView() {        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {            splash = new WeakReference<Drawable>(getResources().getDrawable(getSplashId(currentIndex)));        } else {            splash = new WeakReference<Drawable>(getResources().getDrawable(getSplashId(currentIndex)));        }        splashView.setImageDrawable(splash.get());        initAnimation();    }    private int getSplashId(int curIndex) {        int id = R.mipmap.sp1;        switch (curIndex) {            case 1:                id = R.mipmap.sp1;                break;            case 2:                id = R.mipmap.sp2;                break;            case 3:                id = R.mipmap.sp3;                break;            case 4:                id = R.mipmap.sp4;                break;            case 5:                id = R.mipmap.sp5;                break;            default:                break;        }        return id;    }    private void initAnimation() {        AnimationSet aniSet = new AnimationSet(true);        WindowManager wm = getWindowManager();        int centerX = wm.getDefaultDisplay().getWidth() / 2;        int centerY = wm.getDefaultDisplay().getHeight() / 2;        Log.i("center", String.format("## centerX:%d, centerY:%d", centerX, centerY));        WeakReference<ScaleAnimation> scaleAnimation = new WeakReference<>(new ScaleAnimation(fromScale, toScale, fromScale, toScale, centerX, centerY));        WeakReference<AlphaAnimation> alphaAnimation = new WeakReference<>(new AlphaAnimation(this.fromAlpha, this.toAlpha));        aniSet.setDuration(splashDur);        aniSet.setFillAfter(true);        aniSet.addAnimation(scaleAnimation.get());        aniSet.addAnimation(alphaAnimation.get());        animationListener = new AnimationListenerBack();        aniSet.setAnimationListener(animationListener);        splashView.startAnimation(aniSet);    }    private void endAnimation(){        WeakReference<AlphaAnimation> end = new WeakReference<>(new AlphaAnimation(toAlpha, 0.01f));        end.get().setFillAfter(true);        end.get().setDuration(1000);        end.get().setAnimationListener(new AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {                currentIndex++;                initView();            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });        splashView.startAnimation(end.get());    }    private void setondraweble() {        requestWindowFeature(Window.FEATURE_NO_TITLE);        int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;        Window window = this.getWindow();        window.setFlags(flag, flag);    }    @Override    protected void onPause() {        // TODO Auto-generated method stub        super.onPause();        ispause = true;    }    @Override    protected void onResume() {        // TODO Auto-generated method stub        super.onResume();        ispause = false;    }    private class AnimationListenerBack implements AnimationListener {        @Override        public void onAnimationStart(Animation animation) {            // TODO Auto-generated method stub        }        @Override        public void onAnimationEnd(Animation animation) {            // TODO Auto-generated method stub            if(currentIndex < splashCount){                endAnimation();            }else{                Intent intent = new Intent();                if (next == null) {                    try {                        throw new Exception("not find main entry!");                    } catch (Exception e) {                        e.printStackTrace();                        return;                    }                }                intent.setClass(Splash.this, next);                startActivity(intent);                finish();            }        }        @Override        public void onAnimationRepeat(Animation animation) {            // TODO Auto-generated method stub        }    }

用到的知识点:

  • 安卓动画Animation
  • Java 弱引用WeakReference
  • Java 反射

适用平台:Andorid
支持工具:
1. Eclipse
2. Android Studio
3. Unity
最大支持闪屏数量:5

关于使用:

在Eclipse中使用:

引用Libarbry工程:SplashUtilsLibrary
引用Library工程

设置启动Activity:

将manifest xml文件中的启动入口注释,如图,或者设置为Library工程的Splash为主Activity.

这里写图片描述

在Android Studio中使用:

导入Module SplashUtilsLibrary:
File>New>Import New Moudle ,选择SplashUtilsLibrary工程即可
导入Moudle
并在gradle里进行引用:
引用Library Moudle
设置启动Activity,设置方式和Eclipse中一致.

在Unity中使用:

导入资源:

Res目录: 对应unity目录:plugins/Android/res

闪屏图片资源

将自定义的闪屏图片导入到Unity对应目录中:以sp格式命名

layout:

导入布局文件activity_splash1.xml到unity对应目录

在string.xml中添加以下配置:

<string name="main_activity">dy.cn.splashdemo.MainActivity</string><string name="splash_count">3</string>

修改splash_count的值即可修改闪屏数量,最大支持5张.

在AndroidManifest中添加配置:

<activity    android:name="cn.dy.jzcj.Splash"    android:screenOrientation="landscape">    <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.LAUNCHER" />        <category android:name="android.intent.category.LEANBACK_LAUNCHER" />    </intent-filter></activity><activity    android:name="com.unity3d.player.UnityPlayerActivity"    android:screenOrientation="landscape">    <meta-data        android:name="unityplayer.UnityActivity"        android:value="true" /></activity>

其中cn.dy.jzcj是包名,此包名需与工程 Bundle Identifier ,以及下面说到的jar包包名保持一致。
这里写图片描述

导入jar包:

在Eclipse中修改包名:

修改jar包包名

然后build project
拷贝bin目录下生成的jar包到unity 中plugins/Android/libs中

包名须与Unity工程包名保持一致。

自定义闪屏数量:

修改strings.xml中splash_count,并添加对应闪屏资源即可

更换闪屏资源:

Unity、Eclipse中更新drawable下对应图片资源即可,注意命名格式。
Android Studio中更新mipmap下对应图片资源即可。

自定义跳转Activity入口:

Android Studio、Eclipse中修改strings.xml中main_activity值为闪屏结束需要跳转的Activity,格式为:
包名+Activity名称
Unity中若由自定义闪屏直接跳到Unity程序,则main_activity固定为:com.unity3d.player.UnityPlayerActivity。
若自定义闪屏结束后需跳转到其他Activity,则设置和Eclipse、Android Studio中一致即可。

最后分享一些知识点吧:

可能有人会好奇了,为什么jar包包名,AndroidManifest中配置包名必须和Unity工程Bundle Identifier保持一致呢?
嗯,之前我尝试过jar包不修改包名,也就是和Unity Bundle Identifier无关的一些尝试,但是只有在一种情况下才会成功,那就是Unity中生成的资源Id和Android中资源Id完全一致的情况下,换种说法就是Unity中Plugins/Android/res目录和Android导出jar包完全一致。
总的来说,这其实是Android资源管理机制导致的必然结果,我们知道Android会为所有使用到的资源生成一个对应的资源Id,Eclipse中是./gen/R.java,AS中是./build/intermediates/class/debug/包名/R.class,如图:
R.java

我们可以看到资源id从0x7f020000开始,按照drawable 、id、layout、string、style的顺序向下生成。而Unity打包时,plugins/Android/res下或者ids,只要出现一个不对应,或多或少的资源,打包时重新生成的资源Id就和Eclipse中生成的不对应了。
为什么要说这个呢,Android打包后会为每个包名生成对应的目录,包含对应的资源及资源Id等,比如我们使用不一样的包名,下图为使用apktools解包后的包结构:

smail

可以看到不同包名映射生成的资源Id目录也不同,而我们使用的是Unity中的资源,所以应该保持jar包包名和Unity Bundle Identifier一致,这样在jar包和Unity就会处于同一目录下,jar代码中映射资源就可以正确获取到了。

这无疑是个比较蛋疼的地方,不修改包名还好,如果Unity中修改了包名,那我们就需要修改Eclipse工程包名重新导出jar包来用了,我也尝试过导出jar包时将R.java一起导出,但是还是前面说的,资源不对应会导致Id不一致,行不通,目前还是没有想到有什么好的解决方案,如果小伙伴们谁有更好的办法,请记得告诉我,感激不尽。。

end of:源码下载
http://pan.baidu.com/s/1dEX7NZr
密码:qpmn

原创粉丝点击