Android Studio 学习-第三章 Activity 第二组

事先申明:所有android 类型的学习记录全部基于《第一行代码 Android》第三版,在此感谢郭霖老师的书籍帮助。

1.注册activity

在第一组中,我创建了一个activity,并且编辑布局后加载显示了一个按钮,但实际上每一个activity都要先注册才生效,第一组中的activity实际上已经自动注册过了,打开app/sec/main/AndroidManifest.xml,其中注册的代码如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.ActivityTest"
tools:targetApi="31">
<activity
android:name=".FirstActivity"
android:exported="false"
android:label="@string/title_activity_first"
android:theme="@style/Theme.ActivityTest.NoActionBar" >
</activity>
</application>

</manifest>

 

   其中activity的注册声明要放在application中,使用activity进行注册,android:name制定了注册的acticity,android:exported默认为false,但假如想让此activity作为主activity则需要将其设置为true,这一项的意义为是否能被其他应用程序组件调用或跟它交互,android:label指定activity中标题栏的内容,注意如果不将下一项android:theme删除,是不显示标题栏的自然也就不显示android:label设定的内容了,android:theme是选择主题,我认为如此,之后应该会有所涉及。

   因为不设置android的主activity,程序就不能运行,因为程序不知道将哪个activity作为要显示的东西,即使只有一个activiy,所以我们开始设置android的主要activity,第一步,需要在<activity>这个标签中加入<intent-filter>标签,第二步在<intent-filter>标签中加入以下代码、

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>

   这两句代码在我的理解中诠释了将此activity作为主activity启动的目的,第一句中action标签的意味着结果和方向,android.intent.action.MAIN则是意味著将这个activity作为主要activity使用的结果,第二个则是达成结果的方式,如何向这个方向前进,即category中的 android.intent.category.LAUNCHER  ,使用app的launcher启动器来启动.

   除此之外还需要修改activity标签本身的内容,实际完成的代码如下,

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.ActivityTest"
tools:targetApi="31">
<activity
android:name=".FirstActivity"
android:exported="true"
android:label="the first activity"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

   之前也讲了android:exported应该为true,允许将此activity作为主要的activity,其次给android:label设定想设置的标题内容,此处与原书有点出入,可能是版本原因,所以我以实际版本为主,还有android:theme我认为作为主题设置,导致标题栏不显示,我选择删除后恢复为书中所提。

2.TOAST的使用

  紧接1后,我学习toast这个提醒方式,它能够实现类似于弹出消息框的功能,这种弹出框是2s左右自己渐变消失的那种,不用手动操作,我觉得这个功能很好用,弹出错误信息或者提醒好用看起来又舒服。

  在第一组中完成的按钮只是一个空壳,按那个按钮什么都不会发生,正好作为出发toast的触发点,我们以按一下跳出一个提醒的方式开始编译,首先定义toast的触发点,即设置按钮为触发点,我们需要在firstactivity中的oncreate()中添加几行代码,如下

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout)
val button1:Button = findViewById(R.id.button1)
button1.setOnClickListener{
Toast.makeText(this,"you press button1",Toast.LENGTH_SHORT).show()
}

   紫色为添加的代码,我来解释他的意义,首先第一句代码是使用了findViewById获取布局中的元素,此处便是以res中id标识符为button1的元素,这里的标识符正好对应我们在设置按钮布局时填写的android:id中的@+id/ button1 ,但这个方法获取的元素是继承view的泛型对象,kotlin即使有自动推导的功能也无法推导它到底是什么,所以我们需要将其声明为Button类型,这就使用了val button1:Button,将button1变量声明成了Button类型。其次是第二,和三句代码,注册了setOnclickListener作为一个监听器,点击按钮就会执行监听器中的onclick()方法,而onclick中我们设置一个提醒,使用makeText创建一个Toast对象,传入三个参数,,第一个是Toast需要的content,即上下文(这里我觉得原文有些模糊,思考过后认为这里的上下文应该指的是在哪个activity弹出消息),而这个activity本身就是content对象,这里第一个参数就填入this,第二个参数的弹出显示的内容,根据你想弹出的文字自己填入,第三个参数就是弹出后提醒滞留的时间,有两个常量选择Toast.LENGTH_SHORT和Toast.LENGTH_LONG,根据尾部的short和long自行选择,最后在maketext()后加.show()让其显示出来。

   到此,按照现在版本的androidstudio来说,代码现在就是比较高效的了,在书中,androidstudio支持kotlin-android-extensions插件,是本来就支持的,根据此插件  val button1:Button = findViewById(R.id.button1)  这句代码可以去除,因为这个插件会根据布局文件定义的控件id即按钮的id button1创建一个同名字的变量,也就不需要findviewbyid这个方法了,但是,但是,但是,现在版本的androidstudio已经不自带kotlin-android-extensions插件了,据查询可以手动添加,我这里试验过发现没能成功就不演示了,如果之后成功会新发文章叙述。

3.在activity中使用Menu

    menu自然译为菜单,在一个app中有时需要菜单,但空间的原因,菜单直接出现会占据大量空间,android提供了解决方式,让菜单在需要的时候出现,不需要则占据极小空间,也就是熟悉的三个竖点。

   首先在res目录下建立menu文件夹,右键--》新增--》directory,打入menu,完成。接着在menu文件夹下右键--》新增--》Menu resource file,输入main作为文件名,点击ok。

   这样就获得了一个在res/menu文件夹下的名为main的文件.

   其次,在main文件中加入代码,完成的实际代码如下,

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>

 其中用两个<item>标签来创建具体的某一个菜单项,分别使用android:id给两个菜单项设置唯一的标识符,再使用android:title来给菜单项指定名称。

 接着返回FirstActivity文件,再其中来通过ctrl+o快捷键选择onCreateOptionsMenu来重写onCreateOptionsMenu()方法,添加如下代码

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main,menu)
return true
}

   在解释这个代码前,我们要了解一个事,这个涉及到kotlin的代码糖。

   首先,java中有一个javaBean的概念,它是一个非常简单的JAVA类(本人实际只是略微了解java,对于这个例子理解不是很深,希望有人指点),会根据类中的字段自动生成相应的getter 和setter方法。如下所示:

            public class book{

                        private int pages;

                        public int getPages(){

                                   return pages;

                        }

                        public void setPages(int pages){

                                  this.pages = pages;

                        }

              }

   而在kotlin中我们可以以一种近似于js的方式编写这两个语法结构

                   val book =Book()

                  book.pages = 500

                   val bookPages = book.pages

   在这里看似没有使用setPages和getPages方法,但kotlin实际读取这段代码后会转换为调用setPages和getPages方法来实现book类的pages字段的设置和读取。

 

现在回到项目代码中,代码在下,

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main,menu)
return true
}

    这里同样也使用了kotlin语法糖,这里的menuInflater调用了父类的getMenuInflater()方法,来得到一个menuInflater对象,得到对象后使用inflate方法来创建菜单。

    inflate方法创建菜单需要两个参数,第一个是我们要依据那个资源文件创建菜单,这里自然就是res/menu/main文件夹,输入,R.menu.main,第二个是我们把这个创建的菜单给哪个menu对象安装上,这里便选择onCreateOptionsMenu    传入的menu,这里的menu传入可为空,输入,menu。

    之后还需要打return true,来表示允许将创建的菜单显示出来。 

    到此,创建菜单的第一阶段完成,我们成功的创建了一个有选项的菜单,但是只能展示,不能使用,因为我们没有定义菜单响应事件。

   我们在FirstActivity中重写onOptionItemSelected()方法,如下所示:

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.add_item -> Toast.makeText(this,"you click add",Toast.LENGTH_SHORT).show()
R.id.remove_item -> Toast.makeText(this,"you click remove",Toast.LENGTH_SHORT).show()
}
return true
}

仔细看你会发现我们使用之前说的语法糖,我指的是item.itemId这一句,我们调用这个item.itemId获取点击的是哪个菜单项,这里item.itemId本质上还是在背后调用了getItemid()方法,接下来when根据获得的item.itemId结果,来对应代码中的 R.id.add_item和 R.id.remove_item,并执行相应的逻辑,逻辑就是后面的toast提醒。

到此菜单的创建就完成了,菜单可以收起和放开,也可以点击有反应,如图;

 

 

 

 

 

//

 

posted @ 2023-03-28 22:46  aMadeus-mozart  阅读(47)  评论(1编辑  收藏  举报