如何获得Androidios开发获取设备方向的当前方向ActivityInfo.SCREEN

获取Android设备的方向
带有g-sensor的Android设备上可通过API获取到设备的运动加速度,应用程序通过一些假设和运算,可以从加速度计算出设备的方向
获取设备运动加速度的基本代码是:
& & & & SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
& & & & sm.registerListener(new SensorEventListener() {
& & & & & & public void onSensorChanged(SensorEvent event) {
& & & & & & & & if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
& & & & & & & & & &
& & & & & & & & }
& & & & & & & & float[] values = event.
& & & & & & & & float ax = values[0];
& & & & & & & & float ay = values[1];
& & & & & & & & float az = values[2];
& & & & & & & & // TODO Have fun with the acceleration components...
& & & & & & & &&
& & & & & & }
& & & & & & public void onAccuracyChanged(Sensor sensor, int accuracy) {
& & & & & & }
& & & & }, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
SendorEventListener 通过 SendorEvent 回调参数获得当前设备在坐标系x、y、z轴上的加速度分量。SensorEvent 的 api doc 中定义了这里使用的坐标系为:
我暂且称之为“设备坐标系”吧,设备坐标系是固定于设备的,与设备的方向(在世界坐标系中的朝向)无关
精确地说,Sensor Event 所提供的加速度数值,是设备以地球为参照物的加速度减去重力加速度的叠加后的值。我是这样理解的:当以重力加速度g向地面作自由落体运动时,手机处于失重状态,g-sensor以这种状态作为加速度的0;而当手机处于静止状态(相对于地面)时,为了抵御自由落体运动的趋势,它有一个反向(向上)的g的加速度。因此,得出一个结论:当设备处于静止或者匀速运动状态时,它有一个垂直地面向上的g的加速度,这个g投影到设备坐标系的x、y、z轴上,就是SensorEvent 提供给我们的3个分量的数值。在“设备处于静止或者匀速运动状态”的假设的前提下,可以根据SensorEvent所提供的3个加速度分量计算出设备相对于地面的方向
前面所提到的“设备的方向”是一个含糊的说法。这里我们精确地描述设备方向为:以垂直于地面的方向为正方向,用设备坐标系x、y、z轴与正方向轴之间的夹角Ax、Ay、Az来描述设备的方向,如下图所示。可以看出,设备还有一个自由度,即:绕着正方向轴旋转,Ax、Ay、Az不变。但Ax、Ay、Az的约束条件,对于描述设备相对于正方向轴的相对位置已经足够了。如果需要完全约束设备相对于地面的位置,除了正方向轴外,还需要引入另一个参照轴,例如连接地球南、北极的地轴(如果设备上有地磁强度Sensor,则可满足该约束条件)
Ax、Ay、Az的范围为[0, 2*PI)。例如,当Ay=0时,手机y轴竖直向上;Ay=PI时,手机y轴向下;Ay=PI/2时,手机水平、屏幕向上;Ay=3*PI/2时,手机水平、屏幕向下
根据3D矢量代数的法则,可知:
Gx=g*cos(Ax)
Gy=g*cos(Ay)
Gz=g*cos(Az)
g^2=Gz^2+Gy^2+Gz^2
因此,根据Gx、Gy、Gz,可以计算出Ax、Ay、Az
在x-y平面上的2D简化
当Ax、Ay确定时,Az有两种可能的值,二者相差PI,确定了设备屏幕的朝向是向上还是向下。大多数情况下,我们只关心Ax、Ay(因为程序UI位于x-y平面?),而忽略Az,例如,Android的屏幕自动旋转功能,不管使用者是低着头看屏幕(屏幕朝上)、还是躺在床上看(屏幕朝下),UI始终是底边最接近地心的方向
那么我们设Gx与Gy的矢量和为g'(即:g在x-y平面上的投影),将计算简化到x-y 2D平面上。记y轴相对于g'的偏角为A,以A来描述设备的方向。以逆时针方向为正,A的范围为[0, 2*PI)
g'^2=Gx^2+Gy^2
Gy=g'*cos(A)
Gx=g'*sin(A)
g'=sqrt(Gx^2+Gy^2)
A=arccos(Gy/g')
由于arccos函数值范围为[0, PI];而A&PI时,Gx=g'*sin(A)&0,因此,根据Gx的符号分别求A的值为:
当Gx&=0时,A=arccos(Gy/g')
当Gx&0时,A=2*PI-arccos(Gy/g')
注意:由于cos函数曲线关于直线x=n*PI 对称,因此arccos函数的曲线如果在y轴方向[0, 2*PI]范围内补全的话,则关于直线y=PI对称,因此有上面当Gx&0时的算法
考虑应用程序的屏幕旋转
前面计算出了Android设备的“物理屏幕”相对于地面的旋转角度,而应用程序的UI又相对于“物理屏幕”存在0、90、180、270度4种可能的旋转角度,要综合考虑进来。也就是说:
UI相对于地面的旋转角度=物理屏幕相对于地面的旋转角度-UI相对于物理屏幕的旋转角度
Android应用获取屏幕旋转角度的方法为:
& & & & int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
& & & & int degree= 90 *
& & & & float rad = (float)Math.PI / 2 *
根据上面的算法,我写了一个“不倒翁”的Demo,当设备旋转时,不倒翁始终是站立的。软件市场上不少“水平尺”一类的应用,其实现原理应该是与此相同的
Activity实现了SensorEventListener,并且注册到SensorManager。同时设置屏幕方向固定为LANDSCAPE:
& & private GSensitiveView gsV
& & private SensorM
& & @Override
& & public void onCreate(Bundle savedInstanceState) {
& & & & setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
& & & & super.onCreate(savedInstanceState);
& & & & gsView = new GSensitiveView(this);
& & & & setContentView(gsView);
& & & & sm = (SensorManager) getSystemService(SENSOR_SERVICE);
& & & & sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
& & @Override
& & protected void onDestroy() {
& & & & sm.unregisterListener(this);
& & & & super.onDestroy();
当g-sensor数据变化时的回调如下。这里就是根据我们前面推论的算法计算出UI旋转的角度,并且调用GSensitiveView.setRotation()方法通知View更新
& & public void onSensorChanged(SensorEvent event) {
& & & & if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
& & & & & &
& & & & float[] values = event.
& & & & float ax = values[0];
& & & & float ay = values[1];
& & & & double g = Math.sqrt(ax * ax + ay * ay);
& & & & double cos = ay /
& & & & if (cos & 1) {
& & & & & & cos = 1;
& & & & } else if (cos & -1) {
& & & & & & cos = -1;
& & & & double rad = Math.acos(cos);
& & & & if (ax & 0) {
& & & & & & rad = 2 * Math.PI -
& & & & int uiRot = getWindowManager().getDefaultDisplay().getRotation();
& & & & double uiRad = Math.PI / 2 * uiR
& & & & rad -= uiR
& & & & gsView.setRotation(rad);
GSensitiveView是扩展ImageView的自定义类,主要是根据旋转角度绘制图片:
& & private static class GSensitiveView extends ImageView {
& & & & private B
& & & & pri
& & & & private P
& & & & public GSensitiveView(Context context) {
& & & & & & super(context);
& & & & & & BitmapDrawable drawble = (BitmapDrawable) context.getResources().getDrawable(R.drawable.budaow);
& & & & & & image = drawble.getBitmap();
& & & & & & paint = new Paint();
& & & & @Override
& & & & protected void onDraw(Canvas canvas) {
& & & & & & // super.onDraw(canvas);
& & & & & & double w = image.getWidth();
& & & & & & double h = image.getHeight();
& & & & & & Rect rect = new Rect();
& & & & & & getDrawingRect(rect);
& & & & & & int degrees = (int) (180 * rotation / Math.PI);
& & & & & & canvas.rotate(degrees, rect.width() / 2, rect.height() / 2);
& & & & & & canvas.drawBitmap(image, //
& & & & & & & & & & (float) ((rect.width() - w) / 2),// &
& & & & & & & & & & (float) ((rect.height() - h) / 2),// &
& & & & & & & & & & paint);
& & & & public void setRotation(double rad) {
& & & & & & rotation =
& & & & & & invalidate();
本文已收录于以下专栏:
相关文章推荐
如果用户开启了设置里的屏幕旋转,Android中处理横竖屏切换,通常的做法是在AndroidManifest.xml中定义android:configChanges=&orientation|keyb...
转自:/bpasser/archive//2214517.html
带有g-sensor的Android设备上可通过API获取到设...
带有g-sensor的Android设备上可通过API获取到设备的运动加速度,应用程序通过一些假设和运算,可以从加速度计算出设备的方向
获取设备运动加速度的基本代码是:
带有g-sensor的Android设备上可通过API获取到设备的运动加速度,应用程序通过一些假设和运算,可以从加速度计算出设备的方向
获取设备运动加速度的基本代码是:
晚上好~今天继续给大家分享一下第二个重要的感应器,其实获取方向本应该很简单的事情,在文章一中看到 有个TYPE_ORIENTATION 关键字,说明可以直接获取设备的移动方向,但是最新版的SDK加上了...
一、拍照时竖直预览:
实现原理①:设置拍照的Activity为横屏
实现①:在AndroidManifest.xml相应的activity添加一句 android:screenOrientatio...
在2.2中可以设置屏幕的方向为反转横屏:setRequestedOrientation(8);,因为系统没有公开出这个参数的设置,不过在源码里面已经定义了SCREEN_ORIENTATION_REVE...
MediaMetadataRetriever retr = new MediaMetadataRetriever();
retr.setDataSource(videoPath);
两种方法获取Android设备的三轴方向
他的最新文章
讲师:姜飞俊
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Android开发实践:屏幕旋转的处理_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Android开发实践:屏幕旋转的处理
来源:Linux社区&
作者:ticktick
最近开发 Camera相关的程序,被屏幕旋转搞得头大,一方面得考虑屏幕旋转后布局的变化,另一方面得搞清楚屏幕的旋转方向、角度与Camera的Preview角度的关系。本来通过重载Activity的onConfigurationChanged方法,可以检测到屏幕旋转,但发现有一个问题,它只能检测水平方向与垂直方向的切换,无法检测180度的跳转(例如:水平方向突然转180度到水平方向),所以最后不得不换成OrientationEventListener方法来解决问题。在这里分享下经验,并就此顺便总结下Android开发中屏幕旋转的处理吧。
1. 不做任何处理的情况下
如果没有针对性地做任何处理的话,默认情况下,当用户手机的重力感应器打开后,旋转屏幕方向,会导致app的当前activity发生onDestroy-& onCreate,会重新构造当前activity和界面布局,很多横屏/竖屏的布局如果没有很好的设计的话,转换为竖屏/横屏后,会显示地很难看。
如果想很好地支持屏幕旋转,则建议在res中建立layout-land和layout-port两个文件夹,把横屏和竖屏的布局文件放入对应的layout文件夹中。
2. 如何设置固定的屏幕方向
在AndroidManifest.xml对应的 activity 属性中,添加:
android:screenOrientation="landscape"& //横屏 android:screenOrientation="portrait"& //竖屏
那么,默认的情况下,应用启动后,会固定为指定的屏幕方向,即使屏幕旋转,Activity也不会出现销毁或者转向等任何反应。
3. 强制开启屏幕旋转效果
如果用户的手机没有开启重力感应器或者在AndroidManifest.xml中设置了android:screenOrientation,默认情况下,该Activity不会响应屏幕旋转事件。如果在这种情况下,依然希望Activity能响应屏幕旋转,则添加如下代码:
// activity的 onCreate 函数中 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
4. 屏幕旋转时,不希望activity被销毁
如果希望捕获屏幕旋转事件,并且不希望activity 被销毁,方法如下:
(1)在AndroidManifest.xml对应的activity属性中,添加:
android:configChanges="orientation|screenSize"
(2)在对应的activity中,重载函数onConfigurationChanged
@Overridepublic voidonConfigurationChanged(Configuration newConfig) { & & super.onConfigurationChanged(newConfig); }
在该函数中可以通过两种方法检测当前的屏幕状态:
判断newConfig是否等于Configuration.ORIENTATION_LANDSCAPE,Configuration.ORIENTATION_PORTRAIT
当然,这种方法只能判断屏幕是否为横屏,或者竖屏,不能获取具体的旋转角度。
调用this.getWindowManager().getDefaultDisplay().getRotation();
该函数的返回值,有如下四种:
Surface.ROTATION_0,Surface.ROTATION_90,Surface.ROTATION_180,Surface.ROTATION_270
其中,Surface.ROTATION_0 表示的是手机竖屏方向向上,后面几个以此为基准依次以顺时针90度递增。
(3) 这种方法的Bug
最近发现这种方法有一个Bug,它只能一次旋转90度,如果你突然一下子旋转180度,onConfigurationChanged函数不会被调用。
相关阅读:
Android屏幕分辨率、密度的正确获取&
更多Android相关信息见 专题页面
接下来请看第2页精彩内容:
相关资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款Activity在屏幕显示的方向切换
  android:screenOrientation和android:configChanges
  Activity的内容在屏幕上的显示方向,有时会旋转。
  activity内容方向的设定与转换,以及相关的生命周期处理,是与Manifest中activity标签下的下面两个属性相关的:
  即android:screenOrientation和android:configChanges
  (链接中有所有属性的说明:)
Android的屏幕方向状态是下列的值之一:
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_USER
ActivityInfo.SCREEN_ORIENTATION_BEHIND
ActivityInfo.SCREEN_ORIENTATION_SENSOR
ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
方向属性设置
  我们可以利用android:screenOrientation属性强制锁定屏幕的方向。
  也可以把方向设定为随着传感器而变化。
  下面是这个属性可以设定的值。
&&&&&&&&&&&&&&&&&&&&&&&&
  在程序中也可以调用setRequestedOrientation方法进行屏幕方向的动态设置,具体请参见文后参考资料的第二个链接。
方向转换与生命周期
  当在manifest中把android:screenOrientation的属性设为sensor时:
android:name=".HelloOrientationActivity"
android:label="@string/title_activity_hello_orientation"
android:screenOrientation="sensor" &
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&/activity&
  运行程序可以发现Activity的显示内容的确会随着手机的姿态进行横竖屏的切换。
  但是观察生命周期的相关函数调用Log,发现在进行横竖屏切换的时候整个activity会调用onPause()、onStop()、onDestroy()然后重新调用onCreate()、onResume()。
  并且此时覆写onConfigurationChanged()是不会被调用的。&
  查看android:configChanges部分的文档可以发现,默认情况下activity是会关闭并且重启的,但是通过这个属性可以阻止activity的重启行为,让activity保持运行,并且activity的将会被调用。
  (默认情况下这个方法是不会被调用的)。
  但是官方不建议用这个属性来处理,建议看看&&。
  这个属性设置的各种值就是要阻止activity重启的各种情况。
  比如设置为:
android:name=".HelloOrientationActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/title_activity_hello_orientation"
android:screenOrientation="sensor" &
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&/activity&
  这样在屏幕旋转并切换横竖屏的时候,发现activity并没有被重建,而是调用了方法。
补充一下:
  当android:targetSdkVersion大于等于13时,&要想onConfigurationChanged()方法被调用,mainfest中需要这样写:
android:name="com.example.helloorientation.MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:screenOrientation="sensor" &
  附上测试程序代码:
package com.example.hell
import android.app.A
import android.content.res.C
import android.os.B
import android.util.L
import android.widget.TextV
public class HelloOrientationActivity extends Activity
private static final String LOG_TAG = "Hello Orientation";
public void onCreate(Bundle savedInstanceState)
Log.i(LOG_TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_orientation);
protected void onResume()
Log.i(LOG_TAG, "onResume");
super.onResume();
protected void onPause()
Log.i(LOG_TAG, "onPause");
super.onPause();
protected void onStop()
Log.i(LOG_TAG, "onStop");
super.onStop();
protected void onDestroy()
Log.i(LOG_TAG, "onDestroy");
super.onDestroy();
public void onConfigurationChanged(Configuration newConfig)
Log.i(LOG_TAG, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
Activity代码
&manifest xmlns:android="/apk/res/android"
package="com.example.helloactivityorientation"
android:versionCode="1"
android:versionName="1.0" &
android:minSdkVersion="8"
android:targetSdkVersion="15" /&
&application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" &
android:name=".HelloOrientationActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/title_activity_hello_orientation"
android:screenOrientation="sensor" &
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&/activity&
&/application&
&/manifest&
Manifest代码
  布局代码略,能看出正反向就行,TextView里写个HelloWorld就可以了。
  官方文档中activity标签下的元素说明:
  一个英文的关于屏幕方向的文章:
阅读(...) 评论()获取Android设备的方向 ,使用加速度重力传感器
带有g-sensor的Android设备上可通过API获取到设备的运动加速度,应用程序通过一些假设和运算,可以从加速度计算出设备的方向
获取设备运动加速度的基本代码是:
SensorManager sm = (SensorManager) context.
带有g-sensor的Android设备上可通过API获取到设备的运动加速度,应用程序通过一些假设和运算,可以从加速度计算出设备的方向
获取设备运动加速度的基本代码是:
SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
sm.registerListener(new SensorEventListener() {
public void onSensorChanged(SensorEvent event) {
if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
float[] values = event.
float ax = values[0];
float ay = values[1];
float az = values[2];
// TODO Have fun with the acceleration components...
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
SendorEventListener 通过 SendorEvent 回调参数获得当前设备在坐标系x、y、z轴上的加速度分量。SensorEvent 的 api doc 中定义了这里使用的坐标系为:
我暂且称之为“设备坐标系”吧,设备坐标系是固定于设备的,与设备的方向(在世界坐标系中的朝向)无关
精确地说,Sensor Event 所提供的加速度数值,是设备以地球为参照物的加速度减去重力加速度的叠加后的值。我是这样理解的:当以重力加速度g向地面作自由落体运动时,手机处于失重状态,g-sensor以这种状态作为加速度的0;而当手机处于静止状态(相对于地面)时,为了抵御自由落体运动的趋势,它有一个反向(向上)的g的加速度。因此,得出一个结论:当设备处于静止或者匀速运动状态时,它有一个垂直地面向上的g的加速度,这个g投影到设备坐标系的x、y、z轴上,就是SensorEvent 提供给我们的3个分量的数值。在“设备处于静止或者匀速运动状态”的假设的前提下,可以根据SensorEvent所提供的3个加速度分量计算出设备相对于地面的方向
前面所提到的“设备的方向”是一个含糊的说法。这里我们精确地描述设备方向为:以垂直于地面的方向为正方向,用设备坐标系x、y、z轴与正方向轴之间的夹角Ax、Ay、Az来描述设备的方向,如下图所示。可以看出,设备还有一个自由度,即:绕着正方向轴旋转,Ax、Ay、Az不变。但Ax、Ay、Az的约束条件,对于描述设备相对于正方向轴的相对位置已经足够了。如果需要完全约束设备相对于地面的位置,除了正方向轴外,还需要引入另一个参照轴,例如连接地球南、北极的地轴(如果设备上有地磁强度Sensor,则可满足该约束条件)
Ax、Ay、Az的范围为[0, 2*PI)。例如,当Ay=0时,手机y轴竖直向上;Ay=PI时,手机y轴向下;Ay=PI/2时,手机水平、屏幕向上;Ay=3*PI/2时,手机水平、屏幕向下
根据3D矢量代数的法则,可知:
Gx=g*cos(Ax)
Gy=g*cos(Ay)
Gz=g*cos(Az)
g^2=Gz^2+Gy^2+Gz^2
因此,根据Gx、Gy、Gz,可以计算出Ax、Ay、Az
在x-y平面上的2D简化
当Ax、Ay确定时,Az有两种可能的值,二者相差PI,确定了设备屏幕的朝向是向上还是向下。大多数情况下,我们只关心Ax、Ay(因为程序UI位于x-y平面?),而忽略Az,例如,Android的屏幕自动旋转功能,不管使用者是低着头看屏幕(屏幕朝上)、还是躺在床上看(屏幕朝下),UI始终是底边最接近地心的方向
那么我们设Gx与Gy的矢量和为g'(即:g在x-y平面上的投影),将计算简化到x-y 2D平面上。记y轴相对于g'的偏角为A,以A来描述设备的方向。以逆时针方向为正,A的范围为[0, 2*PI)
g'^2=Gx^2+Gy^2
Gy=g'*cos(A)
Gx=g'*sin(A)
g'=sqrt(Gx^2+Gy^2)
A=arccos(Gy/g')
由于arccos函数值范围为[0, PI];而A&PI时,Gx=g'*sin(A)&0,因此,根据Gx的符号分别求A的值为:
当Gx&=0时,A=arccos(Gy/g')
当Gx&0时,A=2*PI-arccos(Gy/g')
注意:由于cos函数曲线关于直线x=n*PI 对称,因此arccos函数的曲线如果在y轴方向[0, 2*PI]范围内补全的话,则关于直线y=PI对称,因此有上面当Gx&0时的算法
考虑应用程序的屏幕旋转
前面计算出了Android设备的“物理屏幕”相对于地面的旋转角度,而应用程序的UI又相对于“物理屏幕”存在0、90、180、270度4种可能的旋转角度,要综合考虑进来。也就是说:
UI相对于地面的旋转角度=物理屏幕相对于地面的旋转角度-UI相对于物理屏幕的旋转角度
Android应用获取屏幕旋转角度的方法为:
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degree= 90 *
float rad = (float)Math.PI / 2 *
根据上面的算法,我写了一个“不倒翁”的Demo,当设备旋转时,不倒翁始终是站立的。软件市场上不少“水平尺”一类的应用,其实现原理应该是与此相同的
Activity实现了SensorEventListener,并且注册到SensorManager。同时设置屏幕方向固定为LANDSCAPE:
private GSensitiveView gsV
private SensorM
public void onCreate(Bundle savedInstanceState) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(savedInstanceState);
gsView = new GSensitiveView(this);
setContentView(gsView);
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
protected void onDestroy() {
sm.unregisterListener(this);
super.onDestroy();
当g-sensor数据变化时的回调如下。这里就是根据我们前面推论的算法计算出UI旋转的角度,并且调用GSensitiveView.setRotation()方法通知View更新
public void onSensorChanged(SensorEvent event) {
if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
float[] values = event.
float ax = values[0];
float ay = values[1];
double g = Math.sqrt(ax * ax + ay * ay);
double cos = ay /
if (cos & 1) {
} else if (cos & -1) {
double rad = Math.acos(cos);
if (ax & 0) {
rad = 2 * Math.PI -
int uiRot = getWindowManager().getDefaultDisplay().getRotation();
double uiRad = Math.PI / 2 * uiR
rad -= uiR
gsView.setRotation(rad);
GSensitiveView是扩展ImageView的自定义类,主要是根据旋转角度绘制图片:
private static class GSensitiveView extends ImageView {
private double
public GSensitiveView(Context context) {
super(context);
BitmapDrawable drawble = (BitmapDrawable) context.getResources().getDrawable(R.drawable.budaow);
image = drawble.getBitmap();
paint = new Paint();
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
double w = image.getWidth();
double h = image.getHeight();
Rect rect = new Rect();
getDrawingRect(rect);
int degrees = (int) (180 * rotation / Math.PI);
canvas.rotate(degrees, rect.width() / 2, rect.height() / 2);
canvas.drawBitmap(image, //
(float) ((rect.width() - w) / 2),//
(float) ((rect.height() - h) / 2),//
public void setRotation(double rad) {
rotation =
invalidate();
版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
用云栖社区APP,舒服~
【云栖快讯】红轴机械键盘、无线鼠标等753个大奖,先到先得,云栖社区首届博主招募大赛9月21日-11月20日限时开启,为你再添一个高端技术交流场所&&
阿里云专门为物联网领域的开发人员推出的,其目的是帮助开发者搭建安全性能强大的数据通道,方便终端(如传感器、执行器...
阿里云针对移动应用推出的无线加速产品,旨在依托阿里云遍布全网的加速节点,海量带宽网络等优越的基础设施,为开发者提...
一项针对阿里云资源和互联网应用进行监控的服务。云监控服务可用于收集获取阿里云资源的监控指标,探测互联网服务可用性...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
MaxCompute75折抢购
Loading...

我要回帖

更多关于 可穿戴设备发展方向 的文章

 

随机推荐