안드로이드는 세로 방향도 있지만, 가로 방향도 있다. 단말 방향이 바뀌게 되면 화면 비율이 변경되므로 화면이 다시 보이게 된다. 즉 다른 레이아웃을 보게 된다는 것이다. 이로 인해 단말 방향이 바뀌게 되면, 액티비티는 메모리에서 없어졌다가 다시 만들어진다.
우리가 기본적으로 res/layout의 폴더에는 세로 방향 액티비티 xml이 저장된다. 가로 방향 xml을 만들기 위해서는 res/layout-land라는 폴더를 만들어야 한다. 이 layout-land폴더 안에있는 xml파일이 단말이 가로방향으로 되었을때 우선적으로 적용되는 것이다.
정말 단말 방향이 바뀔때마다 액티비티를 메모리에서 없앴다가 다시 만들까?
우선 res 아래 layout_land라는 디렉토리를 만들고, layout폴더 안에있는 activity_main.xml파일을 layout_land디렉토리로 복사한다. layout폴더 의 xml파일에는 Vertical Text, layout-land폴더의 xml파일에는 Horizontal Text라고 표기한다. 그리고 MainActivity.java에 아래와 같이 코드를 작성한다. onStart,onCreate,onStop,onDestroy 메소드들은 화면 상태에 따라 시스템이 자동으로 호출해 주는 메소드인데, 이러한 메소드를 '생명주기 메소드' 라고 한다.
package com.example.orientation_event;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
// 밑에 오버라이드된 화면의 상태에 따라 시스템이 자동으로 호출해 주는 메소드들이다. 이러한 메소드를 Life Cycle 또는 생명주기 메소드 라고 부른다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* layout-land폴더 : layout폴더와 같은 역할을 하지만, 단말이 가로 방향으로 보일때는 layout-land폴더 안에 들어있는 XML 레이아웃 파일이 사용된다.
*
* */
showToast("onCreate() called");
}
@Override
protected void onStart() {
super.onStart();
showToast("onStart() called");
}
@Override
protected void onStop() {
super.onStop();
showToast("onStop() called");
}
@Override
protected void onDestroy() {
super.onDestroy();
showToast("onDestroy() called");
}
public void showToast(String data){
Toast.makeText(this, data,Toast.LENGTH_SHORT).show();
}
}
이 코드를 작성하고 실행 시킨 후 단말 혹은 에뮬레이터를 가로로 돌려보면 아래와 같은 순서로 Toast가 발생되는것을 볼 수 있다.
(실행) -> onCreate -> onStart -> (가로로 화면 전환) -> onStop -> onDestroy -> onCreate -> onStart
단말의 방향이 바뀌면서, 액티비티가 메모리에서 없어졌다가 새로 만들어 진다는 것은, 액티비티 안에 선언해 두었던 "변수값"이 사라진다는 의미이다. 그렇기 때문에 이를 저장했다가 복원하는 방법이 있어야 한다.
액티비티 변수 보존하기
이러한 문제를 해결하기 위해 onSaveInstanceState 라는 콜백 메소드를 제공한다. 이 메소드는 액티비티 종료 전의 상태를 변수를 Bundle객체에 저장하고, 이 저장된 상태는 onCrete메소드가 호출될 때 전달되는 Bundle 객체로 복원된다.
<layout/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">
<EditText
android:id="@+id/editTextTextPersonName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
android:ems="10"
android:hint="type text here"
android:inputType="textPersonName"
android:minHeight="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextTextPersonName" />
</androidx.constraintlayout.widget.ConstraintLayout>
<layout-land/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">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="88dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.499"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextTextPersonName" />
<EditText
android:id="@+id/editTextTextPersonName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:ems="10"
android:hint="type text here"
android:inputType="textPersonName"
android:minHeight="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.499"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.orientation_event;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
// 밑에 오버라이드된 화면의 상태에 따라 시스템이 자동으로 호출해 주는 메소드들이다. 이러한 메소드를 Life Cycle 또는 생명주기 메소드 라고 부른다.
String name;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* layout-land폴더 : layout폴더와 같은 역할을 하지만, 단말이 가로 방향으로 보일때는 layout-land폴더 안에 들어있는 XML 레이아웃 파일이 사용된다.
*
* */
//showToast("onCreate() called");
editText = findViewById(R.id.editTextTextPersonName);
Button btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
name = editText.getText().toString();
showToast("입력된 값을 변수에 저장했습니다 : " + name);
}
});
if(savedInstanceState != null){
name = savedInstanceState.getString("name");
showToast("값을 복원했습니다 : " + name);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("name",name);
}
public void showToast(String data){
Toast.makeText(this, data,Toast.LENGTH_SHORT).show();
}
}
이 코드는 버튼을 클릭하면, 입력한 값을 name이라는 변수에 저장하는 코드이다. 단말의 방향이 바뀔때 onSaveInstance() 메소드가 호출되는데, onSaveInstance() 메소드를 통해서 name 변수의 값을 Bundle객체에 넣어줄 수 있다. 여기서 몇가지를 짚고 넘어가자면, 액티비티가 다시 생성될때 사용할 데이터를 "인스턴스" 라고 한다. 그리고 이 인스턴스는 Bundle객체에 "Key-Value" 형태로 저장이 된다. 그리고 이 onSaveInstance()는 onStop() 메소드가 호출될때 호출되게 된다.
'Android' 카테고리의 다른 글
[Android] AlertDialog를 응용해보기 (0) | 2022.04.07 |
---|---|
[Android] 알림 대화상자 (0) | 2022.04.07 |
[Android] Touch,Gesture 이벤트 처리 (0) | 2022.03.28 |
[Android] 예시 SMS 레이아웃 만들기 (0) | 2022.03.27 |
[Android] 텍스트를 클립보드에 복사하기 (0) | 2022.03.27 |