3.3 编辑Splash活动

11 编辑Splash活动

通过向导完成了SplashActivity活动的创建,但到目前为止还什么都没做,我们希望这个活动能够使Splash界面停留6s后再进入主界面。下面分析一下活动代码,进入app/src/main/java文件夹并双击打开SplashActivity.java文件。

以上就是创建一个基本活动所需的全部代码。可以看到,这是一个继承了android.app.Activity的类,而且实现了一个onCreate()方法。所有活动都必须继承Activity类。Activity类包含一组方法,正是这组方法为Java类赋予了Android生命,把它从一个普通的Java类变成了一个功能完备的正式的Android活动。

另外所有活动都需要实现onCreate()方法。创建活动对象时会调用onCreate()方法,这个方法用来完成一些基本设置,如这个活动与哪个部件相关联。这要使用setContentView()方法来设置。在上面的示例中,setContentView(R.layout.activity_splash)告诉Android这个活动会使用activity_splash作为它的布局。

为实现Splash界面停留6s再进入主界面,需要为活动添加一些代码。下面更新SplashActivity.java。

第8行是新增代码,定义了一个Handler对象。Handler(消息处理器)是一个Android类,可以用来调度要在将来某个时刻运行的代码,还可以用它提交在不同线程中运行的代码。这里需要调出在6s后跳转的主界面。在goToMain()方法中,使用postDelayed()方法实现。

使用Handler时,可以把想要调度的代码包装在一个Runnable对象中,然后使用Handler的post()和postDelayed()方法指定希望这个代码在什么时候运行。

post()方法提交的代码需要尽可能快地运行(通常几乎是立即运行)。post()方法有一个参数,这是一个类型为Runnable的对象。Android里的Runnable对象与普通Java中的Runnable对象很相似,就是要运行的一个作业。可以把想要运行的代码放在Runnable对象的run()方法中,Handler会确保这个代码尽可能快地运行。具体方法如下。

postDelayed()方法的工作与Post()方法类似,不过这个方法用来提交将来运行的代码。postDelayed()方法有两个参数,一个是Runnable对象,另一个是long。运行的代码包含在Run()方法中。long参数指定了希望代码延迟多少毫秒运行,在这个延时后,代码会尽可能快地运行。具体方法如下。

这里使用了postDelayed()方法,long=6000(即6s)。

在run()方法中有两行代码,实现了跳转的功能。

需要让一个活动启动另一个活动,需要使用一个意图(Intent)。可以把Intent看成是一个“想要做某事情的意图”。这个消息类型允许你在运行时把单独的对象(如活动)绑定在一起。如果一个活动想要启动第二个活动,可以向Android发送一个意图。Android会启动第二个活动,并传入意图。只需几行代码就可以创建和发送一个意图。首先创建如下的意图。

第一个参数告诉Android这个活动来自哪个对象,可以用this表示当前活动。第二个参数是接收了这个意图的活动的类名。创建意图后,把它传入Android,代码如下。

这会告诉Android要启动这个意图指定的活动。Android接收到这个意图后,会监测是否一切正常,并要求这个活动启动;如果无法找到这个活动,它会抛出一个ActivityNotFoundException异常。

本例中简单介绍了消息处理器(Handler)和意图(Intent),在后面我们还会遇到并详细介绍。

需要更新AndroidManifest.xml文件,将应用最先启动活动设置为SplashActivity,如下所示。

第3行中android.intent.action.MAIN决定应用的入口Activity,也就是启动应用时首先显示哪一个Activity。

第4行中android.intent.category.LAUNCHER表示Activity应该被列入系统的启动器(Launcher),允许用户启动它。Launcher是Android系统中的桌面启动器,是桌面UI的统称。

运行这个应用可以看到如图3-7所示的结果。

图3-7 界面跳转

一般Splash界面右上角还会显示延时“xs”的描述和“跳过”,用户可以单击“跳过”直接进入主界面,而不需要等待。这需要在布局文件中增加两个TextVeiw组件。

12 添加延时计时和取消

第5、13行中,android:layout_alignParentRight的作用是把视图与父视图右对齐。

第6、14行中,android:layout_marginTop的作用是设置在视图上方额外增加的空间,单位是dp。dp是设备(密度)无关像素(density-independent pixels,dp),有些设备使用非常小的像素,能创建高清晰的图像。另外一些设备则比较廉价,因为这些设备的像素比较少,也比较大。通过使用设备(密度)无关像素,可以避免所创建的界面在某些设备上太小而在另外一些设备上又过大。如果按设备无关像素来度量,那么在所有设备上大小都几乎相同。

第7、15行中,android:layout_marginRight的作用是设置在视图右边额外增加的空间,单位也是dp,一般这些图像单位都使用dp,如果是设置文字大小,则使用sp单位。

第17行中,android:onClick="onClickCancel"指定该文本视图被单击后要调用的方法名称为onClickCancel。当用户单击“取消”时,调用活动SplashActivity中的onClickCancel()方法,通过这个方法实现跳过功能,直接进入主界面。

现在布局知道了要调用活动中的哪个方法,接下来要在活动中编写这个方法,同时还要对goToMain()方法进行修改。

第9行定义了整型变量seconds,记录定时剩余秒数,初始值为6。

第10行定义了布尔变量skipping,是判断是否“取消”的依据。

第35~37行定义了onClickCancel()方法。这个方法的形式为“public void onClickCancel (View view)”,如果未采用这种形式,用户单击“取消”时,这个方法不会有任何响应。这是因为在后台Android会查找一个有void返回值的公共方法,而且方法名要与布局XML中指定的方法匹配。

方法中的View参数看起来很奇怪,不过这个参数的存在是有道理的。这个参数指示触发这个方法的GUI组件(在这里就是文本视图)。文本视图(TextView)是View的一种。

定义该方法要使用View,所以在第6行导入了这个类。当用户单击“取消”时,Android调用该方法,将skipping设为ture,在goToMain()方法中可以判断skipping的值来决定是否跳过延时。

第19行定义了一个TextView的对象,我们用一个名为findViewById()的方法得到这个GUI组件的句柄。findViewById()方法取GUI组件的id作为参数,返回一个View对象,然后把这个返回值转换为正确的GUI组件类型(TextView)。在代码中:

使用findViewById()得到了id为tv_count的文本视图的一个应用。仔细查看如何指定文本视图的ID,这里并不是传入文本视图的名字,而是传入了一个形如R.id.tv_count的ID,这到底是什么意思呢?什么是R?

R.java是一个特殊的Java文件,只要创建或构建应用,Android工具就会生成这个文件。它位于工程app/build/generated/source/debug文件夹下的一个包中,这个包与应用包同名。Android使用R跟踪应用中使用的资源,它有很多作用,如允许在活动代码中得到GUI组件的引用。

如果打开R.java,可以看到其中包含一系列内部类,分别对应不同类型的资源。可以在内部类中引用各种类型的资源。例如,R中有一个名为id的内部类,这个内部类包含一个static final tv_count。利用代码(TextView)findViewById(R.id.tv_count),可以由这个值得到tv_count文本视图的引用。

第20~33行使用Handler的post()方法提交代码。

第23行定义了String类型的变量time(秒数值),通过seconds转换而来。

第24行文本视图对象timeView调用setText()方法,设置该文本视图的文本为time(秒数值)。

第25行判断当前延时的秒数值是否为0,或者用户是否单击了“取消”使得skipping的值为true,只要两个条件满足其一,就跳转到活动MainActivity。

第29、30行中,如果前面两个情况都没出现,则seconds减1,并且使用Handler的postDelayed()方法提交代码,1s后继续执行Run()方法。

运行这个应用可以看到如图3-8所示的结果。

图3-8 界面延时跳转