Activity
除了可以跟使用者互動以外,也可以跟其他的 Activity
互動。我們今天就來介紹一下 Activity
之間如何呼叫。
還記得我們在 Hello world 之專案結構 的時候,有特別提到 AndroidManifest.xml
會是一個很重要的檔案嗎?我們打開後會看到以下的 xml 結構。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
裡面包含著很多關於 app 的重要資訊,包含 package name、app icon、app name 等。
AndroidManifest.xml
也支援按著 ⌘ 點擊可以跳到目標檔案,無論是@mipmap/ic_launcher
、@string/app_name
、@style/AppTheme
或是.MainActivity
大家都可以試試看。
除此之外我們也發現我們的 Activity
也被記錄在這個檔案裡。我們單獨來看這個區塊:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Activity
,由 .
開頭的名稱其實是省略了 package name 後的縮寫。完整的路徑就是 com.example.myapplication.MainActivity
也就是我們專案目前唯一的 Activity
。intent-filter
是我們跟系統註明我們的 Activity
可以接收哪些 Intent
的一種方式。<action android:name="android.intent.action.MAIN" />
指的是這是我們主要進入點,而 <category android:name="android.intent.category.LAUNCHER" />
代表我們這個 app 會出現在 LAUNCHER 列表裡。Intent
是 Android 的一個 class,用來啟動 Activity
或 Service
等的 components。作為一個一般化的介面,提供了諸如 setAction
、setType
、setClass
等參數的設定來表示呼叫 component 的種類,系統會依據我們所附帶參數來匹配適合的對象。依據你提供的參數匹配的對象可能不只一個或是根本沒有結果,而如果有多個 Activity
可以接收這個 Intent
則會跳出一個列表讓使用者自行選擇。
使用方式如下:
val intent = Intent(this, AnotherActivity::class.java)
startActivity(intent)
我們這邊是直接指定接收的 class,所以只有 AnotherActivity
可以接收,這種方式叫做 explicit intent。由於我們必須拿的到對方 class 的 reference,基本上這種呼叫要在同個 app 內才能使用。
但 Android 也支援(並且鼓勵)跨 app 間 Activity
的合作,我們並不確定具體有哪些 Activity
會接收到我們的 Intent
,但其實我們也只關心所要完成的任務是否有被良好的解決。
舉例來說如果我們 app 有個功能希望可以把一段文字分享出去,我們並不清楚使用者手機上有多少種可以分享訊息的 app,但我們還是可以使用標準的方式把 Intent
拋出來讓使用者選擇他們想要用什麼方式做分享。以下就是分享文字的範例:
val sendIntent = Intent(ACTION_SEND)
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)
原理介紹完了,我們一起把 helloworld 改成二個 Activity
吧,首先建立一個新的 SecondActivity
在我們的 com.example.myapplication
目錄下。
可以在 package 上按右鍵會有清單可以選,New -> Kotlin File/Class 然後輸入 file name 即可。
你也可以使用內建的 template New -> Activity 會有一系列可以使用的範例,如果很常重複這個動作的話也可以建立你自己的 template。
檔案內容如下:
package com.example.myapplication
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
}
}
還有二個地方要修改,一個是我們並沒有 activity_second
這個 layout,ㄧ樣可以在 layout 這個 folder 按右鍵選,New -> Layout resource file,輸入 file name 跟 Root element(有自動完成)即可,加上一個 TextView
設定不同的內容來識別:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="It's second page"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
我們也必須把 SecondActivity
加到 AndroidManifest.xml
的 application
tag 裡,系統才知道我們有一個新的 Activity
可以使用,修改內容如下:
<application
......>
<activity android:name=".MainActivity">
......
</activity>
<activity android:name=".SecondActivity"></activity>
</application>
最後回到 MainActivity
在 OnClickListener
的 onClick
裡加上呼叫 SecondActivity
的 code 如下:
myTextView.setOnClickListener {
startActivity(Intent(this, SecondActivity::class.java))
}
這樣就大功告成囉,記得跑在手機或模擬器試試看,如果大家有遇到什麼問題也歡迎留言囉,明天見。
Android 十全大補已經正式出書上架囉!
有興趣的讀者歡迎參考:
https://www.tenlong.com.tw/products/9789864345786