Reputation: 1688
In my app I have a basic compass which is rendered in a "compassView" Class. If I set the contentView in my Display Compass activity like so: compassView = new CompassView(this); setContentView(compassView);
it works fine and points north however if I set the content view to setContentView(activity_display_compass)
it will render the compass and any textviews I may have but the compass is static; ie the needle does not move. I am at loss to what is causing this. Any guidance would be much appreciated?
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"/>
<com.example.gpsfinder.CompassView
android:id="@+id/compassView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Display Compass Activity
public class DisplayCompass extends Activity {
private static SensorManager sensorService;
private CompassView compassView;
private Sensor sensorAccelerometer;
private Sensor sensorMagnetometer;
private float [] lastAccelerometer = new float[3];
private float [] lastMagnetometer = new float[3];
private boolean lastAccelerometerSet = false;
private boolean lastMagnetometerSet = false;
private float[] rotation = new float[9];
private float[] orientation = new float[3];
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
compassView = new CompassView(this);
setContentView(compassView);
sensorService = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensorAccelerometer = sensorService.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagnetometer = sensorService.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//sensor = sensorService.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (sensorAccelerometer != null && sensorMagnetometer != null) {
sensorService.registerListener(mySensorEventListener, sensorAccelerometer,
SensorManager.SENSOR_DELAY_UI);
sensorService.registerListener(mySensorEventListener, sensorMagnetometer,
SensorManager.SENSOR_DELAY_UI);
Log.i("Compass MainActivity", "Registerered for ORIENTATION Sensor");
} else {
Log.e("Compass MainActivity", "Registerered for ORIENTATION Sensor");
Toast.makeText(this, "ORIENTATION Sensor not found",
Toast.LENGTH_LONG).show();
finish();
}
}
private SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if(event.sensor == sensorAccelerometer){
System.arraycopy(event.values,0,lastAccelerometer, 0,event.values.length);
lastAccelerometerSet= true;
}
else if (event.sensor == sensorMagnetometer){
System.arraycopy(event.values,0,lastMagnetometer, 0,event.values.length);
lastMagnetometerSet = true;
}
if(lastAccelerometerSet && lastMagnetometerSet)
SensorManager.getRotationMatrix(rotation,null,lastAccelerometer ,lastMagnetometer );
SensorManager.getOrientation(rotation,orientation);
// angle between the magnetic north direction
// 0=North, 90=East, 180=South, 270=West
double azimuth = Math.toDegrees(orientation[0]);
compassView.updateDirection(azimuth);
}
};
@Override
protected void onDestroy() {
super.onDestroy();
sensorService.unregisterListener(mySensorEventListener);
}
}
Compass View
public class CompassView extends View{
private Paint paint;
private double position = 0;
public CompassView(Context context) {
super(context, null);
init();
}
public CompassView(Context context, AttributeSet attrs) {
super(context,attrs, 0);
init();
}
public CompassView(Context context, AttributeSet attrs,int defStyle) {
super(context,attrs, defStyle);
init();
}
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
paint.setTextSize(25);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
int xPoint = getMeasuredWidth() / 2;
int yPoint = getMeasuredHeight() / 2;
float radius = (float) (Math.max(xPoint, yPoint) * 0.6);
canvas.drawCircle(xPoint, yPoint, radius, paint);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);
// 3.143 is a good approximation for the circle
canvas.drawLine(xPoint,
yPoint,
(float) (xPoint + radius
* Math.sin((double) (-position) / 180 * 3.143)),
(float) (yPoint - radius
* Math.cos((double) (-position) / 180 * 3.143)), paint);
canvas.drawText(String.valueOf(position), xPoint, yPoint, paint);
}
public void updateDirection(double azimuth) {
this.position = azimuth;
invalidate();
}
}
Upvotes: 1
Views: 231
Reputation: 31045
Your problem was simply that when you first coded the app, you were programmatically creating your CompassView
with this:
compassView = new CompassView(this);
setContentView(compassView);
When you changed to use XML layouts, that first line was presumably removed. But, you still need to assign your compassView
member variable, because you use it in your SensorEventListener
's onSensorChanged()
method. You were getting a NullPointerException
(which you can see by looking at LogCat).
So, in your onCreate()
method, after setting the content view, remember to do this:
setContentView(R.layout.activity_display_compass);
compassView = (CompassView)findViewById(R.id.compassView); // <- missing?!
Upvotes: 2