Calgar99
Calgar99

Reputation: 1688

Android: CustomView is static when it is supposed to react to orientation

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

Answers (1)

Nate
Nate

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

Related Questions