Splash的实现

news/2024/7/5 4:56:32


什么是Splash

Splash也就是应用程序启动之前先启动一个画面,上面简单的介绍应用程序的厂商,厂商的LOGO,名称和版本等信息,多为一张图片,显示几秒钟后会自动消息,然后显示出应用程序的主体页面。在PC上,很常见各种平台的应用程序都会有,多半是一张图片显示在屏幕中央,如Microsoft Office系列,或者GIMP等。在各种游戏中Splash是最常见的,几乎所有的游戏开始都会有一张全屏的图片,上面通常都显示厂商的LOGO,游戏的名称等。在手机平板等移动设备上,类似PC的Splash很少,起码对于Android和iOS来讲原生的应用程序都没有这种Splash,但是不知从何时起,这种Splash开始在第三方应用中流行起来,几乎所有的第三方应用程序都有启动Splash。这些Splash的特点是占满整个屏幕,上面LOGO,厂商的名字,应用的名字版本等,大约3到5秒后,Splash自动消失,应用主页面显示出来。很多应用在Splash页面也显示加载过程。

下面谈谈在Android中如何实现Splash以及它的优缺点:

使用Activity作为Splash

这可能也是最常用的方式,方法就是用一个Activity,给它设置一个背景,或者要显示的信息(厂商,LOGO,名字和版本),让它显示几秒种,然后finish()掉,并启动应用主体Activity。

[html] view plain copy print ?
  1. <activity android:name=".SplashActivity"  
  2.           android:theme="@android:style/Theme.NoTitleBar.Fullscreen"  
  3.           android:noHistory="true"  
  4.           android:configChanges="orientation|keyboardHidden"  
  5.           android:label="@string/app_name">  
  6.     <intent-filter>  
  7.         <action android:name="android.intent.action.MAIN" />  
  8.         <category android:name="android.intent.category.LAUNCHER" />  
  9.     </intent-filter>  
  10. </activity>  
        <activity android:name=".SplashActivity"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:noHistory="true"
                  android:configChanges="orientation|keyboardHidden"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
[java] view plain copy print ?
  1. public class SplashActivity extends Activity {  
  2.     private Handler mMainHandler = new Handler() {  
  3.     @Override  
  4.     public void handleMessage(Message msg) {  
  5.         Intent intent = new Intent(Intent.ACTION_MAIN);  
  6.         intent.setClass(getApplication(), NotTomorrowActivity.class);  
  7.         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  8.         startActivity(intent);  
  9.         // overridePendingTransition must be called AFTER finish() or startActivity, or it won't work.  
  10.         overridePendingTransition(R.anim.activity_in, R.anim.splash_out);  
  11.     }  
  12.     };  
  13.       
  14.     @Override  
  15.     public void onCreate(Bundle icicle) {  
  16.     super.onCreate(icicle);  
  17.     getWindow().setBackgroundDrawableResource(R.drawable.kg);  
  18.     mMainHandler.sendEmptyMessageDelayed(05000);  
  19.     }  
  20.       
  21.     // much easier to handle key events  
  22.     @Override  
  23.     public void onBackPressed() {  
  24.     }  
  25. }  
public class SplashActivity extends Activity {
    private Handler mMainHandler = new Handler() {
	@Override
	public void handleMessage(Message msg) {
	    Intent intent = new Intent(Intent.ACTION_MAIN);
	    intent.setClass(getApplication(), NotTomorrowActivity.class);
	    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	    startActivity(intent);
	    // overridePendingTransition must be called AFTER finish() or startActivity, or it won't work.
	    overridePendingTransition(R.anim.activity_in, R.anim.splash_out);
	}
    };
    
    @Override
    public void onCreate(Bundle icicle) {
	super.onCreate(icicle);
	getWindow().setBackgroundDrawableResource(R.drawable.kg);
	mMainHandler.sendEmptyMessageDelayed(0, 5000);
    }
    
    // much easier to handle key events
    @Override
    public void onBackPressed() {
    }
}


使用Activity的优势在于:

  1. 容易控制KEY事件

    因为在显示Splash的时候,是不应该响应事件的,比如触摸事件,或者BACK或者MENU,因为这是一个单独的Activity,所以你可以很容易禁掉这些用户事件,而不必担忧影响其他逻辑,或者担心未及时把它们重新启用。

  2. 容易定制

    因为它是一个单独的Activity,所以你可以把它设置成全屏的,或者没有TitleBar的,或者其他什么样式与风格。在实际使用中,几乎所有的Splash都设置成了全屏。因为它是单独的Activity,所以即使你的应用不是全屏的,也没有关系,因为只把SplashActivity设置成了全屏不会对其他Activity产生影响。

  3. 逻辑与主体逻辑分开,容易维护

    如前面二点,因为它是一个单独的Activity,所有的Splash相关的逻辑都在其中,而与应用主体的Activity是分开的,所以Splash中的逻辑不会影响到其他的Activity,这也更容易修改和维护,因为不会绞在一起相互影响。

使用Activity的唯一缺点就是它无法利用Splash显示的时间里做数据加载。因为它是一个单独的Activity,无法控制其他的Activity,并且这时其他Activity还未创建。

使用ViewSwitcher作为Splash

这个也可以用作Splash。ViewSwitcher是一个ViewGroup,它有二个子View,每次只能显示其中一个。主要做法就是,Activity的RootView设置为ViewSwitcher,把一个布局(如ImageView)作为Splash作为ViewSwitcher的第一个子View;再把Activity的主体布局作为第二个子View;当Activity启动时,先显示作为Splash的ImageView,过几秒后再显示主体布局。事实上ViewSwitcher通常用在Activity需要加载数据,先显示一个进度条,当有数据时再显示真正的布局。

使用ViewSwitcher的优势

使用ViewSwitcher的优势就在于,你可以利用Splash的时间来进行数据的加载,这样用户就不必在等待了Splash之后,再等待数据加载。

[html] view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/view_container"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:inAnimation="@anim/activity_in"  
  7.     android:outAnimation="@anim/splash_out">  
  8.     <ImageView android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"  
  10.         android:src="@drawable/kg"  
  11.         android:scaleType="fitXY"/>  
  12.     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  13.         android:orientation="vertical"  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="fill_parent" >  
  16.         <TextView android:id="@+id/header"  
  17.             style="@style/header_text" />  
  18.         <TextView android:id="@+id/header_tip"  
  19.             style="@style/task_text" />  
  20.         <ListView android:id="@+id/task_list"  
  21.            android:layout_width="match_parent"  
  22.            android:layout_height="match_parent"  
  23.            android:footerDividersEnabled="true"   
  24.            android:background="@color/white"/>  
  25.     </LinearLayout>  
  26. </ViewSwitcher>  
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:inAnimation="@anim/activity_in"
    android:outAnimation="@anim/splash_out">
    <ImageView android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/kg"
        android:scaleType="fitXY"/>
	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:orientation="vertical"
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent" >
		<TextView android:id="@+id/header"
		    style="@style/header_text" />
	    <TextView android:id="@+id/header_tip"
	        style="@style/task_text" />
		<ListView android:id="@+id/task_list"
		   android:layout_width="match_parent"
		   android:layout_height="match_parent"
		   android:footerDividersEnabled="true" 
		   android:background="@color/white"/>
	</LinearLayout>
</ViewSwitcher>

[java] view plain copy print ?
  1. public class NotTomorrowActivity extends Activity {  
  2.     protected static final String TAG = "NoTomorrowActivity";  
  3.     protected static final int MSG_SHOW_LAYOUT = 10;  
  4.     private static final int MENU_ADD_TASK = 0;  
  5.     private Handler mMainHandler = new Handler() {  
  6.     @Override  
  7.     public void handleMessage(Message msg) {  
  8.         switch (msg.what) {  
  9.         case MSG_SHOW_LAYOUT:  
  10.         final ViewSwitcher container = (ViewSwitcher) findViewById(R.id.view_container);  
  11.         container.showNext();  
  12.         ImageView view = (ImageView) container.getChildAt(0);  
  13.         view.setImageResource(0);  
  14.         container.removeViewAt(0);  
  15.         mSplashing = false;  
  16.         break;  
  17.         default:  
  18.         break;  
  19.         }  
  20.     }  
  21.     };  
  22.     private boolean mSplashing;  
  23.   
  24.     @Override  
  25.     public void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         mSplashing = true;  
  28.         setContentView(R.layout.not_tomorrow_activity);  
  29.   
  30.         mMainHandler.sendEmptyMessageDelayed(MSG_SHOW_LAYOUT, 5000);     
  31.     }  
  32.   
  33.        @Override  
  34.     public void onBackPressed() {  
  35.     if (!mSplashing) {  
  36.         super.onBackPressed();  
  37.     }  
  38.     }  
  39.       
  40.     @Override  
  41.     public boolean onCreateOptionsMenu(Menu menu) {  
  42.     if (mSplashing) {  
  43.         return false;  
  44.     }  
  45.     menu.add(0, MENU_ADD_TASK, 0, R.string.add_hint);  
  46.     return super.onCreateOptionsMenu(menu);  
  47.     }  
  48.       
  49.     @Override  
  50.     public boolean onPrepareOptionsMenu(Menu menu) {  
  51.     if (mSplashing) {  
  52.         return false;  
  53.     }  
  54.     return super.onPrepareOptionsMenu(menu);  
  55.     }  
  56. }  
public class NotTomorrowActivity extends Activity {
    protected static final String TAG = "NoTomorrowActivity";
    protected static final int MSG_SHOW_LAYOUT = 10;
    private static final int MENU_ADD_TASK = 0;
    private Handler mMainHandler = new Handler() {
	@Override
	public void handleMessage(Message msg) {
	    switch (msg.what) {
	    case MSG_SHOW_LAYOUT:
		final ViewSwitcher container = (ViewSwitcher) findViewById(R.id.view_container);
		container.showNext();
		ImageView view = (ImageView) container.getChildAt(0);
		view.setImageResource(0);
		container.removeViewAt(0);
		mSplashing = false;
		break;
	    default:
		break;
	    }
	}
    };
    private boolean mSplashing;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSplashing = true;
        setContentView(R.layout.not_tomorrow_activity);

        mMainHandler.sendEmptyMessageDelayed(MSG_SHOW_LAYOUT, 5000);   
    }

       @Override
    public void onBackPressed() {
	if (!mSplashing) {
	    super.onBackPressed();
	}
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	if (mSplashing) {
	    return false;
	}
	menu.add(0, MENU_ADD_TASK, 0, R.string.add_hint);
	return super.onCreateOptionsMenu(menu);
    }
    
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
	if (mSplashing) {
	    return false;
	}
	return super.onPrepareOptionsMenu(menu);
    }
}


使用ViewSwitcher的缺点

  1. 要注意事件

    必须在显示Splash的时候禁止BACK,MENU等事件,然后再在Splash结束后把它们重新启用。

  2. 没办法全屏

    除非主体Activity是全屏的,否则没办法让View全屏,然后再设置回。

  3. 逻辑绞在一起,难维护

    就如上面的禁止和启用事件一样,这些东西都是在Activity中,所有的逻辑都在一个Activity中,自然难维护和修改,并且易出错。

推荐做法

推荐的做法是不使用Splash的,或者最多在应用程序安装后第一次使用,从用户角度来讲,它毫无意义,所以你看Android或iOS的原生应用中都没有Splash之类的东西。应该让应用直接进入正题,让用户立刻进到他最关心的页面。同样,应用使用提示也是无用的东西,真正的优秀的应该是简洁且操作,不用学就会的,而不是搞出一大堆教程或者提示。与其花时间精力搞Splash或使用提示,还不如想想如何简化操作。

以上为3.0之前的实现方式。



http://www.niftyadmin.cn/n/4606980.html

相关文章

Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的&#xff0c;大家跟着弄MAC搭建RTMP服务器https://www.jianshu.com/p/6fcec3b9d644这个是在windows上的&#xff0c;RTMP服务器搭建(crtmpserver和nginx) http…

基于PelicanDT实现dubbo断网验证

具体介绍 Dubbo-example&#xff0c;是基于PelicanDT实现dubbo环境准备&#xff0c;禁止端口网络访问&#xff0c;执行接口调用验证端口是否禁用示例 前期准备 本示例程序是基于阿里云ECS或远程Linux服务器完成&#xff0c;只需购买阿里云机器&#xff0c;或者选定已准备好的远…

Launcher解析

&#xfeff;&#xfeff;首先来说说我为什么写这篇文章&#xff0c;最近公司要我负责搞Launcher&#xff0c;网上一查这方面的资料比较少&#xff0c;并且不全&#xff0c;研究起来相当困难&#xff0c;所以就写了这篇文章&#xff0c;希望对大家有帮助。这篇文章是相当长的&a…

你遵守开源协议GPL/LGPL吗?

一款Linux 手机操作系统&#xff0c;至少要有40&#xff5e;50个开源项目的支援。这些开源项目拿来后如何用&#xff1f;直接修改&#xff0c;当然要修改。修改后如何发布&#xff1f;还是闭源算了&#xff01;这个问题我也考虑过&#xff0c;有时又不想考虑。 下面是网友的关于…

滴滴工程师带你深入理解 TCP 握手分手全过程

本文作者&#xff1a;饶全成&#xff0c;中科院计算所硕士&#xff0c;滴滴出行后端研发工程师。个人主页&#xff1a;https://zhihu.com/people/raoquancheng记得刚毕业找工作面试的时候&#xff0c;经常会被问到&#xff1a;你知道“3次握手&#xff0c;4次挥手”吗&#xff…

Linux手机开发中,尽量不要用多线程。

在Linux手机操作系统中&#xff0c;一般不提倡用多线程&#xff0c;为什么呢&#xff1f; 1 难调试&#xff1b; 2 难同步。 所以&#xff0c;一个进程中就搞一个线程。不要在进程中搞一堆线程&#xff0c;否则调试起来很痛苦。 不过也有一些比较特殊的程序&#xff0c;比如…

精辟的山寨。

有人为山寨机编了这么一段话&#xff1a; “一定得选最好的硬件芯片&#xff0c;雇法国设计师&#xff0c;做就得做最高档的手机&#xff1b; 平台直接用MTK&#xff0c;屏幕最小也得3.0的&#xff0c;什么智能呀、电视功能呀、双卡同时待机呀、能给他装的全给他装上&#xf…

Android4.0 Launcher拖拽原理分析(1)

&#xfeff;&#xfeff;Android4.0 Launcher拖拽原理分析&#xff08;一&#xff09;在Android4.0源码自带的Launcher中&#xff0c;拖拽是由DragController进行控制的。 基本流程是相应的View在检测到用户操作后进行判断&#xff0c;若可以触发拖拽&#xff0c;则设置自身的…