안드로이드 핸드폰 뿐만 아니라 대부분의 이동형 장치는 위치에 따라 기본 방향이 설정되어 있습니다. 

이걸 기준으로 화면 자동 회전을 설정해 놓아 사진 가로보기가 가능 합니다.

동서남북을 가리키는 나침반은 방향을 바꾸면 그에 맞추어 위치를 다시 계산해야 합니다.

일반적인 컴퓨터 모니터는 우측상단이 원점이고 가로 방향이 x, 세로 아래 방향이 y축이지만

Android 기기 에서는 일반적인 수학에서 배운 대로 가로 방향이 x, 세로 방향이 y, 나를 향하는 전면 방향을 z축으로 설정 합니다.

좌표 축은 이렇게 설정이 되어 있지만 장치가 세로로 있을 때 우측(가로) 방향이 x축 일까요?

태블릿 장치는 가로로 있을 때 우측 방향이 x축 일까요?


Android를 사용하는 모든 기기가 동일 하지 않다고 하니 방향과 축에 관련된 앱을 개발하려면 한번쯤 확인을 하는게 좋을 듯 합니다.



1. 상수 값


방향 확인을 위해 장치가 어느 방향으로 회전 되어 있는가를 확인하는 상수 값이 있습니다.


 Type

 Constants

 value

 설명

 int

 Surface.ROTATION_0

 0

 장치가 사용자 기준 정방향

 int

 Surface.ROTATION_90

 1

 장치가 사용자 기준 반 시계방향 90도 회전

 int

 Surface.ROTATION_180

 2

 장치가 사용자 기준 반 시계방향 180도 회전

 int

 Surface.ROTATION_270

 3

 장치가 사용자 기준 반 시계방향 270도 회전

 int

 SensorManager.AXIS_X

 1

 X축에 해당하는 상수 값

 int

 SensorManager.AXIS_Y

 2

 Y축에 해당하는 상수 값

 int

 SensorManager.AXIS_Z

 3

 Z축에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_X

 129

 X축 반대 방향에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_Y

 130

 Y축 반대 방향에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_Z

 131

 Z축 반대 방향에 해당하는 상수 값



2. 회전 결과


먼저 앱을 실행하였을 때의 결과를 보면 간단하게 확인이 가능 합니다.

앱을 켜고 핸드폰을 좌측으로 한 바퀴, 우측으로 한 바퀴 돌리며 결과를 보면

반 시계방향으로 90도씩 증가하는 하며 180도 에서는 어느 방향으로 돌렸는가에 따라

90, 270도의 결과가 그대로 유지 됩니다.


android gyroscope sensor



3. 화면 회전 프로젝트

 

실제 프로젝트 하나를 만들어 보겠습니다.

 

3.1 신규 프로젝트 생성


Android studio에서 새로운 프로젝트를 생성합니다. 여기서는 SurfaceRotation로 했습니다.

캡처 화면은 팝업을 축소하여 받은 것으로 실제 화면의 일부분 입니다.




3.2 장치 설정


앱이 실행될 기본 장치를 알맞게 선택 합니다.




3.3 Configure


기본 화면은 empty를 선택 했고 코딩용 설정 값은 기본값을 그대로 사용 합니다.



 

3.4 Layout 작성


x, y 축의 값을 보여주고 회전 각을 표시하기 위한 TextView를 축의 개수에 맞게 생성 합니다.


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Surface Rotation"
        android:layout_marginTop="50dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvXaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="X axis : 0"
        />
    <TextView
        android:id="@+id/tvYaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvXaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Y axis : 0"
        />
    <TextView
        android:id="@+id/tvZaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvYaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Z axis : 0"
        />
    <TextView
        android:id="@+id/tvRotation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvZaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Rotation : 0"
        />

</android.support.constraint.ConstraintLayout>


3.5 Java Source


소스는 일반적인 센서 테스트용 프로젝트와 동일한 구조를 갖고 있습니다.

센서는 TYPE_GYROSCOPE를 사용 했는데 별의미 없으므로 다른 센서를 사용해도 됩니다.

화면 회전에 대한 값을 구하기 위한 getSurfaceRotation() 함수가 추가되었습니다.

이 함수에서 화면에 값을 출력 합니다.


package com.example.desk.surfacerotation;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity  implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor gyroSensor;
    int rotation;
    TextView tvXaxis, tvYaxis, tvZaxis, tvRotation;

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

        tvXaxis = (TextView)findViewById(R.id.tvXaxis);
        tvYaxis = (TextView)findViewById(R.id.tvYaxis);
        tvZaxis = (TextView)findViewById(R.id.tvZaxis);
        tvRotation = (TextView)findViewById(R.id.tvRotation);

        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

    }

    void getSurfaceRotation() {
        String windowsService = Context.WINDOW_SERVICE;
        WindowManager windowManager = (WindowManager)getSystemService(windowsService);
        Display display = windowManager.getDefaultDisplay();
        rotation = display.getRotation();

        int xAxis = SensorManager.AXIS_X;
        int yAxis = SensorManager.AXIS_Y;
        int zAxis = SensorManager.AXIS_Z;

        switch (rotation) {
            case Surface.ROTATION_0:
                tvRotation.setText("Rotation : 0");
                break;
            case Surface.ROTATION_90:
                xAxis = SensorManager.AXIS_Y;
                yAxis = SensorManager.AXIS_MINUS_X;
                tvRotation.setText("Rotation : 90");
                break;
            case Surface.ROTATION_180:
                yAxis = SensorManager.AXIS_MINUS_Y;
                tvRotation.setText("Rotation : 180");
                break;
            case Surface.ROTATION_270:
                xAxis = SensorManager.AXIS_MINUS_Y;
                yAxis = SensorManager.AXIS_X;
                tvRotation.setText("Rotation : 270");
                break;
            default:
                break;
        }
        tvXaxis.setText("X axis : " + String.valueOf(xAxis));
        tvYaxis.setText("Y axis : " + String.valueOf(yAxis));
        tvZaxis.setText("Z axis : " + String.valueOf(zAxis));
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor ==gyroSensor) {
            getSurfaceRotation();
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}


4. 결과


4.1 결과 화면


위에서 회전각을 표시한 그림과 같은 결과들을 볼 수 있습니다.



3.2 Source Code

소스코드를 첨부 합니다.


SurfaceRotation.7z



 

3.3 APK File

직접 테스트 하려면 apk를 이용 하세요.


SurfaceRotation.apk


- copy coding -


+ Recent posts