【Android】android开发---实现屏幕旋转的两种方法

前言

为实现播放器全屏竖屏切换,还可锁住横屏,解锁后又可以跟随传感器变化。


正文

方法一:通过控制android:screenOrientation属性控制横竖屏

1.使用 SCREEN_ORIENTATION_SENSOR 参数设置其可以跟随传感器

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

2.当全屏时点击锁住,使用  SCREEN_ORIENTATION_LOCKED 锁住屏幕

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

3.点击解锁,再设置为跟随传感器

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

 这时候就有一个新的问题给大家,如果要实现点击播放器放大按钮,变成全屏,全屏后还可以跟随传感器变化,大家会怎么做?

你可能会想使用 SCREEN_ORIENTATION_LANDSCAPE 使其横屏,接着设置为跟随传感器 ,也就是以下两行代码。

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

可是结果总是这么不尽如人意。点击"开启旋转"会发现旋转成横屏后会自动又旋回竖屏(因为传感器是读取你现在的手机状态),显而易见,这种体验很不好。

所以我们就有了方法二

方法二:通过监听屏幕旋转角度控制横竖屏

前期配置:

AndroidManifest.xml

android:configChanges="orientation|screenSize">

使其不会重新调用onCreate方法,而是调用onConfigurationChanged,避免出现奇怪的问题。

基础类:

别看代码多,直接拷去用就好

package com.aliyun.vodplayerview.utils;

import android.content.Context;
import android.hardware.SensorManager;
import android.view.OrientationEventListener;


/*
 * Copyright (C) 2010-2018 Alibaba Group Holding Limited.
 */

/**
 * 屏幕方向监听类
 */
public class OrientationWatchDog {
    private static final String TAG = OrientationWatchDog.class.getSimpleName();

    private Context mContext;
    //系统的屏幕方向改变监听
    private OrientationEventListener mLandOrientationListener;
    //对外的设置的监听
    private OnOrientationListener mOrientationListener;
    //上次屏幕的方向
    private Orientation mLastOrientation = Orientation.Port;

    /**
     * 屏幕方向
     */
    private enum Orientation {
        /**
         * 竖屏
         */
        Port,
        /**
         * 横屏
         */
        Land
    }


    public OrientationWatchDog(Context context) {
        mContext = context.getApplicationContext();
    }

    /**
     * 开始监听
     */
    public void startWatch() {
        VcPlayerLog.e(TAG, "startWatch");
        if (mLandOrientationListener == null) {
            mLandOrientationListener = new OrientationEventListener(mContext,
                    SensorManager.SENSOR_DELAY_NORMAL) {
                @Override
                public void onOrientationChanged(int orientation) {
                    //这里的|| 和&& 不能弄错!!
                    //根据手机的方向角度计算。在90和180度上下10度的时候认为横屏了。
                    //竖屏类似。
                    boolean isLand = (orientation < 100 && orientation > 80)
                            || (orientation < 280 && orientation > 260);

                    boolean isPort = (orientation < 10 || orientation > 350)
                            || (orientation < 190 && orientation > 170);

                    if (isLand) {
                        if (mOrientationListener != null) {
                            mOrientationListener.changedToLandScape(mLastOrientation == Orientation.Port);
                        }
                        mLastOrientation = Orientation.Land;
                    } else if (isPort) {
                        if (mOrientationListener != null) {
                            mOrientationListener.changedToPortrait(mLastOrientation == Orientation.Land);
                        }
                        mLastOrientation = Orientation.Port;
                    }

                }
            };
        }

        mLandOrientationListener.enable();
    }

    /**
     * 结束监听
     */
    public void stopWatch() {
        if (mLandOrientationListener != null) {
            mLandOrientationListener.disable();
        }
    }

    /**
     * 销毁监听
     */
    public void destroy() {
        stopWatch();
        mLandOrientationListener = null;
    }

    /**
     * 屏幕方向变化事件
     */
    public interface OnOrientationListener {
        /**
         * 变为Land
         *
         * @param fromPort 是否是从竖屏变过来的
         */
        void changedToLandScape(boolean fromPort);

        /**
         * 变为Port
         *
         * @param fromLand 是否是从横屏变过来的
         */
        void changedToPortrait(boolean fromLand);
    }

    /**
     * 设置屏幕方向变化事件
     *
     * @param l 事件监听
     */
    public void setOnOrientationListener(OnOrientationListener l) {
        mOrientationListener = l;
    }

}

使用方法:

1.实现OnOrientationListener接口,将旋转时需要实现的操作放进去

  界面:

  MainAcitivity:

package com.eddie.screenorientationdemo;

import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.eddie.screenorientation.OrientationWatchDog;



public class MainActivity extends AppCompatActivity implements OrientationWatchDog.OnOrientationListener {

    TextView mTvStartSpan;
    TextView mTvStopSpan;
    /**
     * 监听类
     */
    private OrientationWatchDog mOrientationWatchDog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTvStartSpan = findViewById(R.id.tv_start_span);
        mTvStopSpan = findViewById(R.id.tv_stop_span);
        initOrientationWatchdog();
        mTvStartSpan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOrientationWatchDog != null) {
                    mOrientationWatchDog.startWatch();
                }
            }
        });
        mTvStopSpan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOrientationWatchDog != null) {
                    mOrientationWatchDog.stopWatch();
                }
            }
        });
    }

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

    @Override
    public void changedToLandScape(boolean fromPort) {
        //如果不是从竖屏变过来,也就是一直是横屏的时候,就不用操作了
        if (!fromPort) {
            return;
        }
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    @Override
    public void changedToPortrait(boolean fromLand) {
        //如果没有转到过横屏,就不让他转了。防止竖屏的时候点横屏之后,又立即转回来的现象
        if (!fromLand) {
            return;
        }
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /**
     * 初始化屏幕方向监听器。用来监听屏幕方向。结果通过OrientationListener回调出去。
     */
    private void initOrientationWatchdog() {
        mOrientationWatchDog = new OrientationWatchDog(this);
        mOrientationWatchDog.setOnOrientationListener(this);
    }
}

2.初始化监听器

 /**
     * 初始化屏幕方向旋转。用来监听屏幕方向。结果通过OrientationListener回调出去。
     */
    private void initOrientationWatchdog() {
        final Context context = getContext();
        mOrientationWatchDog = new OrientationWatchDog(context);
        mOrientationWatchDog.setOnOrientationListener(new InnerOrientationListener(this));
    }

3.在你需要跟随传感器变化的地方,开启监听器

if (mOrientationWatchDog != null) {
    mOrientationWatchDog.startWatch();
}

 4.别忘了在不使用的时候关闭监听器

if (mOrientationWatchDog != null) {
    mOrientationWatchDog.stopWatch();
}

源码: github

借鉴阿里云播放器源码

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值