Android Studio screenOrientation 고정 상태에서 360˚ 회전 감지하기
Laptop
Mobile
screenOrientation 을 고정한 상태에서 회전을 감지해야 할 필요가 있을 수 있다.
이 때 OrientationEventListener라는 핸들러를 이용하여 방향센서의 값을 가져올 수 있다.
OrientationEventListener는 이름 그대로 기기의 기울기가 변할 때 감지하는 역할을 한다. 말은 이렇지만 그냥 항상 작동한다고 보면 된다.
간단한 예제를 만들어 보자.
먼저 AndroidManifest.xml 을 수정하여 activity를 portrait(세로방향)로 고정해준다.
android:screenOrientation="portrait" 한 줄만 추가해주면 된다.
<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>
그리고 xml 레이아웃은 간단하게 RelativeLayout과 LinearLayout을 통해
화면 중앙에 orientation 측정값과 위쪽 방향 화살표 ↑ 를 TextView로 띄워준다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:orientation="vertical">
<TextView
android:id="@+id/text_orientation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="Orientation: 0"/>
<TextView
android:id="@+id/text_arrow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="40dp"
android:text="↑"/>
</LinearLayout>
</RelativeLayout>
이제 main 함수를 작성해준다.
이벤트 발생 시(센서 변화) 실행될 내용은 onOrientationChanged 안에 입력하면 된다.
또한 canDetectOrientation 메소드를 통해 핸들러가 정상적으로 작동하는지 여부를 판단할 수 있다.
MainActivity.java
package com.orientationtest;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.OrientationEventListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private TextView mTextOrient;
private TextView mTextArrow;
private OrientationEventListener orientEventListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextOrient = (TextView) findViewById(R.id.text_orientation);
mTextArrow = (TextView) findViewById(R.id.text_arrow);
//보통 속도(SENSOR_DELAY_NORMAL)로 측정
orientEventListener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int arg0) {
//arg0: 기울기 값
mTextOrient.setText("Orientation: "
+ String.valueOf(arg0));
// 0˚ (portrait)
if(arg0 >= 315 || arg0 < 45) {
mTextArrow.setRotation(0);
}
// 90˚
else if(arg0 >= 45 && arg0 < 135) {
mTextArrow.setRotation(270);
}
// 180˚
else if(arg0 >= 135 && arg0 < 225) {
mTextArrow.setRotation(180);
}
// 270˚ (landscape)
else if(arg0 >= 225 && arg0 < 315)
{
mTextArrow.setRotation(90);
}
}
};
//핸들러 활성화
orientEventListener.enable();
//인식 오류 시, Toast 메시지 출력
if (!orientEventListener.canDetectOrientation()) {
Toast.makeText(this, "Can't DetectOrientation",
Toast.LENGTH_LONG).show();
finish();
}
}
}
if문을 통해 45˚씩 여유 범위를 두어 각 방향에 따라 화살표가 회전하여 항상 위를 가리키도록 하였다.
이 부분에서는 onConfigurationChanged 핸들러나 Display.getRotation 함수가 상수형 결과값을 받아오기 때문에 더 편리하지만, 현재 상태를 받아오기 때문에 고정 상태에서는 사용할 수 없다.
결과동영상
참고 사이트 : http://mainia.tistory.com/2208
+ 위 링크에는 나와있지만 테스트 결과 SensorManager는 이 프로그램에서는 필요 없는 듯 하다.
+ 평면을 기준으로 한 기울기 값을 측정하기 때문에 기기를 수평으로 눕혀 놓으면 제대로 측정하지 못한다.