Android之随用户的角度旋转屏幕

翁良弼
2023-12-01

一个良好的播放器应该能够很好地随着用户的视角而改变播放的角度,也就是说能够实现自动旋转。今天,费了好长时间才弄懂屏幕的自动旋转,现在来做个总结。

实现屏幕的手动旋转

在activity中有个方法,setRequestedOrientation,通过这个方法,可以改变屏幕的方向。里面可以设置的参数是有约束的,都在ActivityInfo这个类里面,先给出四个。
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
查一下这几个单词的意思REVERSE反向,LANDSCAPE景观(就是横屏啦,老外就喜欢这么玩),PORTRAIT肖像(就是竖屏了,想像一下挺符合意境的),那么
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE横屏
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT竖屏
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT横屏反向
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE竖屏反向(这个设置之后好像实现不了,不知道为啥)

若直接设置的话,在屏幕旋转之后,是会重新启动activity的,想要让它不重启的话,需要在Activity 的配置文件里添加属性: android:configChanges=”orientation|keyboardHidden|navigation”
可以在activity中重载onConfigurationChanged方法,根据不同旋转方向做其他动作,如下:

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
           //更新屏幕布局,而不执行onCreate()方法            
        }

好了,来做个测试:
先来看布局文件,很简单,只有几个button

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.gesturedetectortest.test.Main5Activity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/shang"
        android:text="上"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/xia"
        android:text="下"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/zuo"
        android:text="左"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/you"
        android:text="右"/>
</LinearLayout>

再来看看代码:

public class Main5Activity extends AppCompatActivity implements View.OnClickListener{
    private Button shang,xia,zuo,you;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        initView();

    }

    private void initView() {
        shang = (Button) findViewById(R.id.shang);
        xia = (Button) findViewById(R.id.xia);
        zuo = (Button) findViewById(R.id.zuo);
        you = (Button) findViewById(R.id.you);
        shang.setOnClickListener(this);
        xia.setOnClickListener(this);
        zuo.setOnClickListener(this);
        you.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.shang:shangClick();break;
            case R.id.xia:xiaClick();break;
            case R.id.zuo:zuoClick();break;
            case R.id.you:youClick();break;
        }
    }
    private void shangClick(){
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
    private void xiaClick(){
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
    private void zuoClick(){
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
    }
    private void youClick(){
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
    }
}

很简单,有木有,只是那个ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE好像不起作用,不知道为啥。

实现屏幕的自动旋转

要实现屏幕的自动旋转,就需要使用加速度传感器了。
先来看看加速度传感器的使用:

   @Override
    protected void onResume() {
        super.onResume();
        //传感器管理器
        sensorEventListener = new SensorEventListener(){
            @Override
            public void onSensorChanged(SensorEvent event) {
                Log.i("---","---");//这儿就是加速度传感器产生的事件,我们需要对传感器变化后的处理逻辑需要写在这儿
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
            }
        };
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        //注册传感器(sensor.TYPE_ORIENTATION(方向传感器);SENSOR_DELAY_GAME(20,000延时);
        // SENSOR_DELAY_GAME(20,000毫秒延迟)、SENSOR_DELAY_UI(60,000毫秒延迟)))
        sensorManager.registerListener(sensorEventListener,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sensorManager.unregisterListener(sensorEventListener);
    }

再来看一个对象,OrientationEventListener(方向事件监听),这个对象里面封装了对加速度传感器使用。

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        final TextView textView = (TextView) findViewById(R.id.textview);
        orientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
            @Override
            public void onOrientationChanged(int orientation) {
                textView.setText(orientation+"");//每次旋转屏幕就会产生一个值,在0-360之间的一个值,代表的我们屏幕的方向
            }
        };
        orientationEventListener.enable();

    }

想要的旋转屏幕的处理,只需要对抽象方法实现即可。
现在就差连接传感器事件与屏幕旋转了,这段代码我就不贴了,因为别人写的,我也没看懂,也就不好贴了。不过想要实现屏幕旋转的可以自己试着写一下,相信聪明的你是可以轻松实现的(就是对角度值的一些过滤,不会让它老是转屏就可以了),或者继续向下看。
前面说了四个setRequestedOrientation方法里面的参数,其实不止这么多。

ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,//未指定,此为默认值。由Android系统自己选择合适的方向。

ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,//横屏

ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,//竖屏

ActivityInfo.SCREEN_ORIENTATION_USER,//用户当前的首选方向

ActivityInfo.SCREEN_ORIENTATION_BEHIND,//继承Activity堆栈中当前Activity下面的那个Activity的方向

ActivityInfo.SCREEN_ORIENTATION_SENSOR,//由物理感应器决定显示方向(测试时竖屏反向达不到效果)

ActivityInfo.SCREEN_ORIENTATION_NOSENSOR,//忽略物理感应器——即显示方向与物理感应器无关

ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE,//横屏会自动旋转
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT,//竖屏会自动旋转(测试时达不到效果)
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE,//横屏相反
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,//竖屏相反(测试时达不到效果)
ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR,//和SCREEN_ORIENTATION_SENSOR相似,不过这个四个方向都可以旋转

哈哈,其实自动屏幕旋转一句话就可以了setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR)有了这么多的参数,选择将会更多。至于前面的一些代码,明白就行,看看热闹,熟悉一些实现。

 类似资料: