The level here refers to a more traditional bubble level, filled with liquid in a transparent disc, with a bubble in the liquid. When one end is tilted, this bubble will float at one end. In the preceding section, a small compass application is implemented using the first parameter returned by the Direction sensor. Next, we use the second and third parameters returned to implement the level. Because the second parameter indicates the angle at the bottom (or top), the third parameter indicates the angle at the right (or left. Based on these two perspectives, you can develop a level meter. This is also the realization idea of the level meter. The Code is as follows: Activity:
Package com. home. activity; import android. app. activity; import android. hardware. sensor; import android. hardware. sensorEvent; import android. hardware. sensorEventListener; import android. hardware. sensorManager; import android. OS. bundle; import com. home. r; import com. home. view. myView; public class MainActivity extends Activity implements SensorEventListener {// defines the private MyView view of the dashboard of the level. // defines the maximum tilt angle that the level can handle, beyond this angle, the bubble is directly located at the boundary private final int MAX_ANGLE = 30; // defines the Sensor manager private SensorManager mSensorManager; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); // obtain the widget view = (MyView) findViewById (R. id. main_myview); // get the Sensor Management Service mSensorManager = (SensorManager) getSystemService (SENSOR_SERVICE) ;}@ Override protected void onResume () {super. onResume (); // registers the listener mSensorManager for the system's sensor. registerListener (this, mSensorManager. getdefasensensor (Sensor. TYPE_ORIENTATION), SensorManager. SENSOR_DELAY_GAME) ;}@ Override protected void onPause () {// cancel mSensorManager registration. unregisterListener (this); super. onPause () ;}@ Override public void onAccuracyChanged (Sensor sensor, int accuracy) {}@ Override public void onSensorChanged (SensorEvent event) {float [] values = event. values; // The sensor type int sensorType = event. sensor. getType (); switch (sensorType) {case Sensor. TYPE_ORIENTATION: // obtain the float yAngle = values [1] From the Y axis; // obtain the float zAngle = values [2] From the Z axis. // when the bubble is in the middle (the level is completely horizontal), the X and Y coordinates of the bubble int x = (view. back. getWidth ()-view. bubble. getWidth ()/2; int y = (view. back. getHeight ()-view. bubble. getHeight ()/2; // if the tilt angle with the Z axis is still within the maximum angle if (Math. abs (zAngle) <= MAX_ANGLE) {// calculate the change value of x coordinate based on the tilt angle with the Z axis (the larger the angle, the larger the x coordinate change) int deltaX = (int) (view. back. getWidth ()-view. bubble. getWidth ()/2 * zAngle/MAX_ANGLE); x + = deltaX;} // If the tilt angle with the Z axis is greater than MAX_ANGLE, bubble should be to the leftmost else if (zAngle> MAX_ANGLE) {x = 0 ;}// if the tilt angle with the Z axis is already less than negative MAX_ANGLE, bubble should go to the rightmost else {x = view. back. getWidth ()-view. bubble. getWidth ();} // if the tilt angle with the Y axis is still within the maximum angle if (Math. abs (yAngle) <= MAX_ANGLE) {// calculate the variation value of Y coordinate based on the tilt angle of Y axis (the larger the angle, the larger the Y coordinate variation) int deltaY = (int) (view. back. getHeight ()-view. bubble. getHeight ()/2 * zAngle/MAX_ANGLE); y + = deltaY;} // If the tilt angle with the y axis is greater than MAX_ANGLE, bubble should be at the bottom of else if (yAngle> MAX_ANGLE) {y = view. back. getHeight ()-view. bubble. getHeight () ;}// if the tilt angle with the y axis is already less than the negative MAX_ANGLE, the bubble should reach the rightmost else {y = 0 ;} // if the calculated X and Y coordinates are still in the gauge, update the if (isContain (x, y) {view. bubbleX = x; view. bubbleY = y;} // notify the system to re-paint the MyView component view. postInvalidate (); break ;}// calculates whether the bubbles at the X and Y points are in the gauge private boolean isContain (int x, int y) {// calculates the coordinates of the bubble center X and Y int bubbleCx = x + view. bubble. getWidth ()/2; int bubbleCy = y + view. bubble. getHeight ()/2; // calculates the coordinates of the center of the horizontal dashboard X and Y int backCx = view. back. getWidth ()/2; int backCy = view. back. getHeight ()/2; // calculate the distance between the center of the bubble and the center of the horizontal dashboard. double distance = Math. sqrt (bubbleCx-backCx) * (bubbleCx-backCx) + (bubbleCy-backCy) * (bubbleCy-backCy); // if the distance between the two centers is smaller than their radius, you can think that the bubble in the store is still in the dashboard if (distance <(view. back. getWidth ()-view. bubble. getWidth ()/2) {return true;} else {return false ;}} package com. home. activity; import android. app. activity; import android. hardware. sensor; import android. hardware. sensorEvent; import android. hardware. sensorEventListener; import android. hardware. sensorManager; import android. OS. bundle; import com. home. r; import com. home. view. myView; public class MainActivity extends Activity implements SensorEventListener {// defines the private MyView view of the dashboard of the level. // defines the maximum tilt angle that the level can handle, beyond this angle, the bubble is directly located at the boundary private final int MAX_ANGLE = 30; // defines the Sensor manager private SensorManager mSensorManager; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); // obtain the widget view = (MyView) findViewById (R. id. main_myview); // get the Sensor Management Service mSensorManager = (SensorManager) getSystemService (SENSOR_SERVICE) ;}@ Overrideprotected void onResume () {super. onResume (); // registers the listener mSensorManager for the system's sensor. registerListener (this, mSensorManager. getdefasensensor (Sensor. TYPE_ORIENTATION), SensorManager. SENSOR_DELAY_GAME) ;}@ Overrideprotected void onPause () {// cancel mSensorManager registration. unregisterListener (this); super. onPause () ;}@ Overridepublic void onAccuracyChanged (Sensor sensor, int accuracy) {}@ Overridepublic void onSensorChanged (SensorEvent event) {float [] values = event. values; // The sensor type int sensorType = event. sensor. getType (); switch (sensorType) {case Sensor. TYPE_ORIENTATION: // obtain the float yAngle = values [1] From the Y axis; // obtain the float zAngle = values [2] From the Z axis. // when the bubble is in the middle (the level is completely horizontal), the X and Y coordinates of the bubble int x = (view. back. getWidth ()-view. bubble. getWidth ()/2; int y = (view. back. getHeight ()-view. bubble. getHeight ()/2; // if the tilt angle with the Z axis is still within the maximum angle if (Math. abs (zAngle) <= MAX_ANGLE) {// calculate the change value of x coordinate based on the tilt angle with the Z axis (the larger the angle, the larger the x coordinate change) int deltaX = (int) (view. back. getWidth ()-view. bubble. getWidth ()/2 * zAngle/MAX_ANGLE); x + = deltaX;} // If the tilt angle with the Z axis is greater than MAX_ANGLE, bubble should be to the leftmost else if (zAngle> MAX_ANGLE) {x = 0 ;}// if the tilt angle with the Z axis is already less than negative MAX_ANGLE, bubble should go to the rightmost else {x = view. back. getWidth ()-view. bubble. getWidth ();} // if the tilt angle with the Y axis is still within the maximum angle if (Math. abs (yAngle) <= MAX_ANGLE) {// calculate the variation value of Y coordinate based on the tilt angle of Y axis (the larger the angle, the larger the Y coordinate variation) int deltaY = (int) (view. back. getHeight ()-view. bubble. getHeight ()/2 * zAngle/MAX_ANGLE); y + = deltaY;} // If the tilt angle with the y axis is greater than MAX_ANGLE, bubble should be at the bottom of else if (yAngle> MAX_ANGLE) {y = view. back. getHeight ()-view. bubble. getHeight () ;}// if the tilt angle with the y axis is already less than the negative MAX_ANGLE, the bubble should reach the rightmost else {y = 0 ;} // if the calculated X and Y coordinates are still in the gauge, update the if (isContain (x, y) {view. bubbleX = x; view. bubbleY = y;} // notify the system to re-paint the MyView component view. postInvalidate (); break ;}// calculates whether the bubbles at the X and Y points are in the gauge private boolean isContain (int x, int y) {// calculates the coordinates of the bubble center X and Yint bubbleCx = x + view. bubble. getWidth ()/2; int bubbleCy = y + view. bubble. getHeight ()/2; // calculates the coordinates of the center of the horizontal dashboard X and Yint backCx = view. back. getWidth ()/2; int backCy = view. back. getHeight ()/2; // calculate the distance between the center of the bubble and the center of the horizontal dashboard. double distance = Math. sqrt (bubbleCx-backCx) * (bubbleCx-backCx) + (bubbleCy-backCy) * (bubbleCy-backCy); // if the distance between the two centers is smaller than their radius, you can think that the bubble in the store is still in the dashboard if (distance <(view. back. getWidth ()-view. bubble. getWidth ()/2) {return true;} else {return false ;}}}
Custom component class (MyView ):
Package com. home. view; import com. home. r; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. util. attributeSet; import android. view. view; public class MyView extends View {// defines the level disk image public Bitmap back; // defines the bubble icon public Bitmap bubble in the level; // define the X and Y coordinates of bubbles in the level public int bubbleX, bubbleY; public MyView (Context context, AttributeSet attrs) {super (context, attrs ); // load the level image and bubble image back = BitmapFactory. decodeResource (getResources (), R. drawable. back); bubble = BitmapFactory. decodeResource (getResources (), R. drawable. bubble) ;}@ Override protected void onDraw (Canvas canvas) {super. onDraw (canvas); // draw the canvas of the level picture. drawBitmap (back, 0, 0, null); // draw a bubble canvas Based on the bubble coordinates. drawBitmap (bubble, bubbleX, bubbleY, null) ;}} package com. home. view; import com. home. r; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. util. attributeSet; import android. view. view; public class MyView extends View {// defines the level disk image public Bitmap back; // defines the bubble icon public Bitmap bubble in the level; // define the X and Y coordinates of bubbles in the level public int bubbleX, bubbleY; public MyView (Context context, AttributeSet attrs) {super (context, attrs ); // load the level image and bubble image back = BitmapFactory. decodeResource (getResources (), R. drawable. back); bubble = BitmapFactory. decodeResource (getResources (), R. drawable. bubble) ;}@ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); // draw the canvas of the level picture. drawBitmap (back, 0, 0, null); // draw a bubble canvas Based on the bubble coordinates. drawBitmap (bubble, bubbleX, bubbleY, null );}}
Layout XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.home.view.MyView android:id="@+id/main_myview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.home.view.MyView android:id="@+id/main_myview" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>