端末を縦表示しているところから横表示にするとアプリが初期化されて最初からスタートしてしまいます。これはライフサイクルを見るとわかります。
これを回避するには、画面を回転させない 、あるいは回転しても初期化されないようにすることができます。
2021.1.1
画面回転
ActivityのLife Cycleは下のようなフローになっています。この流れは重要で、これを理解しないでアプリを作っていると困ることになります。
Reference: Activity | Android Developers
ライフサイクルテスト
実際に初期化されている状況を見てみます。
ユーザーが「画面の自動回転」を許可の設定をしていることが前提です。
ActivityのLife Cycleに合わせてログを出すために、このように記述します。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package your.package.name; //AndroidX import androidx.appcompat.app.AppCompatActivity; //import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("debug","onCreate()"); } @Override protected void onStart() { super.onStart(); Log.d("debug","onStart()"); } @Override protected void onRestart() { super.onRestart(); Log.d("debug","onRestart()"); } @Override protected void onResume() { super.onResume(); Log.d("debug","onResume()"); } @Override protected void onPause() { super.onPause(); Log.d("debug","onPause()"); } @Override protected void onStop() { super.onStop(); Log.d("debug","onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.d("debug","onDestroy()"); } } |
起動させるとこうなります。onCreate()から始まり、onResume()でアプリ実行状態になっています。
1 2 3 |
06-28 14:03:04.235 13876-13876/com.example.testorientation D/debug: onCreate() 06-28 14:03:04.244 13876-13876/com.example.testorientation D/debug: onStart() 06-28 14:03:04.244 13876-13876/com.example.testorientation D/debug: onResume() |
その後、バックキーでアプリを終了させると、
1 2 |
06-28 14:03:18.053 13876-13876/com.example.testorientation D/debug: onPause() 06-28 14:03:18.145 13876-13876/com.example.testorientation D/debug: onStop() |
onDestroy()が呼ばれません(以前はこれで呼ばれていましたが)
次のいずれかの理由でシステムによって呼び出されます。
- アクティビティが終了する(ユーザーがアクティビティを完全に閉じるか、アクティビティに対して finish() が呼び出さたことによる)。
- 構成の変更(デバイスの向きの変更やマルチウィンドウ モードなど)に伴いアクティビティが一時的に破棄される。
画面を回転させるとonDestroy()が呼ばれます。
1 2 3 4 5 6 7 8 9 |
06-28 14:06:27.420 16839-16839/com.example.testorientation D/debug: onCreate() 06-28 14:06:27.436 16839-16839/com.example.testorientation D/debug: onStart() 06-28 14:06:27.437 16839-16839/com.example.testorientation D/debug: onResume() 06-28 14:06:31.625 16839-16839/com.example.testorientation D/debug: onPause() 06-28 14:06:31.626 16839-16839/com.example.testorientation D/debug: onStop() 06-28 14:06:31.626 16839-16839/com.example.testorientation D/debug: onDestroy() 06-28 14:06:31.833 16839-16839/com.example.testorientation D/debug: onCreate() 06-28 14:06:31.835 16839-16839/com.example.testorientation D/debug: onStart() 06-28 14:06:31.835 16839-16839/com.example.testorientation D/debug: onResume() |
ログからは一旦onDestroy()が呼ばれています。つまりアプリが終了して、その後onCreate()となり再起動しているのがわかります。
これによりアプリが再起動してしまい、それまでやっていた作業がリセットされて困ることがあります。それを見越してパラメータを保存させておくこともありますが、再起動させないという方法もあるでしょう。
configChanges
API Level 13以上のケースですが、このコードをAndroidManifest.xmlに追加します。
1 |
android:configChanges="orientation|screenSize" |
これで、画面を回転されると
1 2 3 |
06-28 14:18:44.189 27421-27421/com.example.testorientation D/debug: onCreate() 06-28 14:18:44.190 27421-27421/com.example.testorientation D/debug: onStart() 06-28 14:18:44.190 27421-27421/com.example.testorientation D/debug: onResume() |
アプリが終了せずそのままになっていることがわかります。
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... <application ... > <activity android:name=".MainActivity" android:configChanges="orientation|screenSize"> ... </activity> </application> </manifest> |
一応レイアウトです
actiity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" android:background="#dfe" android:gravity="center" tools:context=".MainActivity"> <EditText android:background="#ced" android:layout_width="250dp" android:layout_height="wrap_content" android:textSize="40sp" android:gravity="center" android:hint="@string/hint" /> </LinearLayout> |
strings.xml
1 2 3 4 |
<resources> <string name="app_name">YourAppName</string> <string name="hint">input</string> </resources> |
ただし、このconfigChangesはconfigによるActivityの再生成を止めることで、縦画面から横に変わって変更してほしいものも変更されないという問題を含んでいるので万能ではありません。
screenOrientation
ここまできて何ですが、そもそも回転させなければリセットもないのではということで
回転させずに固定する方法です。
android:configChanges=”orientation|screenSize”
の代わりに以下の設定で、縦・横方向の画面固定ができます。
1 2 3 4 5 |
<!-- 縦方向 --> android:screenOrientation="portrait" <!-- 横方向 --> android:screenOrientation="landscape" |
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 |
... <activity android:name=".MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ... |
ダイナミックに状況に応じて縦画面、横画面にしたい場合はActivityに設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 縦画面 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //横画面 //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); ... } |
関連ページ:
- アプリの画面を遷移させる
- アプリの画面遷移とActivity間のデータ転送
- Activity Life Cycle と画面回転
References:
Activity | Android Developers
activity – Android Developers