在 Android的 Settings->Sound and Display中有 Orientation这一设置项。当选中时,反转手机,手机屏幕会随之旋转,一般只可以旋转90度。

这一 settings设置是在文件 SoundAndDisplaySettings.java中,该项对应的键字符串为:

  1. private   static   final  String KEY_ACCELEROMETER =  "accelerometer" ;

复制代码

Java代码

  1. private static final String KEY_ACCELEROMETER = "accelerometer";

复制代码

其默认值保存在 xml文件中,默认是 Enable。 UI程序初始化时会根据其值是否在复选框中打勾(代码在 onCreate函数中):

  1. protected   void  onCreate(Bundle savedInstanceState) {
  2. mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
  3. mAccelerometer.setPersistent(false );
  4. }

复制代码

Java代码

  1. protected void onCreate(Bundle savedInstanceState) {
  2. mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
  3. mAccelerometer.setPersistent(false);
  4. }

复制代码

当用户改变了该值时,会保存起来:

Java代码

  1. public   boolean  onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
  2. } else   if  (preference == mAccelerometer) {
  3. Settings.System.putInt(getContentResolver(),
  4. Settings.System.ACCELEROMETER_ROTATION,
  5. mAccelerometer.isChecked() ? 1  :  0 );
  6. }

复制代码

  1. public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
  2. } else if (preference == mAccelerometer) {
  3. Settings.System.putInt(getContentResolver(),
  4. Settings.System.ACCELEROMETER_ROTATION,
  5. mAccelerometer.isChecked() ? 1 : 0);
  6. }

复制代码

文件 frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中的 SettingsServer会随时监控其值,对用户设置做出反应:

  1. public void update() {
  2. ContentResolver resolver = mContext.getContentResolver();
  3. boolean updateRotation = false ;
  4. synchronized (mLock) {
  5. int accelerometerDefault = Settings.System.getInt(resolver,
  6. Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
  7. if (mAccelerometerDefault != accelerometerDefault) {
  8. mAccelerometerDefault = accelerometerDefault;
  9. updateOrientationListenerLp();
  10. }
  11. }

复制代码

Java代码

  1. publicvoid update() {
  2. ContentResolver resolver = mContext.getContentResolver();
  3. boolean updateRotation = false;
  4. synchronized (mLock) {
  5. int accelerometerDefault = Settings.System.getInt(resolver,
  6. Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
  7. if (mAccelerometerDefault != accelerometerDefault) {
  8. mAccelerometerDefault = accelerometerDefault;
  9. updateOrientationListenerLp();
  10. }
  11. }

复制代码

上述是设置生效流程。当 Orientation设置 Enable时,会发生什么呢?

在 PhoneWindowManager.java有个 Listener,它会根据 Sensor判别出的旋转方向,调用 WindowManager.setRotation让屏幕进行旋转。另外,当应用程序显示禁止屏幕旋转时则不会旋转,见函数 needSensorRunningLp()。

  1. class MyOrientationListener extends WindowOrientationListener {
  2. MyOrientationListener(Context context) {
  3. super (context);
  4. }
  5. @Override
  6. public void onOrientationChanged( int rotation) {
  7. // Send updates based on orientation value
  8. if ( true ) Log.i(TAG, "onOrientationChanged, rotation changed to " +rotation);
  9. try {
  10. mWindowManager.setRotation(rotation, false ,
  11. mFancyRotationAnimation);
  12. } catch (RemoteException e) {
  13. // Ignore
  14. }
  15. }
  16. }
  17. MyOrientationListener mOrientationListener;
  18. boolean useSensorForOrientationLp( int appOrientation) {
  19. if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
  20. return true ;
  21. }
  22. if (mAccelerometerDefault != 0 && (
  23. appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER ||
  24. appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
  25. return true ;
  26. }
  27. return false ;
  28. }
  29. /*
  30. * We always let the sensor be switched on by default except when
  31. * the user has explicitly disabled sensor based rotation or when the
  32. * screen is switched off.
  33. */
  34. boolean needSensorRunningLp() {
  35. if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
  36. // If the application has explicitly requested to follow the
  37. // orientation, then we need to turn the sensor or.
  38. return true ;
  39. }
  40. if (mAccelerometerDefault == 0 ) {
  41. // If the setting for using the sensor by default is enabled, then
  42. // we will always leave it on.  Note that the user could go to
  43. // a window that forces an orientation that does not use the
  44. // sensor and in theory we could turn it off... however, when next
  45. // turning it on we won't have a good value for the current
  46. // orientation for a little bit, which can cause orientation
  47. // changes to lag, so we'd like to keep it always on.  (It will
  48. // still be turned off when the screen is off.)
  49. return false ;
  50. }
  51. return true ;
  52. }

复制代码

Java代码

  1. class MyOrientationListener extends WindowOrientationListener {
  2. MyOrientationListener(Context context) {
  3. super(context);
  4. }
  5. @Override
  6. publicvoid onOrientationChanged(int rotation) {
  7. // Send updates based on orientation value
  8. if (true) Log.i(TAG, "onOrientationChanged, rotation changed to " +rotation);
  9. try {
  10. mWindowManager.setRotation(rotation, false,
  11. mFancyRotationAnimation);
  12. } catch (RemoteException e) {
  13. // Ignore
  14. }
  15. }
  16. }
  17. MyOrientationListener mOrientationListener;
  18. boolean useSensorForOrientationLp(int appOrientation) {
  19. if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
  20. returntrue;
  21. }
  22. if (mAccelerometerDefault != 0 && (
  23. appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER ||
  24. appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
  25. returntrue;
  26. }
  27. returnfalse;
  28. }
  29. /*
  30. * We always let the sensor be switched on by default except when
  31. * the user has explicitly disabled sensor based rotation or when the
  32. * screen is switched off.
  33. */
  34. boolean needSensorRunningLp() {
  35. if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
  36. // If the application has explicitly requested to follow the
  37. // orientation, then we need to turn the sensor or.
  38. returntrue;
  39. }
  40. if (mAccelerometerDefault == 0) {
  41. // If the setting for using the sensor by default is enabled, then
  42. // we will always leave it on.  Note that the user could go to
  43. // a window that forces an orientation that does not use the
  44. // sensor and in theory we could turn it off... however, when next
  45. // turning it on we won't have a good value for the current
  46. // orientation for a little bit, which can cause orientation
  47. // changes to lag, so we'd like to keep it always on.  (It will
  48. // still be turned off when the screen is off.)
  49. returnfalse;
  50. }
  51. returntrue;
  52. }

复制代码

在 WindowOrientationListener(见文件 javaframeworks/base/core/java/android/view/WindowOrientationListener.java)中会监听Sensor的值,对旋转方向进行判断,然后调用抽象方法 onOrientationChanged,因此,只要在子类 Listener中重新实现这个函数即可对四个不同方向做出响应(见上面让屏幕旋转即是一例)。

遗憾的是在 Donut和 Éclair中,对旋转方向的识别只给出了 90度旋转,在 Froyo中增加了一个 270度旋转,不支持 180度即倒立的操作。

可以在修改下面代码,判断来自于 Gsensor的值,识别出旋转方向:

  1. public void onSensorChanged(SensorEvent event) {
  2. float [] values = event.values;
  3. float X = values[_DATA_X];
  4. float Y = values[_DATA_Y];
  5. float Z = values[_DATA_Z];
  6. float OneEightyOverPi = 57 .29577957855f;
  7. float gravity = ( float ) Math.sqrt(X*X+Y*Y+Z*Z);
  8. float zyangle = ( float )Math.asin(Z/gravity)*OneEightyOverPi;
  9. int rotation = - 1 ;
  10. if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) {
  11. // Check orientation only if the phone is flat enough
  12. // Don't trust the angle if the magnitude is small compared to the y value
  13. float angle = ( float )Math.atan2(Y, -X) * OneEightyOverPi;
  14. int orientation = 90 - ( int )Math.round(angle);
  15. // normalize to 0 - 359 range
  16. while (orientation >= 360 ) {
  17. orientation -= 360 ;
  18. }
  19. while (orientation < 0 ) {
  20. orientation += 360 ;
  21. }
  22. // Orientation values between  LANDSCAPE_LOWER and PL_LOWER
  23. // are considered landscape.
  24. // Ignore orientation values between 0 and LANDSCAPE_LOWER
  25. // For orientation values between LP_UPPER and PL_LOWER,
  26. // the threshold gets set linearly around PIVOT.
  27. if ((orientation >= PL_LOWER) && (orientation <= LP_UPPER)) {
  28. float threshold;
  29. float delta = zyangle - PIVOT;
  30. if (mSensorRotation == Surface.ROTATION_90) {
  31. if (delta < 0 ) {
  32. // Delta is negative
  33. threshold = LP_LOWER - (LP_LF_LOWER * delta);
  34. } else {
  35. threshold = LP_LOWER + (LP_LF_UPPER * delta);
  36. }
  37. rotation = (orientation >= threshold) ? Surface.ROTATION_0 : Surface.ROTATION_90;
  38. } else {
  39. if (delta < 0 ) {
  40. // Delta is negative
  41. threshold = PL_UPPER+(PL_LF_LOWER * delta);
  42. } else {
  43. threshold = PL_UPPER-(PL_LF_UPPER * delta);
  44. }
  45. rotation = (orientation <= threshold) ? Surface.ROTATION_90: Surface.ROTATION_0;
  46. }
  47. } else if ((orientation >= LANDSCAPE_LOWER) && (orientation < LP_LOWER)) {
  48. rotation = Surface.ROTATION_90;
  49. } else if ((orientation >= PL_UPPER) || (orientation <= PORTRAIT_LOWER)) {
  50. rotation = Surface.ROTATION_0;
  51. }
  52. if ((rotation != - 1 ) && (rotation != mSensorRotation)) {
  53. mSensorRotation = rotation;
  54. onOrientationChanged(mSensorRotation);
  55. }
  56. }
  57. }

复制代码

Java代码

  1. publicvoid onSensorChanged(SensorEvent event) {
  2. float[] values = event.values;
  3. float X = values[_DATA_X];
  4. float Y = values[_DATA_Y];
  5. float Z = values[_DATA_Z];
  6. float OneEightyOverPi = 57.29577957855f;
  7. float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
  8. float zyangle = (float)Math.asin(Z/gravity)*OneEightyOverPi;
  9. int rotation = -1;
  10. if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) {
  11. // Check orientation only if the phone is flat enough
  12. // Don't trust the angle if the magnitude is small compared to the y value
  13. float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
  14. int orientation = 90 - (int)Math.round(angle);
  15. // normalize to 0 - 359 range
  16. while (orientation >= 360) {
  17. orientation -= 360;
  18. }
  19. while (orientation < 0) {
  20. orientation += 360;
  21. }
  22. // Orientation values between  LANDSCAPE_LOWER and PL_LOWER
  23. // are considered landscape.
  24. // Ignore orientation values between 0 and LANDSCAPE_LOWER
  25. // For orientation values between LP_UPPER and PL_LOWER,
  26. // the threshold gets set linearly around PIVOT.
  27. if ((orientation >= PL_LOWER) && (orientation <= LP_UPPER)) {
  28. float threshold;
  29. float delta = zyangle - PIVOT;
  30. if (mSensorRotation == Surface.ROTATION_90) {
  31. if (delta < 0) {
  32. // Delta is negative
  33. threshold = LP_LOWER - (LP_LF_LOWER * delta);
  34. } else {
  35. threshold = LP_LOWER + (LP_LF_UPPER * delta);
  36. }
  37. rotation = (orientation >= threshold) ? Surface.ROTATION_0 : Surface.ROTATION_90;
  38. } else {
  39. if (delta < 0) {
  40. // Delta is negative
  41. threshold = PL_UPPER+(PL_LF_LOWER * delta);
  42. } else {
  43. threshold = PL_UPPER-(PL_LF_UPPER * delta);
  44. }
  45. rotation = (orientation <= threshold) ? Surface.ROTATION_90: Surface.ROTATION_0;
  46. }
  47. } elseif ((orientation >= LANDSCAPE_LOWER) && (orientation < LP_LOWER)) {
  48. rotation = Surface.ROTATION_90;
  49. } elseif ((orientation >= PL_UPPER) || (orientation <= PORTRAIT_LOWER)) {
  50. rotation = Surface.ROTATION_0;
  51. }
  52. if ((rotation != -1) && (rotation != mSensorRotation)) {
  53. mSensorRotation = rotation;
  54. onOrientationChanged(mSensorRotation);
  55. }
  56. }
  57. }

复制代码

在Froyo中,对上述算法进行了修改,让其报出270度的旋转方向。

Android Sensor 屏幕360度旋转实现

修改下面函数

  1. void android.view.WindowOrientationListener SensorEventListenerImp.onSensorChanged(android.hardware.SensorEvent event)
  2. float[] values = event.values;
  3. float X = values[_DATA_X];
  4. float Y = values[_DATA_Y];
  5. float Z = values[_DATA_Z];
  6. //For fixing the problem of Sensor change the window orientation error but the sensor game is no problem.
  7. float OneEightyOverPi = 57.29577957855f;
  8. float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
  9. float zyangle = (float)Math.asin(Z/gravity)*OneEightyOverPi;
  10. int rotation = -1;
  11. if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) {
  12. // Check orientation only if the phone is flat enough
  13. // Don't trust the angle if the magnitude is small compared to the y value
  14. float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
  15. int orientation = 90 - (int)Math.round(angle);
  16. // normalize to 0 - 359 range
  17. while (orientation >= 360) {
  18. orientation -= 360;
  19. }
  20. while (orientation < 0) {
  21. orientation += 360;
  22. }
  23. Log.i("Tiger","orientation="+orientation);
  24. //确定由角度与屏幕方向的对应范围
  25. if(orientation > 325 || orientation <= 45){
  26. rotation = Surface.ROTATION_0;
  27. }else if(orientation > 45 && orientation <= 135){
  28. rotation = Surface.ROTATION_270;
  29. }else if(orientation > 135 && orientation < 225){
  30. rotation = Surface.ROTATION_180;
  31. }else {
  32. rotation = Surface.ROTATION_90;
  33. }
  34. Log.i("Tiger","mSensorRotation="+mSensorRotation+"    , rotation="+rotation);
  35. if ((rotation != -1) && (rotation != mSensorRotation)) {
  36. mSensorRotation = rotation;
  37. onOrientationChanged(mSensorRotation);
  38. }
  39. }

复制代码

利用GSensor让屏幕实现360度旋转相关推荐

  1. 【计算机图形】制作能够利用鼠标拖拽实现360度旋转的3D人体模型flash文件

    前段时间,由于要对参加挑战杯的系统进行改善,老师要求我们在系统当中添加一个可旋转的3D人体模型,于是俺陷入了深深的思考当中.之前一直都没有接触过3D模型的制作,而且老师这回给的时间又特紧,当时那个急呀 ...

  2. jQuery 图像 360 度旋转插件

    13 款最热门的 jQuery 图像 360 度旋转插件推荐 时间:02月07日 在 web 页面上使用 jQuery 图像 360 度旋转插件是最美也是最方便的显示图像的方式.这些超级棒的 360° ...

  3. 【精心挑选】10款基于 jQuery 的图片360度旋转插件

    之前的文章向大家分享了实现网站功能的各种优秀的 jQuery 插件,今天这篇文章向大家推荐10款基于 jQuery 的图片360度旋转插件,同时还有非常详细的制作教程可以学习和参考.图片旋转展示是一种 ...

  4. 旋转矩阵中6保6_40岁阿姨发明新型手推车,可以360度旋转,干活效率提升6倍

    科技,其实很有趣!大家好,欢迎收看本期木易机械 40岁阿姨发明新型手推车,能够360度旋转,干活效率提升6倍 科技的发展是我们有目共睹的,不仅是那些震惊世界的发明,就在我们的日常生活中,也有很多的小发 ...

  5. 360度旋转图片小特效

    现在,在这个网络发达的时代,一些电子商务公司,需要将自己线上的产品给买家或用户看,为了能让用户了解的更全面,那么把一个物件的产品要展示到方方面面,就要运用到360度旋转图片特效,因为上次有朋友叫我帮她 ...

  6. js产品360度旋转预览图片插件

    下载地址 纯js实现的产品360度旋转预览图片插件.该js特效仅使用120行代码,即可实现通过滑块.或鼠标手动360度旋转图片,以及自动360度旋转图片的效果. dd:

  7. 精心挑选10款基于 jQuery 的图片360度旋转插件

    之前的文章向大家分享了实现网站功能的各种优秀的 jQuery 插件,今天这篇文章向大家推荐10款基于 jQuery 的图片360度旋转插件,同时还有非常详细的制作教程可以学习和参考.图片旋转展示是一种 ...

  8. 360环物如何发布html,制作网页上的360度旋转全景图PixMaker使用详细教程

    PixMaker是一个简单方便的360度全景图片制作软件,它可以将描写一个环型场景的多个连续图片无缝地接合在一起,形成一个360度"场景"图片.可以在网页上播放,使你的页面更加生动 ...

  9. 图片可以360度旋转类似广告代码

    图片可以360度旋转类似广告代码 <div style='height:60px; line-height:50px; text-align:center; color: #b2b2b2;'&g ...

  10. html5图片自动翻转,纯js实现360度旋转预览图片特效

    这是一款纯js实现360度旋转预览图片特效.该js特效仅使用120行代码,即可实现通过滑块.或鼠标手动360度旋转图片,以及自动360度旋转图片的效果. 使用方法 HTML结构 import Roll ...

最新文章

  1. 03-MySQL多表操作
  2. 设计一个shell程序,在/userdata目录下建立50个目录,并对每个目录给754权限!
  3. 11月25日struts培训日记
  4. MYSQL jdbc autoReconnect
  5. 无限复活服务器,绝地求生无限复活模式怎么玩 无限复活新手教程
  6. php mongo sort -1出错,mongoDB排序引起的ERROR
  7. element UI Cascader 级联选择器 动态加载次级选项
  8. C#计算程序的运行时间
  9. 【报告分享】激荡2020--吴晓波疫情特别演讲PPT.pdf(附下载链接)
  10. 20201023:力扣第37场双周赛(上)
  11. 我是如何在GitHub上开源一个项目的(截图说明) (VS2010可以安装git插件)
  12. iOS xcode 9 注释快捷键
  13. AT91SAM7SE应用 -- UART
  14. hrbust 1699 矩阵游戏【枚举找规律】
  15. Java:Java实现简单闹钟设计
  16. PTA 1088三人行
  17. 网易2016实习研发工程师编程题——寻找第K大
  18. Java模拟项目开发(快递柜)
  19. 深入Vue底层,手写一个vuex
  20. 用Python玩转数据(三)

热门文章

  1. Redis主从复制原理
  2. 袁老走好,谢谢您!我辈也当自强。
  3. 360wifi驱动linux驱动安装,ubuntu安装360随身wifi驱动
  4. 公开处刑,专家博主开发游戏的老王专栏抄袭事件始末
  5. python—文件处理
  6. python自动化测试-最常用的自动化测试框架
  7. Robotframework(三)常用API介绍
  8. 互联网思维——极致思维
  9. 【会议预告】第七届上海国际皮革展览会
  10. MPLS排错练习题分享