Android-加速传感器或者OrientationEventListener做横竖屏切换

2019-06-23 09:20:53

参考链接  Android-加速传感器或者OrientationEventListener做横竖屏切换

在播放视频的时候,可能要做横竖屏的切换,但是,用户可以设置自己的手机关掉屏幕旋转,这个时候就需要想其他的办法了,比如:加速传感器或者OrientationEventListener。


1、这是用加速传感器来实现:


public class ScreenSwitchUtils {

private static final String TAG = ScreenSwitchUtils.class.getSimpleName();

private volatile static ScreenSwitchUtils mInstance;

private Activity mActivity;

// 是否是竖屏

private boolean isPortrait = true;

private SensorManager sm;

private OrientationSensorListener listener;

private Sensor sensor;

 

private SensorManager sm1;

private Sensor sensor1;

private OrientationSensorListener1 listener1;

private Handler mHandler = new Handler() {

public void handleMessage(Message msg) {

switch (msg.what) {

case 888:

int orientation = msg.arg1;

if (orientation > 45 && orientation < 135) {

 

} else if (orientation > 135 && orientation < 225) {

 

} else if (orientation > 225 && orientation < 315) {

if (isPortrait) {

Log.e("test", "切换成横屏");

mActivity.setRequestedOrientation(0);

isPortrait = false;

}

} else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {

if (!isPortrait) {

Log.e("test","切换成竖屏");

mActivity.setRequestedOrientation(1);

isPortrait = true;

}

}

break;

default:

break;

}

 

};

};

/** 返回ScreenSwitchUtils单例 **/

    public static ScreenSwitchUtils init(Context context) {

        if (mInstance == null) {

            synchronized (ScreenSwitchUtils.class) {

                if (mInstance == null) {

                    mInstance = new ScreenSwitchUtils(context);

                }

            }

        }

        return mInstance;

    }

 

    private ScreenSwitchUtils(Context context) {

        Log.d(TAG, "init orientation listener.");

        // 注册重力感应器,监听屏幕旋转

        sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);

        sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        listener = new OrientationSensorListener(mHandler);

 

        // 根据 旋转之后/点击全屏之后 两者方向一致,激活sm.

        sm1 = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);

        sensor1 = sm1.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        listener1 = new OrientationSensorListener1();

    }

    

    /** 开始监听 */

    public void start(Activity activity) {

    Log.d(TAG, "start orientation listener.");

        mActivity = activity;

        sm.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI);

    }

 

    /** 停止监听 */

    public void stop() {

    Log.d(TAG, "stop orientation listener.");

    sm.unregisterListener(listener);

sm1.unregisterListener(listener1);

    }

    

    /**

     * 手动横竖屏切换方向

     */

    public void toggleScreen() {

sm.unregisterListener(listener);

sm1.registerListener(listener1, sensor1,SensorManager.SENSOR_DELAY_UI);

if (isPortrait) {

isPortrait = false;

// 切换成横屏

mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

} else {

isPortrait = true;

// 切换成竖屏

mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

}

}

    

    public boolean isPortrait(){

    return this.isPortrait;

    }

    

    /**

* 重力感应监听者

*/

public class OrientationSensorListener implements SensorEventListener {

private static final int _DATA_X = 0;

private static final int _DATA_Y = 1;

private static final int _DATA_Z = 2;

 

public static final int ORIENTATION_UNKNOWN = -1;

 

private Handler rotateHandler;

 

public OrientationSensorListener(Handler handler) {

rotateHandler = handler;

}

 

public void onAccuracyChanged(Sensor arg0, int arg1) {

}

 

public void onSensorChanged(SensorEvent event) {

float[] values = event.values;

int orientation = ORIENTATION_UNKNOWN;

float X = -values[_DATA_X];

float Y = -values[_DATA_Y];

float Z = -values[_DATA_Z];

float magnitude = X * X + Y * Y;

// Don't trust the angle if the magnitude is small compared to the y

// value

if (magnitude * 4 >= Z * Z) {

// 屏幕旋转时

float OneEightyOverPi = 57.29577957855f;

float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;

orientation = 90 - (int) Math.round(angle);

// normalize to 0 - 359 range

while (orientation >= 360) {

orientation -= 360;

}

while (orientation < 0) {

orientation += 360;

}

}

if (rotateHandler != null) {

rotateHandler.obtainMessage(888, orientation, 0).sendToTarget();

}

}

}

 

public class OrientationSensorListener1 implements SensorEventListener {

private static final int _DATA_X = 0;

private static final int _DATA_Y = 1;

private static final int _DATA_Z = 2;

 

public static final int ORIENTATION_UNKNOWN = -1;

 

public OrientationSensorListener1() {

}

 

public void onAccuracyChanged(Sensor arg0, int arg1) {

}

 

public void onSensorChanged(SensorEvent event) {

float[] values = event.values;

int orientation = ORIENTATION_UNKNOWN;

float X = -values[_DATA_X];

float Y = -values[_DATA_Y];

float Z = -values[_DATA_Z];

float magnitude = X * X + Y * Y;

// Don't trust the angle if the magnitude is small compared to the y

// value

if (magnitude * 4 >= Z * Z) {

// 屏幕旋转时

float OneEightyOverPi = 57.29577957855f;

float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;

orientation = 90 - (int) Math.round(angle);

// normalize to 0 - 359 range

while (orientation >= 360) {

orientation -= 360;

}

while (orientation < 0) {

orientation += 360;

}

}

if (orientation > 225 && orientation < 315) {// 检测到当前实际是横屏

if (!isPortrait) {

sm.registerListener(listener, sensor,SensorManager.SENSOR_DELAY_UI);

sm1.unregisterListener(listener1);

}

} else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {// 检测到当前实际是竖屏

if (isPortrait) {

sm.registerListener(listener, sensor,SensorManager.SENSOR_DELAY_UI);

sm1.unregisterListener(listener1);

}

}

}

}

}


转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/47423131


使用的时候:


public class MainActivity extends Activity implements OnClickListener {

 

private ScreenSwitchUtils instance;

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

instance = ScreenSwitchUtils.init(this.getApplicationContext());

}

 

@Override

protected void onStart() {

super.onStart();

instance.start(this);

}

 

@Override

protected void onStop() {

super.onStop();

instance.stop();

}

 

@SuppressLint("NewApi")

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

Log.e("test", "onConfigurationChanged");

if (instance.isPortrait()) {

// 切换成竖屏

LayoutParams params1 = new RelativeLayout.LayoutParams(screenWidth, DensityUtil.dip2px(this, 160));

videoView.setLayoutParams(params1);

Toast.makeText(getApplicationContext(), "竖屏", 0).show();

Log.e("test", "竖屏");

} else {

// 切换成横屏

LayoutParams params1 = new RelativeLayout.LayoutParams(screenHeight, screenWidth);

videoView.setLayoutParams(params1);

Toast.makeText(getApplicationContext(), "横屏", 0).show();

Log.e("test", "横屏");

}

}

 

@Override

public void onClick(View arg0) {

switch (arg0.getId()) {

case R.id.iv_stretch:

instance.toggleScreen();

break;

}

}

}


调用了activity.setRequestedOrientation()以后,会触发activity.onConfigurationChanged();可以在这里面重新设置播放界面的大小。




参考:http://download.csdn.net/download/liubo080852/8446445




2.还有一种更简单的方式OrientationEventListener:


public class ScreenOrientationUtil {

private int mOrientation;

private OrientationEventListener mOrEventListener;

private int mOrientation1;

private OrientationEventListener mOrEventListener1;

private Activity mActivity;

private static ScreenOrientationUtil instance = new ScreenOrientationUtil();

public static ScreenOrientationUtil getInstance(){

return instance;

public void start(Activity activity){

this.mActivity = activity;

if(mOrEventListener == null){

initListener();

}

mOrEventListener.enable();

}

public void stop(){

if(mOrEventListener != null){

mOrEventListener.disable();

}

if(mOrEventListener1 != null){

mOrEventListener1.disable();

}

}

private void initListener(){

mOrEventListener = new OrientationEventListener(mActivity) {

        @Override

        public void onOrientationChanged(int rotation) {

        Log.e("test", ""+rotation);

            if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) {

                return;

            }

            int orientation = convert2Orientation(rotation);

            // 方向没有变化,跳过

            if (orientation == mOrientation) {

                return;

            }

            mOrientation = orientation;

            mActivity.setRequestedOrientation(mOrientation);

            

        }

    };

    

    mOrEventListener1 = new OrientationEventListener(mActivity) {

        @Override

        public void onOrientationChanged(int rotation) {

            if (rotation == OrientationEventListener.ORIENTATION_UNKNOWN) {

                return;

            }

            int orientation = convert2Orientation(rotation);

            // 方向没有变化,跳过

            if (orientation == mOrientation1) {

                return;

            }

            mOrientation1 = orientation;

            if(mOrientation1 == mOrientation){

            mOrEventListener1.disable();

            mOrEventListener.enable();

            }

        }

    };

}

public boolean isPortrait(){

if(mOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || mOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT){

return true;

}

return false;

}

public int getOrientation(){

return mOrientation;

}

public void toggleScreen(){

mOrEventListener.disable();

mOrEventListener1.enable();

int orientation = 0 ;

if(mOrientation ==  ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){

orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;

}else if(mOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){

orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

}else if(mOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE){

orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

}else if(mOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT){

orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;

}

mOrientation = orientation;

mActivity.setRequestedOrientation(mOrientation);

}

private int convert2Orientation(int rotation){

int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

        if (((rotation >= 0) && (rotation <= 45)) || (rotation > 315)) {

            orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

        } else if ((rotation > 45) && (rotation <= 135)) {

            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;

        } else if ((rotation > 135) && (rotation <= 225)) {

            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;

        } else if ((rotation > 225) && (rotation <= 315)) {

            orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

        } else {

            orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

        }

        return orientation;

}

}



  • 2018-12-13 11:41:23

    Android drawable微技巧,你所不知道的drawable的那些细节

    好像有挺久时间没更新博客了,最近我为了准备下一个系列的博客,也是花了很长的时间研读源码。很遗憾的是,下一个系列的博客我可能还要再过一段时间才能写出来,那么为了不至于让大家等太久,今天就给大家更新一篇单篇的文章,讲一讲Android drawable方面的微技巧。

  • 2018-12-13 17:14:41

    Android安全开发之浅谈密钥硬编码

    在阿里聚安全的漏洞扫描器中和人工APP安全审计中,经常发现有开发者将密钥硬编码在Java代码、文件中,这样做会引起很大风险。信息安全的基础在于密码学,而常用的密码学算法都是公开的,加密内容的保密依靠的是密钥的保密,密钥如果泄露,对于对称密码算法,根据用到的密钥算法和加密后的密文,很容易得到加密前的明文;对于非对称密码算法或者签名算法,根据密钥和要加密的明文,很容易获得计算出签名值,从而伪造签名。

  • 2018-12-13 17:17:02

    轻松实现动态获取Android手机CPU架构类型

    .so文件是unix的动态连接库,是二进制文件,作用相当于windows下的.dll文件。 他使用了C/C++代码编写的可以操作硬件比java更高级的 底层代码,执行速度和效率比其他语言要高。 在Android中调用动态库文件(*.so)都是通过jni的方式。

  • 2018-12-13 22:48:48

    Android MultiDex实践:如何绕过那些坑?

    MultiDex, 顾名思义,是指多dex实现,大多数App,解压其apk后,一般只有一个classes.dex文件,采用MultiDex的App解压后可以看到有classes.dex,classes2.dex,… classes(N).dex,这样每个dex都可以最大承载65k个方法,很大限度地缓解了单dex方法数限制。

  • 2018-12-14 13:32:18

    解决chrome调试手机模式没有鼠标问题

    F12后,切换到手机模式,方向没有鼠标,这对于调试前端页面来说无疑是一大难题,看不见只能盲点, 以为是浏览器问题,清理缓存,升级浏览器,清除插件等都不好使。 后来查到资料说是显卡问题。果然还真是显卡问题。

  • 2018-12-14 17:12:51

    Android APP适配全面屏手机的技术要点

    全面屏是手机业界对于超高屏占比手机设计的一个宽泛的定义。从字面上解释就是,手机的正面全部都是屏幕,四个边框位置都是采用无边框设计,追求接近100%的屏占比。但受限于目前的技术,还不能做到手机正面屏占比100%的手机。现在业内所说的全面屏手机是指真实屏占比可以达到80%以上,拥有超窄边框设计的手机。

  • 2018-12-14 17:15:50

    Android适配刘海屏沉浸式状态栏的一些坑

    18年简直是刘海元年,所有手机都在跟风刘海屏,甚至每个厂商还有自己的一套适配规范。我的初始需求很简单,就是做一个全屏显示的页面,一般情况下只需要开启Android规范的全屏模式就好: