관리 메뉴

java,javascript,android,php,sql,공부용,메모용

안드로이드 이벤트 처리 단말 방향 세로 가로 / Android Studio / 안드로이드 앱만들기 공부 14 본문

모바일/안드로이드앱

안드로이드 이벤트 처리 단말 방향 세로 가로 / Android Studio / 안드로이드 앱만들기 공부 14

yy_dd2 2021. 2. 26. 01:33
반응형

단말 방향을 전환했을 떄 이벤트 처리하기

 

 

단말을 세로/가로 방향으로 바꿨을 때 발생하는 방향(Orientation) 전환
- 단말을 세로 가로를 바꾸면 화면 비율에 따라 화면이 다시 보이게 되는데 XML레이아웃도 다르게 보여야 한다.
- 그래서 액티비티는 메모리가 없어졌다가 다시 만들어진다
- 사용자가 가로 화면으로 바꾸면 내용을 좀 더 크게 보기 위해서 또는 왼쪽 오른쪽 다양한 내용이 나타나길 바래서 이다

1. SampleOrientation 새 프로젝트 생성

2. res 폴더 아래 새로운 폴더 생성 (layout-land 리소스 폴더 추가하기)

- res폴더를 선택한 후 마우스 오른쪽 -> [New Android Resource Directory] -> Directory name : layout-land  생성

- 이 폴더는 프로젝트 창에 보이지 않는다 [Project]탭을 선택하면 폴더 확인이 가능함

- 경로 SampleOrientation/app/src/main/res로 가면 layout-land 폴더가 추가되어 있다.

 

layout-land 폴더는 layout 폴더와 같은 역할이지만

단말이 가로 방향으로 보일 때 layout-land 폴더 안에 들어있는 XML 레이아웃 파일을 사용함

** layout-land 폴더명은 지정된 것 :  이 이름으로 된 폴더는 앱을 실행했을 경우 단말의 방향을 자동으로 확인하고 이 폴더 안에 있는 레이아웃 파일을 우선적으로 적용함

 

3. layout에 있는 TextView 세로방향이라고 작성하고 복사해서

4. layout-land 폴더에 붙여넣기 TextView 가로방향이라고 변경

** layout-land는 가로화면 일때 나타나는 폴더로 이름이 지정되어있다.

 

5. MainActivity.java 작성

MainActivity 클래스 우클릭 -> [Generate... -> Override Methods...] -> onStart, onStop, OnDestroy

package com.togapp.sampleorientation;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showToast("onCreate 호출됨");
    }

    @Override
    protected void onStart() {
        super.onStart();
        showToast("onStart 호출됨");
    }

    @Override
    protected void onStop() {
        super.onStop();
        showToast("onStop 호출됨");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        showToast("onDestroy 호출됨");
    }

    // 연속적인 Toast 메시지를 띄우는 코드가 많아져서 showToast를 만들었다.
    public void showToast(String data){
        Toast.makeText(this,data,Toast.LENGTH_LONG).show();
    }


}

 

단말을 세로-> 가로 로 변경을 하면 액티비티의 메모리가 없어졌다가 생겨나는데

문제 : 액티비티에 선언해두었던 변수 값이 사라지는 일이 발생

해결 : onSeaveInstanceState 콜백 메서드 사용

 

onSeaveInstanceState 메서드는 액티비티가 종료되기 전의 상태를 저장한다.

저장한 상태는 onCreate() 메서드가 호출될 때 전달되는 번들Budle 객체로 복원이 가능하다.

 

MainActivity.java 코드 작성

package com.togapp.sampleorientation;

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 {

    String name;
    EditText editText;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        showToast("onCreate 호출됨.");

        editText = findViewById(R.id.editText);
        Button button = findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                name = editText.getText().toString();   // 버튼 클릭하면 사용자가 입력한 값을 name 변수에 할당
                showToast("입력된 값을 변수에 저장했습니다 : " + name);
                // Toast.makeText(getApplicationContext(),"입력된 값을 변수에 저장했습니다 : " + name,Toast.LENGTH_LONG).show();
            }
        });

        if (savedInstanceState != null) {
            name = savedInstanceState.getString("name");
            showToast("값을 복원했습니다" + name);
            // Toast.makeText(getApplicationContext(), "값을 복원했습니다 : " + name, Toast.LENGTH_LONG).show();
        }

    }

    @Override
    protected void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);

        outState.putString("name", name);   // name의 변수의 값 저장장
    }



   @Override
    protected void onStart() {
        super.onStart();
        //showToast("onStart 호출됨");
    }

    @Override
    protected void onStop() {
        super.onStop();
        //showToast("onStop 호출됨");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //showToast("onDestroy 호출됨");
    }

    // 연속적인 Toast 메시지를 띄우는 코드가 많아져서 showToast를 만들었다.
    public void showToast(String data){
        Toast.makeText(this,data,Toast.LENGTH_LONG).show();
    }


}

 

책에서는 MainActivity 클래스 오른쪽클릭 Generate -> Override Methods...   [바로가기버튼 ctrl + o]

메서드를 부르는 창에서 onSaveInstanceState를 불러오라고 하는데 메서드 선택창에 나타나지 않는다....

그래서 그대로 타자를 쳤다.

- onSaveInstanceState() 메서드 안에서 name 변수의 값을 파라미터로 전달받은 Budle 객체에 넣고

- Bundle 객체에 데이터를 넣으면 데이터 단말에 저장되고

- onCreate() 메서드가 호출될 때 파라미터로 전달된다

- onCreate() 메서드의 파라미터의 값은 savedInstanceState 이름으로 되어있고 데이터를 가져와 name의 변수에 할당해서 데이터를 복구한다.



 

app/res/layout 폴더 안의 activity_main.mxl

<?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">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="세로 방향"
        android:textSize="50sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text=""
        app:layout_constraintEnd_toEndOf="parent"
        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="16dp"
        android:text="확인"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />


</androidx.constraintlayout.widget.ConstraintLayout>

 

app/res/layout-land 폴더 안의 activity_main.mxl

<?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">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="가로 방향"
        android:textSize="50sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text=""
        app:layout_constraintEnd_toEndOf="parent"
        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="16dp"
        android:text="확인"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />


</androidx.constraintlayout.widget.ConstraintLayout>

 

세로 화면과 가로 화면의 레이아웃이 다르다면 시스템이 액티비티를 없앴다가 다시 만들어주는데

액티비티는 바뀌지 않고 단순히 화면에 보이는 레이아웃만 바꿀 수 있는 방법이 있다.

 

단말의 방향이 바뀌는 것을 앱에서 이벤트로 전달받도록 하고                                         

액티비티를 유지하는 방법은 configChanges 속성을 설정한다

 

1. 새프로젝트를 만든다 SampleOrientation3

2. activity_main.xml 텍스트 변경

3. manifests 폴더 선택하면 AndroidManifest.xml 파일이 선택된다

 

    <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> 태그는 액티비티를 등록할 때 사용하는 태그 -->
        <activity android:name=".MainActivity"
                android:configChanges="orientation|screenSize|keyboardHidden"> \
                <!-- 방향 전환을 알 수 있도록 configChanges 속성 설정
                     단말의 방향이 바뀌는 시점에 configurationChanged() 메서드가 호출된다.
                     keyboardHidden 값은 액티비티가 보일 때 키패드가 자동으로 나타나지 않도록 하고
                     키패드가 보여야 할 시점을 액티비티 쪽에서 알려주면 된다
                     MainActivity.java 파일에 onConfigurationChanged() 메서드 재정의한다.
                -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

activity 태그는 액티비티 등록할 떄 사용하는 태그

여기에 configChanges 속성을 추가


방향 전환을 알 수 있도록 configChanges 속성 설정
단말의 방향이 바뀌는 시점에 configurationChanged() 메서드가 호출된다.
keyboardHidden 값은 액티비티가 보일 때 키패드가 자동으로 나타나지 않도록 하고
키패드가 보여야 할 시점을 액티비티 쪽에서 알려주면 된다
MainActivity.java 파일에 onConfigurationChanged() 메서드를 재정의한다.


 

MainActivity.java 파일

 

package com.togapp.sampleorientation3;

//import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    @Override
    //public void onConfigurationChanged(@NonNull Configuration newConfig) {
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // 가로방향 전환처리 _LANDSCAPE
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            showToast("방향 : ORIENTATION_LANDSCAPE");
        }
        // 세로방향 전환처리 _PORTRAIT
        else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            showToast("방향 : ORIENTATION_PORTRAIT");
        }
    }

    public void showToast (String data){
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }

}

 


 

화면의 가로와 세로의 고정값을 지정할 수 있다.

매니페스트 파일에서 screenOrientation 속성 값을 지정한다.

 

android:screenOrientation="landscape" 가로고정 portrait 세로고정

    <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> 태그는 액티비티를 등록할 때 사용하는 태그 -->
        <activity android:name=".MainActivity"
                android:screenOrientation="landscape"
                android:configChanges="orientation|screenSize|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
반응형
Comments