アクティビティは、アンドロイド開発の基本であり、コンポーネントです。アクティビティとは、ユーザーが操作する画面をカプセル化したものです。アクティビティには通常、ユーザーが操作するコンポーネントが含まれています。これには、ボタン、リスト、エディットテキストなどがあります。しかし、アクティビティには独自のライフサイクルがあり、ライフサイクル・メソッドを通じてアクティビティが発するイベントをリッスンすることができます。
このチュートリアルでは、このようなイベントが発生したときに何かを行うコードを書くことで、ライフサイクル・メソッドを実践的に学びます。
(a). Kotlinでアクティビティのライフサイクルメソッドを一覧表示するアプリを作る
この例では、これらのメソッドとの基本的なやりとりを学びます。このようなイベントが発生したときに、簡単なトーストメッセージを表示します。
アンドロイドスタジオとKotlinを使用します。
ステップ 1: 依存関係
このプロジェクトに必要な依存関係はありません。
ステップ 2: Kotlin コード
まず、MaiActivity.kt
というファイルを作成します。
MainActivity.ktを作成します。
次にimportを追加します。
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.StringBuilder
次にAppCompatActivityを拡張します。
class MainActivity : AppCompatActivity() {
//
オーバーライドする最初のライフサイクルメソッドは、onCreate()
です。これは、アクティビティが最初に作成されたときに発生します。ここでは、xmlレイアウトを膨らませます。そして、テキストビルダーにテキストを追加します。そして、そのテキストをテキストビューに表示します。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sb.append("\n onCreate Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onCreate Called")
}
次に、onStart()
をオーバーライドします。これは、アクティビティが開始され、使用できるようになったときに発生します。
override fun onStart() {
super.onStart()
sb.append("\n onStart Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onStart Called")
}
といった具合になります。
これが全コードです。
package info.camposha.activitylifecycle
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.StringBuilder
class MainActivity : AppCompatActivity() {
val sb: StringBuilder = StringBuilder()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sb.append("\n onCreate Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onCreate Called")
}
override fun onStart() {
super.onStart()
sb.append("\n onStart Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onStart Called")
}
override fun onResume() {
super.onResume()
sb.append("\n onResume Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onResume Called")
}
override fun onPause() {
super.onPause()
sb.append("\n onPause Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onPause Called")
}
override fun onStop() {
super.onStop()
sb.append("\n onStop Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onStop Called")
}
override fun onDestroy() {
super.onDestroy()
sb.append("\n onDestroy Called")
tv.text = sb.toString()
Log.d("ACTIVITY_LIFECYCLE", "onDestroy Called")
}
}
Step 3: Layouts
activity_main.xmlを作成します。
メインアクティビティのレイアウトで重要なのは、ライフサイクルメソッドが発生したときにそれを表示するテキストビューを用意することです。
<?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:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text=""
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ステップ4: 実行
プロジェクトを実行します。
画面構成の変更
この作品では、アンドロイド端末の設定変更に関連するアンドロイドのソリューションを見ていきます。
ここでは、アンドロイドの公式ドキュメントに沿って、設定変更の取り扱いについて簡単に説明します。
一部のデバイスの設定は、ランタイム中に変更される可能性があります(画面の向き、キーボードの有無、ユーザーがマルチウィンドウモードを有効にした場合など)。このような変更が発生すると、Androidは実行中のActivity
を再起動します(onDestroy()
が呼ばれ、続いてonCreate()
)。リスタートの動作は、新しいデバイス構成にマッチした代替リソースでアプリケーションを自動的にリロードすることで、アプリケーションが新しい構成に適応できるように設計されています。
リスタートを適切に処理するためには、アクティビティが以前の状態を復元することが重要です。onSaveInstanceState()](https://developer.android.com/reference/android/app/Activity#onsaveinstancestate)、[
ViewModel`](https://developer.android.com/reference/androidx/lifecycle/ViewModel)オブジェクトと永続的なストレージを組み合わせて、構成の変更に関わらずアクティビティのUI状態を保存・復元することができます。詳しくは[こちら](https://developer.android.com/guide/topics/resources/runtime-changes)をご覧ください。
アンドロイドで設定変更をリッスンするには?
Step 1 - androidのマニフェストでconfigChangesプロパティを指定する。
このようにします。
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
このコードでは、画面の向きの変更とキーボードの有無の変更の両方を処理するアクティビティを宣言しています。
- orientation」の値は、画面の向きが変わったときの再起動を防ぎます。
- screenSize "値は、画面の向きが変わったときの再起動を防ぎますが、Android 3.2(APIレベル13)以上の場合に限ります。
- screenLayout "値は、折りたたみ式の携帯電話や変換可能なChromebookなどのデバイスによって引き起こされる変化を検出するために必要です。
- keyboardHidden」の値は、キーボードの使用状況が変化した場合の再起動を防ぎます。
Step 2: onConfigurationChangedメソッドをオーバーライドする
このようにします。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int newOrientation = newConfig.orientation;
if (newOrientation == Configuration.ORIENTATION_LANDSCAPE) {
// show("Landscape");
} else if (newOrientation == Configuration.ORIENTATION_PORTRAIT){
// show("Portrait");
}
}
または、switch文を使います。
int orientation=newConfig.orientation;
switch(orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
//to do something
break;
case Configuration.ORIENTATION_PORTRAIT:
//to do something
break;
}
Kotlinでは
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks the orientation of the screen
if (newConfig.orientation === Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show()
} else if (newConfig.orientation === Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show()
}
}
なお、実装コードを書く前に、
super.onConfigurationChanged(newConfig);
を追加しないと、例外が発生する可能性があります。
観測結果
以下のような場合、onConfigurationCalled()が呼び出されないことがあります。
*1.XMLでレイアウトをランドスケープに設定している**。
android:screenOrientation="landscape"
2. setRequestedOrientationを手動で呼び出す。
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
3. android:screenOrientation
と android:configChanges
の両方が指定されている。
例 - 画面の向きの変更を処理する方法
アンドロイドアクティビティの設定変更を監視し、画面が縦に回転しているか横に回転しているかに応じてトーストメッセージを表示する簡単な例を作ってみましょう。
ステップ1- レイアウトの作成
xmlレイアウトに以下のコードを追加します。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
ステップ2: MainActivity.java
続いて、メインアクティビティに以下のコードを追加します。
package com.example.screenorientation;
import android.os.Bundle;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
onConfigurationChanged(new Configuration());
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
{
Toast.makeText(getApplicationContext(), "portrait", Toast.LENGTH_SHORT).show();
System.out.println("portrait");
}
else if (getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(getApplicationContext(), "landscape", Toast.LENGTH_SHORT).show();
System.out.println("landscape");
}
else
{
Toast.makeText(getApplicationContext(), "none", Toast.LENGTH_SHORT).show();
System.out.println("none");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
以上で完成です。