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-04 23:41:47

    制作自己的Pod库(公有/私有)

    目的:1.管理自己常用的类;2.组件化开发步骤:1.想一个比较酷的名字,在桌面简历文件夹。2.打开terminal,cd到这个文件夹下面,执行pod lib create  xxx(这里我们以JJCategoryKit为例子,下同)命令,如下图。这个过程会问几个问题,根据实际情况输入回答即可。这里我们选择添加demo,结束的时候会自动Lanuch这个app. 作者:深水日月 链接:https://www.jianshu.com/p/ece0b5721461 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 2018-12-05 06:08:26

    CocoaPods建立私有仓库 spec repo

    好多项目里都有公共的组件,copy来,copy去很容易出错,而且不容易维护,所以就想到用用cocoapods 建自己的私有库,Carthage用法虽然相对简单,但是它是把公共组件都放在framework里不容易单步调试,所以我还是选择用Cocoapods 来建立私有仓库 参考使用Cocoapods创建私有podspec

  • 2018-12-05 15:11:18

    为什么 Objective-C非常难

    作为一个Objective-C的coder,我总能听到一部 分人在这门语言上抱怨有很多问题。他们总在想快速学习这门语言来写一个App出来,但他们也总是联想到Objective-C看上去实在太难了或者在想这 些语法符号都是神马玩意?不错,他们问得非常好,所以本人也解释一下为什么很多程序员相比较学习Ruby或者Java很容易,但在决定开发iOS或者OS X应用时会那么犹豫。

  • 2018-12-05 15:22:23

    十分钟让你明白Objective-C的语法(和Java、C++的对比)

    很多想开发iOS,或者正在开发iOS的程序员以前都做过Java或者C++,当第一次看到Objective-C的代码时都会头疼,Objective-C的代码在语法上和Java, C++有着很大的区别,有的同学会感觉像是看天书一样。不过,语言都是相通的,有很多共性。下面列出Objective-C语言的语法和Java,C++的对比,这样你就会很容易Objective-C的语法是怎么回事了。

  • 2018-12-05 15:33:33

    一篇文章看懂有关iOS开发语言的一切!

    OS开发语言有哪些?OS开发语言主要包括什么?iOS开发语言具体怎么学习?今天重点介绍一下: iOS开发语言主要包括:C语言基础、Obiective-C编程、Swift、UIKit框架详解这几大块,在这里项目阶段就不详细的介绍了。 C语言基础 C语言是开发语言的基础,是最常用的一门程序设计语言,最常用于编写计算机程序。

  • 2018-12-06 10:03:36

    定时杀掉processlist sleep状态的线程

    由于程序设计的Bug,导致目前这个项目使用的数据库中有很多Sleep状态的线程。找了很多解决办法,还没发现最终有效的解决方案。只能临时使用如下方法: 编写shell文件,如killSleepProcess.sh

  • 2018-12-07 08:26:37

    mysql线程池和连接池的区别

    可能有的DBA会把线程池和连接池混淆,其实两者是有很大区别的,连接池一般在客户端设置,而线程池是在DB服务器上配置;另外连接池可以取到避免了连接频繁创建和销毁,但是无法取到控制MySQL活动线程数的目标,在高并发场景下,无法取到保护DB的作用。比较好的方式是将连接池和线程池结合起来使用。 作者:飞鸿无痕 链接:https://www.jianshu.com/p/88e606eca2a5 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 2018-12-07 17:47:24

    linux中wc命令用法

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。