Android系统示例分析之AccelerometerPlay
程序界面:

创建 SimulationView , 实现接口 SensorEventListener , 实现接口中两个抽象方法
public void onSensorChanged(SensorEvent event);
public void onAccuracyChanged(Sensor sensor, int accuracy);
SimulationView 扩展了 View ,至少需要一个构造方法,例如
public SimulationView(Context context) {
super(context);
}
在 SimulationView 构造方法中:
// 得到加速传感器
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
得到屏幕上X/Y方向上每英寸有多少个物理像素
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mXDpi = metrics.xdpi;
mYDpi = metrics.ydpi;
注:float android.util.DisplayMetrics.xdpi
The exact physical pixels per inch of the screen in the X dimension.
译:在屏幕的X方向,每英寸有多少个物理像素。
将“每英寸有多少个物理像素”换算成“每米有多少个物理像素”,其中1.0英寸等于0.0254米。
mMetersToPixelsX = mXDpi / 0.0254f;
mMetersToPixelsY = mYDpi / 0.0254f;
将小球位图进行缩放处理,宽度 = 小球直径 X (每米有多少个像素),高度计算方法类似
Bitmap ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
final int dstWidth = (int) (sBallDiameter * mMetersToPixelsX + 0.5f);
final int dstHeight = (int) (sBallDiameter * mMetersToPixelsY + 0.5f);
mBitmap = Bitmap.createScaledBitmap(ball, dstWidth, dstHeight, true);
得到 wood 位图
Options opts = new Options();
opts.inDither = true;
opts.preferredConfig = Bitmap.Config.RGB_656;
mWood = BitmapFactory.decodeResource(getResources(), R.drawable.wood, opts);
注:boolean android.graphics.BitmapFactory.Options.inDither
If dither is true, the decoder will attempt to dither the decoded image.
生词:
dither 抖,发抖,兴奋,犹豫不决;
在 SimulationView 类中,除构造方法SimulationView,onSensorChanged, onAccuracyChanged,还有
public void onSizeChanged(int w, int h, int oldW, int oldH);
public void onDraw(Canvas canvas);
在 SimulationView 类中,定义了子类 Particle。
在 Particle 构造方法中,
final float r = ((float) Math.random() – 0.5f) * 0.2f;
mOneMinusFriction = 1.0f – sFriction + r;
在AccelerometerPlayActivity.onCreate()方法中
// 得到 SensorManager 对象
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// 得到 PowerManager 对象
mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
// 得到 WindowManager 对象
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// 得到 Display 对象
mDisplay = mWindowManager.getDefaultDisplay();
// 得到 WakeLock 对象
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName());
// 创建 SimulationView 对象
mSimulationView = new SimulationView(this);
// 设置 ContentView
setContentView(mSimulationView);
在AccelerometerPlayActivity类中,除了onCreate方法,还有onResume和onPause方法
在AccelerometerPlayActivity.onResume方法中
mWakeLock.acquire();
mSimulationView.startSimulation();
在SimulationView.startSimulation()方法中注册加速器传感器。
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
注:int android.hardware.SensorManager.SENSOR_DELAY_UI = 2 [0x2]
rate suitable for the user interface
生词:
rate 比率,速度,价格,费用,等级;
在AccelerometerPlayActivity.onPause方法中
mSimulationView.stopSimulation();
mWakeLock.release();
在SimulationView.stopSimulation()方法中注销加速器传感器。
mSensorManager.unregisterListener(this);
在SimulationView中,定义ParticleSystem变量
private final ParticleSystem mParticleSystem = new ParticleSystem();
在SimulationView.onSensorChanged方法中
注:SensorEventListener.onSensorChanged: Called when sensor values have changed.
// 判断是加速计传感器数据发生了变化
if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
// 当SensorValue发生变化时,重新计算mSensorX和mSensorY两个数值
switch (mDisplay.getRotation()) {
case Surface.ROTATION_0:
mSensorX = event.values[0];
mSensorY = event.values[1];
break;
case Surface.ROTATION_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;
}
得到事件发生的时间
mSensorTimeStamp = event.timestamp;
mCpuTimeStamp = System.nanoTime();
注:long java.lang.System.nanoTime()
the current timestamp in nanoseconds.
生词:nanoseconds 纳秒
注:long android.hardware.SensorEvent.timestamp
The time in nanosecond at which the event happened
在 SimulationView.onDraw(Canvas) 方法中
// 绘出背景图片(木板)
canvas.draw(mWood, 0, 0, null);
方法解析:
public void SimulationView.ParticleSystem.update(float sx, float sy, long now)
Performs one iteration of the simulation. First updating the position of all the particles and resolving the constraints and collisions.
生词:
perform 执行,履行,表演,运转,举行;
iteration 迭代,循环,重复;
resolve 分解,溶解,解析;
constraints 强制,约束,被约束;
collisions 碰撞
方法解析
private void SimulationView.ParticleSystem.updatePositions(float sx, float sy, long timestamp)
Update the position of each particle in the system using the Verlet integrator.
译:更新每个粒子的位置。
方法解析
public void SimulationView.Particle.computePhysics(float sx, float sy, float dT, float dTC)
计算小球的坐标,在画布上绘出小球
final float x = xc + particleSystem.getPosX(i) * xs;
final float y = yc - particleSystem.getPosY(i) * ys;
canvas.drawBitmap(bitmap, x, y, null);
xc和yc都在onSizeChanged方法中计算。
mXOrigin = (w - mBitmap.getWidth()) * 0.5f;
mYOrigin = (h - mBitmap.getHeight()) * 0.5f;
xc和yc在使用时都被赋值mXOrigin和mYOrigin。
两条语句表现出,小球的起始位置在屏幕的中间。
xc, yc, xs, ys, bitmap直接被赋值,很容易理解
final float xc = mXOrigin;
final float yc = mYOrigin;
final float xs = mMetersToPixelsX;
final float ys = mMetersToPixelsY;
final Bitmap bitmap = mBitmap;
其中mXOrigin, mYOrigin在onSizeChanged计算。
mMetersToPixelsX, mMetersToPixelsY在onCreate中计算。
mBitmap在onCreate中赋值。
注:void SimulationView.onSizeChanged(int w, int h, int oldw, int oldh)
This is called during layout when the size of this view has changed. If you were just added to the view hierarchy, you're called with the old values of 0.
译:当view的大小发生变化时调用。如果是加入到view hierarchy中,oldw和oldh的数值都为0。
在onDraw(Canvas)方法最后调用invalidate方法。
注:void android.view.View.invalidate()
Invalidate the whole view. If the view is visible, onDraw will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().
生词:
invalidate 使作废,使无效;
注:void SimulationView.Particle.resolveCollisionWithBounds()
Resolving constraints and collisions with the Verlet integrator can be very simple, we simply need to move a colliding or constrained particle in such way that the constraint is satisfied.
生词:
collide 碰撞
相关:Source/HelixToolkit.Wpf/Physics/VerletIntegrator.cs
在onSizeChanged方法中计算HorizontalBound和mVerticalBound
mHorizontalBound = ((w / mMetersToPixelsX - sBallDiameter) * 0.5f);
mVerticalBound = ((h / mMetersToPixelsY - sBallDiameter) * 0.5f);
跟踪记录:
mHorizontalBound = (0.076 – 0.004) * 0.5f = 0.036;
mVerticalBound = (0.127 – 0.004) * 0.5f = 0.0615;
到目前为止,小球的位置如何计算,就不是很清楚了。
其实这个示例蛮简单的,只是让小球以某个规律/算法移动位置,每移动一次就重绘一次。
Android系统示例分析之AccelerometerPlay的更多相关文章
- Android系统示例分析之AndroidBeamDemo
在这个示例工程中,只有一个Activity: public class Beam extends Activity implements CreateNdefMessageCallback, ...
- Android系统Gps分析(一)【转】
本文转载自:http://blog.csdn.net/xnwyd/article/details/7198728 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 1 G ...
- Android系统示例之ActionBarCompat
导入工程ActionBarCompat时,出现错误.从其他工程下拷贝project.propertiest文件过来,问题仍在.拷贝后需要重启Eclipse才解决.问题如下: [2013-07-03 1 ...
- Android菜鸟的成长笔记(5)——Android系统源代码你下载了吗?
原文:Android菜鸟的成长笔记(5)--Android系统源代码你下载了吗? 在上一篇中我们用Android系统源代码分析了我们前面写的代码,有的朋友可能就会问怎么才能下载到Google官方的源代 ...
- Simpleperf分析之Android系统篇
[译]Simpleperf分析之Android系统篇 译者按: Simpleperf是用于Native的CPU性能分析工具,主要用来分析代码执行耗时.本文是主文档的一部分,系统篇. 原文见aosp仓库 ...
- (转)Android 系统 root 破解原理分析
现在Android系统的root破解基本上成为大家的必备技能!网上也有很多中一键破解的软件,使root破解越来越容易.但是你思考过root破解的 原理吗?root破解的本质是什么呢?难道是利用了Lin ...
- Android系统自带APP分析——短信app
Android操作系统本身就是一个巨大的开源软件仓库,熟悉它既可以了解到Android系统的设计框架,也可以获得高效的应用程序编写方式.本文所分析的源码来自于Google官方的AOSP源码4.0.1_ ...
- 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...
- 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析
作者:唐老师,华清远见嵌入式学院讲师. 通过前两节HAL框架分析和JNI概述,我们对Android提供的Stub HAL有了比较详细的了解了,下面我们来看下led的实例,写驱动点亮led灯,就如同写程 ...
随机推荐
- [转]Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件
Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件. 1.为了防止拖动ListView时,在列表末尾重复数据显示.需要加入 HashMap<In ...
- 国内OCR供应商及其演示链接
最近因为需要收集了一些OCR的供应商,可以做身份证识别,银行卡识别,名片识别等特定场景下的文字识别.在通用场景下的文字识别效果还不是很理想.现在OCR在特定的场景下做得已经很不错了.下面列出下这些厂商 ...
- Android 动画——属性动画Property Animation
Android在3.0之前只提供了两种动画:View Animation .Drawable Animation .也就是我们在<Android 动画——Frame Animation与Twee ...
- CentOS 6.9/7通过yum安装指定版本的Node.js
说明:通过yum好处其实很多,环境变量不用配置,配置文件放在大家都熟悉的地方,通过rpm -ql xxx可以知道全部文件的地方等等. Node.js(8.x) 一.安装和配置 1.安装Node.js ...
- SpringMVC访问静态页面
Spring MVC显示静态页面 在前面搭建spring MVC环境时,我们设置了spring-mvc配置,通过tomcat来访问了index.jsp 页面,但是当我将页面换成.thml的静态面之后就 ...
- Codeforces Round #FF (Div. 1) B. DZY Loves Modification
枚举行取了多少次,如行取了i次,列就取了k-i次,假设行列单独贪心考虑然后相加,那么有i*(k-i)个交点是多出来的:dpr[i]+dpc[k-i]-i*(k-i)*p 枚举i取最大值.... B. ...
- ASP.NET Core 1.0 基础之配置
来源https://docs.asp.net/en/latest/fundamentals/configuration.html ASP.NET Core 1.0支持不同的配置选项.应用配置数据可以是 ...
- SVM初学
一. 一点基础数学知识 如今硕士都快毕业了,反而将自己的很多数学知识忘的几乎相同了.所以.如今决心再捡起来.以补齐自己的数学短板.为以后的研究做好铺垫吧.如今结合自己学习SVM. ...
- iOS:视图切换的第二种方式:UINavigationController导航栏控制器
UINavigationController:一个以栈的形式管理多视图的容器,负责子控制器之间的跳转.由于以栈的方式管理视图,各个视图的切换就是压栈和出栈操作,所以出栈后的视图会立即销毁. 介绍: & ...
- Linux系统getopt使用示例
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h&g ...