在看android自带的samples源码里面的AccelerometerPlayActivity时,看到下面这段代码,很不理解

public void onSensorChanged(SensorEvent event) {if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){return;}switch (mDisplay.getRotation()) {    case Surface.ROTATION_0://手机处于正常状态                  mSensorX = event.values[0];                mSensorY = event.values[1];                break;            case Surface.ROTATION_90://手机旋转90度                  mSensorX = -event.values[1];                mSensorY = event.values[0];                break;            case Surface.ROTATION_180:                mSensorX = -event.values[0];                mSensorY = -event.values[1];                break;            case Surface.ROTATION_270:                mSensorX = event.values[1];                mSensorY = -event.values[0];                break;}}

经过查阅资料大体了解了
通过AndroidManifest.xml设置屏幕方向的话,安装后就不能改变,而程序内部设置屏幕方向就不会有这个限制。主要靠这两个API:getRequestedOrientation()和setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)这两个API通过ActivityManagerService.java的转换后,实际上都是调用的WindowManagerService的同名方法。

每个Activity在WindowManagerService端都有一个AppWindowToken做代表,而屏幕的方向信息就存储在这里。
PhoneWindowManager会自动根据屏幕物理特性决定屏幕方向,看这段代码:

if (mPortraitRotation < 0) {      // Initialize the rotation angles for each orientation once.       Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))              .getDefaultDisplay();      if (d.getWidth() > d.getHeight()) {          mPortraitRotation = Surface.ROTATION_90;          mLandscapeRotation = Surface.ROTATION_0;          mUpsideDownRotation = Surface.ROTATION_270;          mSeascapeRotation = Surface.ROTATION_180;      } else {          mPortraitRotation = Surface.ROTATION_0;          mLandscapeRotation = Surface.ROTATION_90;          mUpsideDownRotation = Surface.ROTATION_180;          mSeascapeRotation = Surface.ROTATION_270;      }  }  

这里的d.getWidth() 和 d.getHeight()得到的是物理屏幕的宽高。一般来说,平板和手机的是不一样的。

平板是宽比高大(0度时位于landscape模式,右转90度进入porit模式),手机是高比宽大(0度是位于porit模式,右转90度进入landscape模式)。如果应用程序只关心当前是横屏还是竖屏,而不直接使用传感器的话,没什么问题。如果像依靠重力感应的游戏那样直接使用传感器,就需要自己根据物理屏幕的坐标系对传感器数据做转化,否则就会出现坐标系混乱的问题。

如果没有没有通过上面的d.getWidth()和d.getHeight()来检测设备的物理屏幕从确定哪个是landscape和porit模式,而是直接假设设备是和手机一样的模式。由于游戏运行在landscape模式下,它们都把传感器数据右转90度。这样做法在手机上是没有问题,但在平板电脑上是不应该转化的,这是因为物理屏幕宽比高大的情况下,默认就是landscape模式。

现在回到源代码,在这里没有区分手机和平板,仅仅是用来转换加速度的方向而已,也没有必要区分.

case Surface.ROTATION_0://手机处于正常状态                mSensorX = event.values[0];                mSensorY = event.values[1];                break;

这段就是如果手机的方向没有旋转,不管手机处于landscape还是porit模式,加速度的方向都不用变,而下面,如果手机旋转了180度,说明x轴和y轴的方向完全反过来了,这时候对于加速度的方向就要调整到反向.还有90度和270度的情况都类似.

case Surface.ROTATION_180:                mSensorX = -event.values[0];                mSensorY = -event.values[1];                break;



更多相关文章

  1. android EditText 添加图片表情以及在四个方向上绘制图片
  2. android获得手机的电量
  3. android获得手机的电量
  4. Android壁纸服务WallpaperManagerService
  5. android 环境配置
  6. android修改手机默认音量配置
  7. Android手机用户隐私获取,包括读取通讯录、读取通话记录、读取浏
  8. Android(安卓)如何实现屏幕转换方向
  9. Supporting Multiple Screens(支持Android各种屏幕尺寸)

随机推荐

  1. Mysql查询需要太多时间来执行。
  2. 做了一个工程(VB+SQLServer)后,老板又要我将
  3. kali攻防第6章 SQLMAP介绍及ASP网站渗透
  4. sql2000 数据库文件突然丢失
  5. SQL Server2008清除数据库日志
  6. esql的查询结果集 ObjectQuery
  7. SQL Server 一些关键字详解(一)
  8. 备份SQL Server数据库
  9. LINUX下用SHELL脚本执行带输入输出参数的
  10. C#中操作Oracle时的SQL语句参数的用法