Android App开发超实用实例 | Activity
介绍Activity内各View间的关系,讲解不同Android版本设置全屏的方法。通过案例了解Activity的生命周期流转。
布局文件实现Android应用程序的界面设计,而Activity作为Android的应用组件,通过Java代码设计实现UI交互功能。一个App通常由一个或多个Activity组成。
01、系统状态栏、标题栏和导航栏
默认每个Activity的界面都会显示系统状态栏、标题栏和导航栏。对于某些应用,需要将以上三者部分或全部隐藏。如果要实现Activity调用时就不显示标题栏,最简单的办法是在AndroidManifest.xml文件的application或activity标签中加入以下代码: android:theme="@android:style/Theme.NoTitleBar"上述代码加在application标签中,表示所有的Activity都不显示标题栏。上述代码加在activity标签中,表示当前activity不显示标题栏。如果在上述节点位置加入:
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
代表相应的Activity不显示系统状态栏和标题栏。其他几种隐藏系统状态栏和标题栏的方法都是在Activity的Java文件中进行设置的。
Activity内各View间关系如图1所示。因此显示了Activity内各View的大致关系,具体逻辑关系可在Android Studio运行程序后选择Android Studio右下角的Layout Inspector选项卡,在弹出的界面中查看各个View之间的关系嵌套,如图2所示。每个Activity对应一个Window。DecorView是Window中的顶层视图,StatusBar是系统状态栏,ActionBar是标题栏,Navigation是导航栏,ContentView就是第8行setContentView()方法调入的布局文件形成的View。隐藏或显示系统状态栏、标题栏和导航栏就是对Activity中的相应View执行隐藏或显示操作。
■ 图1Activity内各View间关系
■ 图2用Layout Inspector查看各View间关系
如果去掉第7行的注释,当前Activity将不显示标题栏。此命令必须在第8行setContentView()方法之前,否则程序运行出错。加上之前介绍的隐藏标题栏的方法,如果再执行第24行或第28行的actionBar操作时会因标题栏设置冲突而出错。上述介绍的几种隐藏系统状态栏和标题栏的方法都无法在Activity启动以后再进行动态变更。
第10行的代码可放置在setContentView()方法前后任意位置(有些特殊属性需将此方法放在setContentView()方法前),通过getWindow()方法获取Window,然后用setFlags()方法设置标记来实现全屏效果。
第16~31行定义button1的单击监听器,通过第22行判断按钮文字内容来执行标题栏的显示或隐藏操作。第21行获取标题栏对象并赋予actionBar。第24行actionBar的show()方法用来显示标题栏,第28行的hide()方法用来隐藏标题栏。
第34行的getWindow()方法获取当前Activity对应的Window,getDecorView()方法获取当前Window包含的View。第43行和第44行效果是一样的,利用decorView实例的setSystemUiVisibility()方法设置UI的相关对象是否显示。
其中,常量的含义为:
(1) View.SYSTEM_UI_FLAG_VISIBLE:系统状态栏和导航栏都显示。
(2) View.SYSTEM_UI_FLAG_FULLSCREEN:显示界面变为全屏,此时不显示系统状态栏。
(3) SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏导航栏。
(4) View.SYSTEM_UI_FLAG_IMMERSIVE:设置为沉浸模式。 以上常量可以多个同时使用,中间用竖线“|”分隔。第48行如果去掉View.SYSTEM_UI_FLAG_IMMERSIVE,单击按钮隐藏系统状态栏和导航栏后再次单击屏幕,系统状态栏和导航栏又会再次显示。加入沉浸模式可以避免此类问题。 对于API 30的Android系统,引入了新的对象和命令,下列代码实现隐藏系统状态栏和导航栏。如果将hide()方法换成show()方法,则变为显示相关对象。
02、关闭Activity
可以通过关闭Activity来切换Activity或者关闭整个App。本案例在布局文件中添加了一个EditText和Button。当运行不同的关闭代码时,可以通过列表键对比退出效果。
每次运行程序时先修改文本输入框中的内容,然后再单击“退出”按钮,执行相应的关闭Activity命令。为了方便后续的讲解,术语“执行唤回”是指单击列表键,再单击程序列表中的HelloAndroid程序。修改文本输入框中内容的目的是对比执行唤回操作后文本输入框是否能保留关闭前的值。
执行第16行的finish()方法,单击列表键能看到HelloAndroid程序中的控件,执行唤回操作,文本输入框中的值还原为初始值。
第18行的onDestroy()方法在新版本中已无法关闭Activity。
执行第20行System.exit(0)代码退出后,单击列表键在运行程序列表中看不到控件,说明相关资源已被清除。执行唤回操作相当于重启HelloAndroid程序。
第22行开始的方法四是将系统桌面作为切换的intent来处理,等效于按Home键。所以程序列表中能看到控件,执行唤回操作后文本输入框中的内容也保持不变。相当于将后台的HelloAndroid程序切换回前台。
第26行的命令是在Android操作系统级执行杀死当前进程操作,因此退出后程序列表中看不到控件。
03、生命周期
在实际的App开发中,Activity往往不止一个。在多个Activity间切换时,存在相关控件是否还保留Activity切换前的值,或者是否需要刷新以获取新值的问题。在之前的案例中,控件的初始化赋值等代码都是放在onCreate()方法中的,而为了保证Activity切换以后程序能按正常逻辑运行,有些代码就需要放在Activity的其他方法中。Activity生命周期如图3所示。
■ 图3Activity生命周期
从图3可以看出,除了第一次启动Activity或者已启动的Activity资源被Android系统释放后重启会执行onCreate()方法外,其他如Activity被遮挡后重新回到前台显示、切换程序后Activity回到前台显示等情况都会跳过onCreate()方法,此时可能从onRestart()方法、onStart()方法或onResume()方法开始执行。因此可根据实际流程,将相关代码放在不同的方法中。为了便于理解,可以把Activity分成3个不同范围的生命周期。
(1) 完整生命周期:从onCreate()方法到onDestroy()方法。
(2) 可见生命周期:从onStart()方法到onStop()方法。顾名思义,是Activity从显现到消失的周期。如果当前Activity被其他View部分遮挡,当前Activity就还在可见生命周期内;如果是完全遮挡就退出可见生命周期。
(3) 前台生命周期:从onResume()方法到onPause()方法,此周期内的控件可见且可交互。只要当前Activity被其他View遮挡(不论是全部或部分遮挡)都退出前台生命周期。
为了验证Activity在生命周期的流转过程,案例中设计两个Activity,因篇幅限制,本书只列出了FirstActivity.java的代码,SecondActivity.java代码与其大同小异。程序重写了所有生命周期中的方法,两个Activity代码不同的地方是各个方法中使用Log.i()方法输出的内容,指明分别是由哪一个Activity的哪一个方法执行的
第58~70行的方法不属于生命周期的方法,onSaveInstanceState()方法主要在切换Activity、单击HOME键、开关电源键等情况时被调用。
onBackPressed()方法在单击返回键时被调用。 结合生命周期图,变更以下条件并切换Activity,观察调试信息的输出变化。
(1) 观察两个Activity切换时的状态变化。
(2) 观察单击HOME键并再次运行App的变化。
(3) 观察横竖屏切换的状态变化(新版本无变化)。
(4) 观察单击列表键后的变化。
(5) 观察单击返回键后的变化。
(6) 观察将SecondActivity变为Dialog主题后的变化(部分遮挡),可细分为单击按钮返回FirstActivity、单击FirstActivity区域返回和单击返回键3种情况。
(7) 观察添加finish()命令时的变化。
(8) 观察添加System.exit(0)命令时的变化。
(9) 观察开关电源键时的变化。
- 点赞
- 收藏
- 关注作者
评论(0)