센서 주제 (2) - 방향 센서


이 섹션 소개:

이전 섹션에서 우리는 센서의 몇 가지 기본 개념을 배웠고 센서 사용 루틴을 배웠습니다. 이번 섹션에서 소개할 센서는 방향 센서의 사용법입니다. 이제 시작하겠습니다~


1. 3차원 좌표계의 개념:

Android 플랫폼에서 센서 프레임은 일반적으로 값을 표현하기 위한 표준 3차원 좌표계. 이 섹션을 가져가세요 방향 센서를 예로 들어보겠습니다. 방향을 결정하려면 결국 3차원 좌표가 필요합니다. Android에서 반환한 방향 값은 세 방향을 포함하여 길이가 3인 평면 배열입니다. 값! 공식 API 문서에 다음과 같은 그림이 있습니다: sensors_overview

1.png

그림을 이해할 수 없다면 텍스트 설명을 적어주세요:

  • X축 방향: 왼쪽에서 화면의 가로 방향으로 오른쪽, 휴대폰이 정사각형이 아닌 경우 짧은 쪽이 가로로 되어야 합니다. 배치할 때는 긴 쪽을 수직으로 배치해야 합니다.
  • Y축 방향: 화면 왼쪽 하단에서 시작하여 화면의 세로 방향을 따라 화면 상단을 가리킴
  • Z축 방향: 가로로 배치했을 때 방향을 가리킴 of the sky

2. 방향 센서의 세 가지 값

이전 섹션에서 언급한 것처럼 센서 콜백 방법: onSensorChanged의 매개변수 SensorEvent 이벤트, 이벤트 값 유형은 Float[]이고 최대 3개의 요소를 갖는 반면, 방향 센서는 정확히 3개의 요소를 가지며 모두 각도를 나타냅니다! 해당 의미는 다음과 같습니다.

values[0]: 방위각, Z축을 중심으로 휴대폰이 회전하는 각도. 0은 북쪽, 90은 동쪽을 의미합니다. 180은 정남(남쪽), 270은 정서(서쪽)를 의미합니다. 값[0]의 값이 우연히 이 네 가지 값인 경우, 그리고 휴대폰을 수평으로 놓으면 휴대폰의 현재 전면이 이 네 방향이 됩니다. 나침반을 써라!

값[1]: 기울기 각도, 휴대폰이 기울어지는 정도. 이 값은 휴대폰이 x축을 기준으로 기울어지면 변경됩니다. 값 범위는 [-180,180] 사이입니다. 전화기가 바탕 화면에 놓여 있고 바탕 화면이 완전히 수평인 경우 값은 ​​1이어야 합니다. 는 0입니다. 물론 완전히 수평인 테이블은 거의 없습니다. 휴대전화가 x축을 따라 180도 회전할 때까지 휴대전화 상단 에서 들어 올리기 시작합니다(이때 화면은 탁상 위에 수평으로 놓인 시골). 이 회전 과정에서 값[1]의 값이 0에서 -180으로 변경됩니다. 즉, 전화기가 들어 올려집니다. , 값 ​​1은 -180과 같을 때까지 점차 작아지고 전화기가 x축을 따라 이동할 때까지 전화기 아래쪽 을 들어 올리기 시작합니다. 180도 회전하면 값[1]의 값이 0에서 180으로 변경됩니다. 이 가치 특성[1]을 사용하여 결합할 수 있습니다. value[2] 평면자를 구현해보세요!

값[2

]: 스크롤 각도, Y축 스크롤 각도, 값 범위: [-90,90], 휴대폰 화면이 수평 위쪽으로 배치되었다고 가정 바탕화면에서 이때 바탕화면이 평평하다면 값2의 값은 0이 되어야 합니다. 휴대폰을 왼쪽부터 서서히 들어올리면 value[2]의 값이 이때 값[2]의 값은 -90이고 오른쪽부터 0~90까지 수직 위치에 추가됩니다. 계속 오른쪽이나 왼쪽으로 스크롤하면 값[2]의 값이 -90에서 90 사이에서 계속 변경됩니다! 잘 이해가 안 되더라도 괜찮습니다. 데모를 작성해 확인해 보세요~

3. 간단한 데모를 통해 다음 세 가지 값의 변화를 이해할 수 있습니다.

렌더링 실행

:

2.gif

구현 코드

: 레이아웃 코드:

activity_main.xml

:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <TextView
        android:id="@+id/tv_value1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="方位角"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_value2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="倾斜角"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_value3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="滚动角"
        android:textSize="18sp"
        android:textStyle="bold" /></LinearLayout>

MainActivity.java

:

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private TextView tv_value1;
    private TextView tv_value2;
    private TextView tv_value3;
    private SensorManager sManager;
    private Sensor mSensorOrientation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mSensorOrientation = sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        sManager.registerListener(this, mSensorOrientation, SensorManager.SENSOR_DELAY_UI);
        bindViews();
    }

    private void bindViews() {
        tv_value1 = (TextView) findViewById(R.id.tv_value1);
        tv_value2 = (TextView) findViewById(R.id.tv_value2);
        tv_value3 = (TextView) findViewById(R.id.tv_value3);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        tv_value1.setText("方位角:" + (float) (Math.round(event.values[0] * 100)) / 100);
        tv_value2.setText("倾斜角:" + (float) (Math.round(event.values[1] * 100)) / 100);
        tv_value3.setText("滚动角:" + (float) (Math.round(event.values[2] * 100)) / 100);
    }

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

    }
}
코드는 매우 간단합니다~, 이 세 가지 값의 변화를 실제로 경험하고 싶다면 , 프로그램을 직접 실행해 보세요~

4. 간단한 텍스트 나침반 예시

텍스트가 진남을 표시할 때 경험해 볼 수 있는 간단한 텍스트 버전을 작성해 보겠습니다. 휴대폰을 뜻해요 바로앞이 남쪽이에요!

렌더링 실행

:

3.gif

코드 구현

:Custom View:

CompassView.java

/**
 * Created by Jay on 2015/11/14 0014.
 */
public class CompassView extends View implements Runnable{

    private Paint mTextPaint;
    private int sWidth,sHeight;
    private float dec = 0.0f;
    private String msg  = "正北 0°";

    public CompassView(Context context) {
        this(context, null);
    }

    public CompassView(Context context, AttributeSet attrs) {
        super(context, attrs);
        sWidth = ScreenUtil.getScreenW(context);
        sHeight = ScreenUtil.getScreenH(context);
        init();
        new Thread(this).start();
    }



    public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {

        mTextPaint = new Paint();
        mTextPaint.setColor(Color.GRAY);
        mTextPaint.setTextSize(64);
        mTextPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText(msg, sWidth / 4 , sWidth / 2, mTextPaint);
    }

    // 更新指南针角度
    public void setDegree(float degree)
    {
        // 设置灵敏度
        if(Math.abs(dec - degree) >= 2 )
        {
            dec = degree;
            int range = 22;
            String degreeStr = String.valueOf(dec);

            // 指向正北
            if(dec > 360 - range && dec  90 - range && dec  180 - range && dec  270 - range && dec  45 - range && dec  135 - range && dec  225 - range && dec  315 - range && dec < 315 + range)
            {
                msg = "西北 " + degreeStr + "°";
            }
        }
    }


    @Override
    public void run() {
        while(!Thread.currentThread().isInterrupted())
        {
            try
            {
                Thread.sleep(100);
            }
            catch(InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
            postInvalidate();
        }
    }
}

MainActivity.java

:

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private CompassView cView;
    private SensorManager sManager;
    private Sensor mSensorOrientation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        cView = new CompassView(MainActivity.this);
        sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mSensorOrientation = sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        sManager.registerListener(this, mSensorOrientation, SensorManager.SENSOR_DELAY_UI);
        setContentView(cView);
    }


    @Override
    public void onSensorChanged(SensorEvent event) {
        cView.setDegree(event.values[0]);
    }

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

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sManager.unregisterListener(this);
    }
}
이것은 매우 간단한 나침반입니다. 프로토타입, 당신이 그렇다면 관심이 있으시면 나침반과 포인터를 직접 그려서 구현해 보세요. 보기 좋은 나침반~


5. 이 섹션의 샘플 코드 다운로드:

SensorDemo2.zip

SensorDemo3.zip


이 섹션 요약:

이 섹션에서는 가장 일반적으로 사용되는 방향 센서를 소개합니다. Android의 간단한 사용법과 나침반의 예를 작성했습니다. 나침반을 완성하려면 값[0] 하나만 사용하고 나머지 두 개를 사용합니다. 특정 장소가 평평하게 누워 있는지 측정하는 데에도 사용할 수 있습니다. 즉, 레벨자를 만드는 데에도 사용할 수 있습니다. 시간이 있으면 재미로 작성해 보세요~ 그렇군요. 감사합니다~4.jpg