Activityを扱う
Activityを追加する
最小単位で必要な作業は以下2つ。
AppComatActivity
を継承したクラスを新規作成する。AndroidManifest.xml
に定義を追加する。
Activityクラスの新規作成
AppComatActivity
を継承したクラスを追加する。
例えば、CustomActivity
を実装する。
実装はどこでも問題ないが、Activityであれば専用のファイル(CustomActivity.kt
)を作成するのが自然。
class CustomActivity : AppCompatActivity() {
}
AndroidManifest.xmlに定義の追加
前項で実装したCustomActivity
の定義をAndroidManifest.xml
に追加する。
定義は<application>
タグ内に追加する。
<application
...
...>
<activity android:name="com.mkt120.sampleapplication.CustomActivity" />
</application>
新規プロジェクトを作成すると、MainActivity
がすでに定義されているので、それを参考にすると良い。
Activityを開始する
startActivity
を使う。
例えばボタンをタップした時に、1つめの画面(MainActivity
)から2つめの画面(CustomActivity
)を開始する場合は以下。
findViewById<View>(R.id.button_start_activity).setOnClickListener {
val intent = Intent(context, CustomActivity::class.java)
startActivity(intent)
}
Activityを開始し、その結果を受け取る
ActivityResultLauncher.launch
を使う。
2つめのActivity
の処理結果を1つめのActivity
で受け取りたい場合、startActivity
で開始すると結果を受け取ることができない。
ActivityResultLauncher.launch
を使ってActivity
を開始し、2つめのActivity
の処理結果を受け取る処理を実装しておく。
例えば2つめの画面として、CustomActivity
を以下のように実装する。
class CustomActivity : AppCompatActivity() {
companion object {
const val EXTRA_RESULT_DATA = "extra_result_data"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_startactivity_custom)
val button1 = findViewById<Button>(R.id.button_1)
button1.setOnClickListener {
// 処理結果をintentに設定してActivityを終了する
val data = Intent().apply {
putExtra(EXTRA_RESULT_DATA, button1.text.toString())
}
setResult(RESULT_OK, data)
finish()
}
val button2 = findViewById<Button>(R.id.button_2)
button2.setOnClickListener {
// 処理結果をintentに設定してActivityを終了する
val data = Intent().apply {
putExtra(EXTRA_RESULT_DATA, button2.text.toString())
}
setResult(RESULT_OK, data)
finish()
}
}
}
res/activity_startactivity_custon.xml
として以下を追加する。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_1"
android:layout_width="wrap_content"
android:text="ボタン1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button_2"
android:layout_width="wrap_content"
android:text="ボタン2"
android:layout_height="wrap_content"/>
</LinearLayout>
1つ目の画面でCustomActivity
を開始するため、ActivityResultLauncher
を生成する。
ActivityResultLauncher
はregisterForActivityResult
を利用する。
private val activityResultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
if (result.resultCode != RESULT_OK) {
// キャンセルされた
return@registerForActivityResult
}
val data = result.data?.getStringExtra(CustomActivity.EXTRA_RESULT_DATA)
val textView = findViewById<TextView>(R.id.text_view_result)
textView.text = "$data:がタップされました"
}
生成したActivityResultLauncher
でCustomActivity
を開始する。
findViewById<View>(R.id.button_register_activity_for_result).setOnClickListener {
val intent = Intent(context, CustomActivity::class.java)
activityResultLauncher.launch(intent)
}
補足:startActivityForResultについて
startActivityForResult
はActivityResultLauncher
が追加される前に利用されていた機能で、現在はdeprecated(非推奨)となっている。
参考
- Activity | API reference | Android Developers
- ActivityResultCaller | API reference | Android Developers
Activityを透明にする
AndroidManifest.xml
でそのActivity
にテーマを適用する。
styles.xml
で透明なActivity
用のテーマを定義する。
<style name="TransparentActivityTheme" parent="AppTheme.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
追加したテーマを適用することで、そのActivity
を透明にできる。
<activity
android:name="com.sample.application.TransparentActivity"
android:theme="@style/TransparentActivityTheme"/>
注意点:orientation
を指定するとクラッシュする
透明なActivity
の利用時には重要な注意点がある。
AndroidManifest.xml
でandroid:screenOrientation
を指定したり、プログラムで画面の向き(orientation
)を設定すると、アプリがクラッシュする。
これは透明なActivity
が親のActivity
の向きに依存する仕様があるため。
透明なActivity
を使用する際は、画面の向きに関する設定を行わないこと。
参考
Activityをダイアログのように表示する
1. 最小限の設定
Activity
をダイアログのように見せるには、AndroidManifest.xml
で対象のActivity
に以下のテーマを設定するだけです。
android:theme="@style/Theme.MaterialComponents.DayNight.Dialog"
これはDialogFragment
で使われるスタイルで、画面が浮き上がった見た目となる設定。
これをActivity
に設定することでをダイアログのような見せ方を手軽に実現できる。
ただし見た目がかわるだけなので、ダイアログの挙動(ボタンや入力フィールドなど)は、レイアウト側で別途実装する必要がある。
2. カスタマイズする場合
アプリ全体で統一感のあるダイアログにしたい場合は、基本のテーマを継承してカスタマイズするのがよい。
Theme.MaterialComponents.DayNight.Dialog
は、ダイアログのような表示を実現するために複数の属性を内部的に設定しています。主な属性は以下の通りです。
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowBackground">@drawable/abc_dialog_material_background</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@style/Animation.AppCompat.Dialog</item>
これらの属性をアプリの共通テーマを継承した独自のスタイルに設定することで、アプリのデザインに合わせたダイアログを実装できる。
補足
AndroidとしてはDialogFragment
の使用が推奨されているため、簡単な表示のみに留め
複雑なロジックや状態管理が必要な場合はDialogFragment
を利用した方が良い。
Activityのスタックをクリアしたい
Intent#setFlag(int)
で Intent.FLAG_ACTIVITY_CLEAR_TOP
をセットする。
fun showTop(View view) {
let intent = Intent(getApplication(), MainActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent);
}
起動したActivityを全て終了したい
Activity#finishAffinity()
を使う。
参考
共通ボタンとして外部に通知する。
外部の共通ボタンが押されたことを検知したい
実装手順
- AndroidManifest.xmlに宣言を追加
- 通知を受け取った時の処理を実装
- 共有ボタンによるデータ送信のintentを受け取る宣言を明記し
1. AndroidManifest.xmlに宣言を追加
例えば共有ボタンが押された時に MainActivity
を起動したいとき、<intent-filter>
に以下を追加する。
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
2. 通知を受け取った時の処理を実装
メンバ変数として持っているintentに共有情報として値が保持されているので Intent.EXTRA_TEXT
をキーに参照する。
override fun onCreate(savedInstanceState: Bundle?) {
if (intent?.action == Intent.ACTION_SEND) {
val text = intent.getStringExtra(Intent.EXTRA_TEXT)
// 良しなにする
}
}
共有ボタンを実装したい
共有したいデータを詰めたintent
をIntent#createChooser
に渡して、返されたintentをstartActivityする。
val temp: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "テストのテキストです")
type = "text/plain"
}
startActivity(Intent.createChooser(temp, null))
最終更新: NaN.NaN.NaN