Custom views are a very important skill when developing Android applications. This article will explain how to create a custom CompassView that displays the orientation of the device. We will get the orientation data by using SensorManager and use a custom drawing method to draw the compass.
1. Create a project
First, create a new project in Android Studio, select the "Empty Activity" template, named CustomCompass.
2. Add permissions
In order to be able to access sensor data, you need to add the corresponding permissions to the file:
<uses-permission android:name=".ACCESS_FINE_LOCATION"/>
3. Create a custom view
3.1 Create a CompassView class
Create a new Java class in the app/src/main/java/com/example/customcompass/ directory:
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; public class CompassView extends View implements SensorEventListener { private Paint paint; private float direction = 0f; private SensorManager sensorManager; private Sensor accelerometer; private Sensor magnetometer; public CompassView(Context context) { super(context); init(context); } public CompassView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { paint = new Paint(); (); (50); (true); sensorManager = (SensorManager) (Context.SENSOR_SERVICE); accelerometer = (Sensor.TYPE_ACCELEROMETER); magnetometer = (Sensor.TYPE_MAGNETIC_FIELD); } @Override protected void onDraw(Canvas canvas) { (canvas); int width = getWidth(); int height = getHeight(); int centerX = width / 2; int centerY = height / 2; // Draw a circular background (); (centerX, centerY, (width, height) / 2, paint); // Draw pointer (); (centerX, centerY, (float) (centerX + ((direction)) * 150), (float) (centerY - ((direction)) * 150), paint); // Draw directional text (); ("N", centerX, centerY - 100, paint); ("S", centerX, centerY + 100, paint); ("E", centerX + 100, centerY, paint); ("W", centerX - 100, centerY, paint); } @Override public void onSensorChanged(SensorEvent event) { if (() == Sensor.TYPE_ACCELEROMETER) { (, 0, mGravity, 0, 3); } else if (() == Sensor.TYPE_MAGNETIC_FIELD) { (, 0, mGeomagnetic, 0, 3); } boolean success = (mRotationMatrix, null, mGravity, mGeomagnetic); if (success) { (mRotationMatrix, mOrientationAngles); direction = (float) (mOrientationAngles[0]); invalidate(); //Repaint the view } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {} private float[] mGravity = new float[3]; private float[] mGeomagnetic = new float[3]; private float[] mRotationMatrix = new float[9]; private float[] mOrientationAngles = new float[3]; public void registerSensor() { (this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); (this, magnetometer, SensorManager.SENSOR_DELAY_NORMAL); } public void unregisterSensor() { (this); } }
3.2 Using CompassView in Layout Files
Add CompassView in activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> < android: android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" /> </RelativeLayout>
4. Register and log out of sensors in MainActivity
Register and log out of sensors in :
package ; import ; import ; public class MainActivity extends AppCompatActivity { private CompassView compassView; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_main); compassView = findViewById(); (); } @Override protected void onDestroy() { (); (); } }
5. Run the application
Now you can run your app. You should see a compass view that updates as the device changes direction.
Through the above steps, we successfully created a custom compass view. This view utilizes Android's sensor manager to get direction data and uses a custom drawing method to display the compass.
6. Method supplement
In Android application development, custom compass view is a common requirement, especially in applications such as navigation and outdoor activities. Below I will provide a simple example showing how to create a custom compass view. This example will include basic layout files, custom view classes, and using sensor data to update compass orientation.
Method 1
Add permissions
First, add the necessary permissions to the file to allow the application to access the device's orientation sensor:
<uses-permission android:name=".ACCESS_FINE_LOCATION"/> <uses-feature android:name="" />
Create a layout file
Create a new layout file activity_main.xml to display the compass view:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> < android: android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" /> </RelativeLayout>
Create a custom compass view
Next, create a custom compass view. This view will draw a circular compass and rotate the pointer according to the angle passed in:
package ; import ; import ; import ; import ; import ; import ; public class CompassView extends View { private Paint paint; private float direction = 0f; // Direction angle public CompassView(Context context) { super(context); init(); } public CompassView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { paint = new Paint(); (); (5f); (true); } @Override protected void onDraw(Canvas canvas) { (canvas); int width = getWidth(); int height = getHeight(); int radius = (width, height) / 2 - 10; // Draw circles (width / 2, height / 2, radius, paint); // Draw pointer (); (); (-direction, width / 2, height / 2); // Rotate counterclockwise (width / 2, height / 2 - radius, width / 2, height / 2 - 50, paint); (); // Draw N, S, E, W (40); (); ("N", width / 2 - 10, height / 2 - radius + 40, paint); ("S", width / 2 - 10, height / 2 + radius - 10, paint); ("E", width / 2 + radius - 40, height / 2 + 10, paint); ("W", width / 2 - radius + 10, height / 2 + 10, paint); } public void setDirection(float direction) { = direction; invalidate(); //Repaint the view } }
Update compass direction using sensor data
In the main activity, register a sensor listener to get the device's orientation change and update the direction of the compass view:
package ; import ; import ; import ; import ; import ; import ; public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private Sensor rotationSensor; private CompassView compassView; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_main); compassView = findViewById(); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); rotationSensor = (Sensor.TYPE_ROTATION_VECTOR); } @Override protected void onResume() { (); (this, rotationSensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { (); (this); } @Override public void onSensorChanged(SensorEvent event) { if (() == Sensor.TYPE_ROTATION_VECTOR) { float[] rotationMatrix = new float[9]; (rotationMatrix, ); float[] orientation = new float[3]; (rotationMatrix, orientation); // Convert radians to angles float azimuth = (float) (orientation[0]); (azimuth); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // No processing of accuracy changes } }
Run the application
Now you can run the app, it will display a custom compass view and update the orientation as the device rotates.
Method 2
This example shows how to create a simple custom compass view in Android. You can further expand and beautify this view as needed, such as adding more graphical elements or improving the user interface. Creating a custom compass view in Android involves multiple steps, including defining the view, processing sensor data, drawing compass images, etc. Here is a detailed guide to help you implement a basic custom compass view.
Create a custom view
First, you need to create a custom view class to draw the compass. This class will inherit from the View class and override the onDraw method to draw the compass image.
import ; import ; import ; import ; import ; import ; import ; public class CompassView extends View { private Bitmap compassBitmap; private Matrix matrix; private float currentDegree = 0f; public CompassView(Context context) { super(context); init(); } public CompassView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { compassBitmap = (getResources(), ); matrix = new Matrix(); } @Override protected void onDraw(Canvas canvas) { (canvas); (); (-currentDegree, () / 2, () / 2); (compassBitmap, matrix, null); } public void updateDegree(float degree) { currentDegree = degree; invalidate(); // Re-draw the view } }
Process sensor data
To get the device's orientation data, you need to register a SensorEventListener and listen for the TYPE_ORIENTATION sensor (or the more modern TYPE_ROTATION_VECTOR sensor).
import ; import ; import ; import ; import ; import ; public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private Sensor sensor; private CompassView compassView; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_main); compassView = findViewById(); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); sensor = (Sensor.TYPE_ORIENTATION); } @Override protected void onResume() { (); (this, sensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { (); (this); } @Override public void onSensorChanged(SensorEvent event) { if (() == Sensor.TYPE_ORIENTATION) { float degree = ([0]); (degree); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // No processing required } }
Layout file
Add a custom CompassView in the layout file.
<RelativeLayout xmlns:andro xmlns:tools="/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> < android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
Add resource file
Make sure you have a compass image resource file (for example, res/drawable/) and place it in the project's res/drawable directory.
Permissions
Add the necessary permissions in :
<uses-permission android:name=".ACCESS_FINE_LOCATION" /> <uses-permission android:name=".ACCESS_COARSE_LOCATION" />
Summarize
The above steps show how to create a custom compass view in Android. With custom view classes and sensor event listeners, you can implement a compass that dynamically update directions.
The above is the detailed explanation of the Android custom implementation compass view. For more information about Android custom view, please follow my other related articles!