[英]Moving an image using Accelerometer of android
我已經閱讀了有關訪問手機的加速度計(加速度和方向)值的文章/教程。 我正在嘗試構建一個簡單的應用程序,在其中可以使用這些值移動球圖像。 這是我的代碼:
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class Accelerometer extends Activity implements SensorEventListener {
/** Called when the activity is first created. */
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
int x ;
int y ;
private SensorManager sensorManager = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
// setContentView(R.layout.main);
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent) {
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
int someNumber = 100;
float xChange = someNumber * sensorEvent.values[1];
//values[2] can be -90 to 90
float yChange = someNumber * 2 * sensorEvent.values[2];
x = x + (int)xChange;
y = y + (int)yChange;
}
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
protected void onResume() {
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onStop() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View {
public CustomDrawableView(Context context) {
super(context);
int width = 50;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
invalidate();
}
}
}
我在屏幕上顯示的是橢圓形,但此后沒有任何反應。
謝謝
使用此代碼。 初始化該類后,再也無需設置可繪制對象的位置。 您必須進行一些計算才能正確設置球的位置。 您這樣做的方式是獲得超過10000的值,這使橢圓形脫離了屏幕。
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
public class Accelerometer extends Activity implements SensorEventListener
{
/** Called when the activity is first created. */
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
private SensorManager sensorManager = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
// setContentView(R.layout.main);
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent)
{
{
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// the values you were calculating originally here were over 10000!
x = (int) Math.pow(sensorEvent.values[1], 2);
y = (int) Math.pow(sensorEvent.values[2], 2);
}
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
}
}
// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1)
{
// TODO Auto-generated method stub
}
@Override
protected void onResume()
{
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onStop()
{
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
public class CustomDrawableView extends View
{
static final int width = 50;
static final int height = 50;
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas)
{
RectF oval = new RectF(Accelerometer.x, Accelerometer.y, Accelerometer.x + width, Accelerometer.y
+ height); // set bounds of rectangle
Paint p = new Paint(); // set some paint options
p.setColor(Color.BLUE);
canvas.drawOval(oval, p);
invalidate();
}
}
}
這是我對這個問題的實現。 Dymmeh的解決方案不斷給我帶來麻煩,因此我對其進行了重構,直到它起作用為止。
package edu.ian495.accelerometertest;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lastUpdate = System.currentTimeMillis();
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= (int) event.values[0];
y += (int) event.values[1];
}
}
public class AnimatedView extends ImageView {
static final int width = 50;
static final int height = 50;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
@Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
我在onSensorChange代碼中做了一些更改,以將球移到屏幕上。 以我的情況為例,球無法正確移動,因此我進行了更改。 這個例子對我來說很好。
public void onSensorChanged(SensorEvent sensorEvent)
{
//Try synchronize the events
synchronized(this){
//For each sensor
switch (sensorEvent.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD: //Magnetic sensor to know when the screen is landscape or portrait
//Save values to calculate the orientation
mMagneticValues = sensorEvent.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER://Accelerometer to move the ball
if (bOrientacion==true){//Landscape
//Positive values to move on x
if (sensorEvent.values[1]>0){
//In margenMax I save the margin of the screen this value depends of the screen where we run the application. With this the ball not disapears of the screen
if (x<=margenMaxX){
//We plus in x to move the ball
x = x + (int) Math.pow(sensorEvent.values[1], 2);
}
}
else{
//Move the ball to the other side
if (x>=margenMinX){
x = x - (int) Math.pow(sensorEvent.values[1], 2);
}
}
//Same in y
if (sensorEvent.values[0]>0){
if (y<=margenMaxY){
y = y + (int) Math.pow(sensorEvent.values[0], 2);
}
}
else{
if (y>=margenMinY){
y = y - (int) Math.pow(sensorEvent.values[0], 2);
}
}
}
else{//Portrait
//Eje X
if (sensorEvent.values[0]<0){
if (x<=margenMaxX){
x = x + (int) Math.pow(sensorEvent.values[0], 2);
}
}
else{
if (x>=margenMinX){
x = x - (int) Math.pow(sensorEvent.values[0], 2);
}
}
//Eje Y
if (sensorEvent.values[1]>0){
if (y<=margenMaxY){
y = y + (int) Math.pow(sensorEvent.values[1], 2);
}
}
else{
if (y>=margenMinY){
y = y - (int) Math.pow(sensorEvent.values[1], 2);
}
}
}
//Save the values to calculate the orientation
mAccelerometerValues = sensorEvent.values.clone();
break;
case Sensor.TYPE_ROTATION_VECTOR: //Rotation sensor
//With this value I do the ball bigger or smaller
if (sensorEvent.values[1]>0){
z=z+ (int) Math.pow(sensorEvent.values[1]+1, 2);
}
else{
z=z- (int) Math.pow(sensorEvent.values[1]+1, 2);
}
default:
break;
}
//Screen Orientation
if (mMagneticValues != null && mAccelerometerValues != null) {
float[] R = new float[16];
SensorManager.getRotationMatrix(R, null, mAccelerometerValues, mMagneticValues);
float[] orientation = new float[3];
SensorManager.getOrientation(R, orientation);
//if x have positives values the screen orientation is landscape in other case is portrait
if (orientation[0]>0){//LandScape
//Here I change the margins of the screen for the ball not disapear
bOrientacion=true;
margenMaxX=1200;
margenMinX=0;
margenMaxY=500;
margenMinY=0;
}
else{//Portrait
bOrientacion=false;
margenMaxX=600;
margenMinX=0;
margenMaxY=1000;
margenMinY=0;
}
}
}
}
我畫球的風景課
public class CustomDrawableView extends View
{
static final int width = 50;
static final int height = 50;
//Constructor de la figura
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
//Dibujamos la figura
protected void onDraw(Canvas canvas)
{
//Actividad_Principal x,y,z are variables from the main activity where I have the onSensorChange
RectF oval = new RectF(Actividad_Principal.x+Actividad_Principal.z, Actividad_Principal.y+Actividad_Principal.z, Actividad_Principal.x + width, Actividad_Principal.y + height);
Paint p = new Paint();
p.setColor(Color.BLUE);
canvas.drawOval(oval, p);
invalidate();
}
}
}
僅此而已,希望對我們有所幫助。
使用以下庫代替滾動動作
在頂部XML視圖中添加此行
xmlns:parallax="http://schemas.android.com/apk/res-auto"
用於布局
<com.nvanbenschoten.motion.ParallaxImageView
android:id="@+id/parallex"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image_hd"
parallax:motionTiltSensitivity="2.5" />
用於onCreate()方法中的代碼
ParallaxImageView mBackground = (ParallaxImageView) findViewById(R.id.parallex);
在您的onResume()方法中
if(mBackground!=null)
mBackground.registerSensorManager();
在您的onDestroy()方法中
// Unregister SensorManager when exiting
mBackground.unregisterSensorManager();
嘗試使用sensorEvent.values[0]
為您xChange
和sensorEvents.values[1]
為您yChange
如果你想使用加速度傳感器,如果沒有使用相同的值,並將其移動到( sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION
)if語句,這將為您提供聽筒的傾斜度,而不是聽筒沿軸的移動速度。
您還需要調用invalidate();
設置或更改傳感器時,在視圖上顯示。
Sensor.TYPE_ACCELEROMETER
返回:
values[0]: Acceleration minus Gx on the x-axis
values[1]: Acceleration minus Gy on the y-axis
values[2]: Acceleration minus Gz on the z-axis
Sensor.TYPE_ORIENTATION
返回:
values[0]
:磁北方向與y軸之間的角度,圍繞z軸(0到359)。 0 =北,90 =東,180 =南,270 =西
values[1]
:螺距,繞x軸旋轉(-180至180),當z軸朝y軸移動時為正值。
values[2]
:繞y軸(-90到90)旋轉,當x軸朝z軸移動時具有正值。
我認為您需要在onSensorChanged()方法或必須實現的特定fps速率下使視圖無效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.