方向传感器基本是Android手机必备功能,所有这个demo基本都可以使用。
界面一个ImageView(蓝色条) 下面是自己画的圆和线(最开始没去找图,懒)
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv"
android:layout_marginTop="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/sensor"
android:contentDescription="@string/app_name" />
<com.ui.ArrowsView
android:id="@+id/arrows"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.ui.ArrowsView>
</LinearLayout>
自定义的View可以直接替换掉,蓝色条可以自己换其他图片,没有影响,下面贴Activity,无非就是通过系统服务获取传感器控制器SensorManager,注册监听,在监听器里面使用补间动画或者设置旋转setRotation。
需要注意的是使用补间动画旋转 RotateAnimation 时,在0-360 跳转间隔即△>300+时指针会多旋转方向错误,这时需要添加一个判断,当间隔过大,即跳变的时候,把 起始位置/结束位置 -360,即可。
代码如下:
package com.widget;
import com.sernortest.R;
import com.ui.ArrowsView;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
public class ArrowsViewActivity extends Activity {
private ArrowsView arrows;
private ImageView iv;
private Sensor sensor;
private SensorManager manager;
private RotateAnimation rotate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arrows);
arrows = (ArrowsView) findViewById(R.id.arrows);
iv = (ImageView) findViewById(R.id.iv);
manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
@Override
protected void onResume() {
sensor = manager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
super.onResume();
}
@Override
protected void onPause() {
manager.unregisterListener(listener);
super.onPause();
}
float predegree = -100;//起始角度
float degree;//结束角度
float mdg = 180;//设置旋转间隔 数值可以自行调整
/**
*
*由于我使用一个自定义view,而系统的刷新频率太快,
*所以加了判断降低刷新频率,现在是0.5s刷新
*单个ImageView的话不建议降低刷新频率,会显得卡顿,保持默认刷新即可
*/
float dt=500;//刷新频率0.5s
long nowT;
long lastT = -1;
private SensorEventListener listener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
try {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
degree = event.values[0];
arrows.setRotate(degree);
if (predegree == -100) {
predegree = degree;
return;
}
nowT = System.currentTimeMillis();
if (lastT == -1) {
lastT = nowT;
return;
}
if (dt < (nowT - lastT)) {
if((degree-predegree)>mdg){
degree = degree-360;
}else if((degree-predegree)<-mdg){
predegree = predegree-360;
}
rotate = new RotateAnimation(predegree, degree, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1f);
rotate.setDuration(300);
rotate.setFillAfter(true);
iv.startAnimation(rotate);
predegree = degree;
lastT = 0;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
}
自定义ArrowsView仅供参考
package com.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
public class ArrowsView extends View {
private float mWidth = 700;
private float mHeight = 700;
private float degree = 0;
Paint mPaint , paint;
public ArrowsView(Context context) {
this(context, null);
}
public ArrowsView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
paint = new Paint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
setMeasuredDimension((int) mWidth, (int) mHeight);
} else if (widthMode == MeasureSpec.AT_MOST) {
setMeasuredDimension((int) mWidth, heightSize);
} else if (heightMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSize, (int) mHeight);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.mWidth = Math.min(getWidth(), getHeight());
this.mHeight = Math.max(getWidth(), getHeight());
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(6);
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - 100, mPaint);
mPaint.setStyle(Style.FILL);
canvas.drawCircle(mWidth / 2, mHeight / 2, 15, mPaint);
paint.setAntiAlias(true);
paint.setStrokeWidth(10);
canvas.rotate(degree, mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, mHeight / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 110, paint);
canvas.rotate(-degree, mWidth / 2, mHeight / 2);
}
public void setRotate(float degree) {
this.degree = degree;
postInvalidate();
}
}