Implementation of android level (use of direction sensors)

Source: Internet
Author: User

Implementation of android level (use of direction sensors)

A long time ago, I have studied the Sensor. TYPE_ORIENTATION. According to my own practice, I have rewritten the two online leveling examples, re-encapsulated and used them, and finally used them in projects.

1. Preface

The following is a sensor from the Android sensor.

 

Generally, in the android system, the TYPE_ORIENTATION constant is used in the api to obtain the orientation information of the mobile phone. You can get the direction sensor sm as you get the acceleration sensor. getdefasensensor (Sensor. TYPE_ORIENTATION); however, we will see this sentence in the latest SDK: "TYPE_ORIENTATIONThis constant is deprecated. use SensorManager. getOrientation () instead. "That is, This method also expires and is not recommended! Google recommends that you use SensorManager. getOrientation () in your application to obtain raw data.

 

Public static float [] getOrientation (float [] R, float [] values)

The first parameter is R [], which is a rotating matrix used to store the magnetic field and acceleration data. It can be understood as the input value of this function. It is used to obtain the azimuth value for you.

The second parameter is the output of the function, which is automatically filled by the function. This is what we want.

 

Values [0]: direction angle, but the range of data obtained with (magnetic field + acceleration) is (-180 ~ 180), that is, 0 indicates the north, 90 indicates the east, 180/-180 indicates the south, and-90 indicates the West. The direct direction sensor data range is (0 ~ 359) 360/0 indicates the north, 90 indicates the east, 180 indicates the south, and 270 indicates the West.

Values [1] the tilt angle of the pitch starts from the static state. It is flipped before and after, and is lifted up on the top of the mobile phone (0 ~ -90), the end of the mobile phone is raised up (0 ~ 90)

Values [2] The roll Rotation Angle starts from the static state. The left and right sides are flipped, and the left side of the mobile phone is lifted (0 ~ 90), raised to the right of the mobile phone (0 ~ -90)

2. Sample Code 1

 

Package com. level. level1; import com. level. level1.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 LevelView extends View {// defines the Bitmap compass of the Large Horizontal disc image; // defines the bubble icon Bitmap ball in the level; // defines the X and Y coordinates of the bubble in the Level int ballX and ballY; // defines the X and Y coordinates of the bubble when the bubble is in the middle (the level is completely horizontal), and the X and Y coordinates of the bubble int cx, Cy; // defines the coordinates of the center X and Yint backCx of the Large Horizontal disc; // defines the sensitivity, that is, the maximum angle of inclination that can be processed by the level, beyond this angle, the bubble is directly located at the boundary. Int sensitiview = 30; public LevelView (Context context, AttributeSet attrs) {super (context, attrs); // load the Large Horizontal disc image and Bubble Image compass = BitmapFactory. decodeResource (getResources (), R. drawable. back); ball = BitmapFactory. decodeResource (getResources (), R. drawable. small); // calculates that the origin cx = (compass. getWidth ()-ball. getWidth ()/2; cy = (compass. getHeight ()-ball. getHeight ()/2; // calculates the coordinates of the center X and Y of the Large Horizontal disc. BackCx = compass. getWidth ()/2; backCy = compass. getWidth ()/2;} @ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); // draw the canvas of the Large Horizontal disc. drawBitmap (compass, 0, 0, null); // draw a bubble canvas Based on the bubble coordinates. drawBitmap (ball, ballX, ballY, null);} public void onChangeXY (int zAngle, int yAngle, int xAngle) {// defines the current position of the bubble x y coordinate value int x, y; x = cx; y = cy; // if the tilt angle along the x axis is within the maximum angle, the corresponding coordinate value if (Math. abs (xAngle) <= SENSITIVITY) {// calculate the variation value of the X coordinate based on the skew angle of the X axis (the larger the skew angle, the greater the X coordinate variation) int deltaX = (int) (cx * xAngle/sensiti.pdf); x + = deltaX;} // if the tilt angle along the x axis is greater than MAX_ANGLE, the bubble should be to the leftmost else if (xAngle> sensiti.pdf) {x = 0;} // if the angle of inclination with the x axis is already smaller than the negative MAX_ANGLE, the bubble should reach the rightmost else {x = cx * 2 ;} // if the tilt angle along the Y axis is still within the maximum angle if (Math. abs (yAngle) <= sensitiy) {// calculate the variation value of Y coordinates based on the skew angle along the Y axis (the larger the skew angle, the larger the Y coordinate variation) int deltaY = (int) (cy * yAngle/SENSITIVITY); y + = deltaY;} // If The tilt angle of the axis is greater than MAX_ANGLE, and the bubble should be at the bottom of the else if (yAngle> sensiti.pdf) {y = cy * 2;} // if the tilt angle along the y axis is already less than the negative MAX_ANGLE, bubble should go to the rightmost else {y = 0;} // if the calculated X and Y coordinates are still in the dashboard of the level, update the bubble coordinates of the level if (isContain (x, y) {ballX = x; ballY = y;} else {// to be further completed} // redraw the invalidate ();} // calculate whether the bubbles at the x and y points are in the private boolean isContain (int x, int y) of the Large Horizontal disc) {// calculates the coordinates of the bubble center X and Yint ballCx = x + ball. getWidth ()/2; int ballCy = y + ball. getWidth ()/2; // calculate the circle of the bubble The distance between the center of the center and the center of the Large Horizontal disc. Double distance = Math. sqrt (ballCx-backCx) * (ballCx-backCx) + (ballCy-backCy) * (ballCy-backCy); // if the distance between the two centers is smaller than their radius, you can think that the bubble at this point is still in the dashboard if (distance <cx) {return true ;}else {return false ;}}}

Package com. level. level1; import com. level. level1.R; import android. hardware. sensor; import android. hardware. sensorEvent; import android. hardware. sensorEventListener; import android. hardware. sensorManager; import android. OS. bundle; import android. app. activity; import android. widget. textView; public class MyGradienter extends Activity implements SensorEventListener {// define the level's large disc private LevelView myview; // define the Sensor manager SensorManager mySM; // define the display bar to display the x y z axis orientation and the current orientation: private TextView tx, ty, tz, td; private Sensor acc_sensor; private Sensor mag_sensor; // float accValues [] = new float [3]; // float magValues [] = new float [3]; // rotation matrix, float r [] = new float [9], which is used to store the magnetic field and acceleration data; // the data of the analog direction sensor (the original data is in radians) float values [] = new float [3]; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_my_gradienter); myview = (LevelView) findViewById (R. id. myview); tx = (TextView) findViewById (R. id. testviewx); ty = (TextView) findViewById (R. id. testviewy); tz = (TextView) findViewById (R. id. testviewz); td = (TextView) findViewById (R. id. testviewd); // get the mobile phone Sensor Management Service mySM = (SensorManager) getSystemService (SENSOR_SERVICE) ;}@ Overridepublic void onResume () {super. onResume (); acc_sensor = mySM. getdefasensensor (Sensor. TYPE_ACCELEROMETER); mag_sensor = mySM. getdefasensensor (Sensor. TYPE_MAGNETIC_FIELD); // register the listener for the sensor: mySM. registerListener (this, acc_sensor, SensorManager. SENSOR_DELAY_GAME); mySM. registerListener (this, mag_sensor, SensorManager. SENSOR_DELAY_GAME) ;}@ Overrideprotected void onPause () {// cancel listening to the direction sensor mySM. unregisterListener (this); super. onPause () ;}@ Overrideprotected void onStop () {// cancel listening to the direction sensor mySM. unregisterListener (this); super. onStop () ;}@ Overridepublic void onAccuracyChanged (Sensor arg0, int arg1) {// TODO Auto-generated method stub} @ Overridepublic void onSensorChanged (SensorEvent event) {// The sensor type int sensorType = event. sensor. getType (); switch (sensorType) {case Sensor. TYPE_ACCELEROMETER: accValues = event. values. clone (); break; case Sensor. TYPE_MAGNETIC_FIELD: magValues = event. values. clone (); break;} SensorManager. getRotationMatrix (r, null, accValues, magValues); SensorManager. getOrientation (r, values); // get the angle int zAngle = (int) Math. toDegrees (values [0]); tz. setText (":" + zAngle); // display the current position displayCompass (zAngle ); // obtain the angle int yAngle = (int) Math between the X axis and the Y axis. toDegrees (values [1]); ty. setText (":" + yAngle); // obtain the angle int xAngle = (int) Math from the X axis when scrolling along the Y axis. toDegrees (values [2]); tx. setText ("X axis angle:" + xAngle); myview. onChangeXY (zAngle, yAngle, xAngle);} private void displayCompass (int angle) {if (angle <22.5) | (angle> 337.5) td. setText ("current position on the top of the mobile phone: North"); if (angle> 22.5) & (angle <67.5) td. setText ("current position on the top of the mobile phone: Northwest"); if (angle> 67.5) & (angle <112.5) td. setText ("current position on the top of the mobile phone: West"); if (angle> 112.5) & (angle <157.5) td. setText ("current position on the top of the mobile phone: Northwest"); if (angle> 157.5) & (angle <202.5) td. setText ("current position on the top of the mobile phone: South"); if (angle> 202.5) & (angle <247.5) td. setText ("current position on the top of the mobile phone: Southeast"); if (angle> 247.5) & (angle <292.5) td. setText ("current position on the top of the mobile phone: East"); if (angle> 292.5) & (angle <337.5) td. setText ("current position on the top of the mobile phone: Northeast ");}}

 

3. Sample Code 2

 

 

Package com. tcjt. level2; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. graphics. paint. style; import android. graphics. rectF; import android. util. attributeSet; import android. view. view; public class MainView extends View {Paint paint = new Paint (); // brush Bitmap shangBitmap1; // The above large rectangle map Bitmap shangBitmap2; // The above bubble Bitmap zuoBitmap1; // Bitmap zuoBitmap2; // Bitmap zhongBitmap1; // Bitmap zhongBitmap1; // Bitmap zhongBitmap2; // Bitmap xiaBitmap1; // Bitmap xiaBitmap2 in the lower right corner of the rectangle; // the bubble in the lower right corner // The position declaration of the background rectangle int shang1_X = 60; // The large rectangle above int shang1_Y = 12; int zuo1_X = 12; // Large Rectangular graph on the left: int zuo1_Y = 60; int zhong1_X = 65; // large circular graph in the middle: int zhong1_Y = 65; int xia1_X = 145; // int xia1_Y = 145; // declaration of bubble position int shang2_X; // int shang2_Y; int zuo2_X; int zuo2_X; // bubble XY coordinate int zuo2_Y; int zhong2_X; // The small bubble XY coordinate int zhong2_Y; int xia2_X; // The bubble XY coordinate int xia2_Y in the lower right corner; public MainView (Context context, AttributeSet attrs) {super (context, attrs); initBitmap (); // initialize the image resource initLocation (); // initialize the position of the bubble} private void initBitmap () {// Method for initializing the image // some code is omitted here, And the shangBitmap1 = BitmapFactory will be introduced later. decodeResource (getResources (), R. drawable. level_shang1); shangBitmap2 = BitmapFactory. decodeResource (getResources (), R. drawable. level_shang2); zuoBitmap1 = BitmapFactory. decodeResource (getResources (), R. drawable. level_zuo1); zuoBitmap2 = BitmapFactory. decodeResource (getResources (), R. drawable. level_zuo2); zhongBitmap1 = BitmapFactory. decodeResource (getResources (), R. drawable. level_zhong1); zhongBitmap2 = BitmapFactory. decodeResource (getResources (), R. drawable. level_zhong2); xiaBitmap1 = BitmapFactory. decodeResource (getResources (), R. drawable. level_xia1); xiaBitmap2 = BitmapFactory. decodeResource (getResources (), R. drawable. level_xia2);} private void initLocation () {// Method for initializing the bubble position // some code is omitted here. We will introduce shang2_X = shang1_X + shangBitmap1.getWidth () later () /2-shangBitmap2.getWidth ()/2; shang2_Y = shang1_Y + shangBitmap1.getHeight ()/2-shangBitmap2.getHeight ()/2; zuo2_X = zuo1_X + response ()/2-example () /2; zuo2_Y = zuo1_Y + zuoBitmap1.getHeight ()/2-zuoBitmap2.getHeight ()/2; zhong2_X = zhong1_X + random ()/2-zhongBitmap2.getWidth ()/2; zhong2_Y = zhong1_Y + extract ()/2-extract ()/2; xia2_X = xia1_X + extract ()/2-xiaBitmap2.getWidth ()/2; xia2_Y = xia1_Y + xiabitmap1.height () /2-xiaBitmap2.getHeight ()/2;} @ Overrideprotected void onDraw (Canvas canvas) {// override the painting method super. onDraw (canvas); // some code is omitted here, and canvas will be introduced later. drawColor (Color. WHITE); // set the background color to WHITE paint. setColor (Color. BLUE); // set the paint color to paint. setStyle (Style. STROKE); // set the paint brush to not fill the canvas. drawRect (5, 5,315,315, paint); // draw the outer border rectangle // draw the background rectangle canvas. drawBitmap (shangBitmap1, shang1_X, shang1_Y, paint); // upper canvas. drawBitmap (zuoBitmap1, zuo1_X, zuo1_Y, paint); // left canvas. drawBitmap (zhongBitmap1, zhong1_X, zhong1_Y, paint); // canvas. drawBitmap (xiaBitmap1, xia1_X, xia1_Y, paint); // lower // start to draw the bubble canvas. drawBitmap (shangBitmap2, shang2_X, shang2_Y, paint); // upper canvas. drawBitmap (zuoBitmap2, zuo2_X, zuo2_Y, paint); // left canvas. drawBitmap (zhongBitmap2, zhong2_X, zhong2_Y, paint); // canvas. drawBitmap (xiaBitmap2, xia2_X, xia2_Y, paint); // lower paint. setColor (Color. GRAY); // set the paint brush color to draw the scale. // draw the scale canvas in the above box. drawLine (shang1_X + shangBitmap1.getWidth ()/2-7, shang1_Y, shang1_X + shangBitmap1.getWidth ()/2-7, shang1_Y + shangBitmap1.getHeight ()-2, paint); canvas. drawLine (shang1_X + shangBitmap1.getWidth ()/2 + 7, shang1_Y, shang1_X + shangBitmap1.getWidth ()/2 + 7, shang1_Y + shangBitmap1.getHeight ()-2, paint ); // draw the scale canvas in the Left box. drawLine (zuo1_X, zuo1_Y + zuoBitmap1.getHeight ()/2-7, zuo1_X + zuoBitmap1.getWidth ()-2, zuo1_Y + zuoBitmap1.getHeight ()/2-7, paint); canvas. drawLine (zuo1_X, zuo1_Y + zuoBitmap1.getHeight ()/2 + 7, zuo1_X + zuoBitmap1.getWidth ()-2, zuo1_Y + zuoBitmap1.getHeight ()/2 + 7, paint ); // draw the scale canvas in the box below. drawLine (xia1_X + extract ()/2-10, xia1_Y + xiaBitmap1.getHeight ()/2-20, xia1_X + xiaBitmap1.getWidth ()/2 + 20, xia1_Y + xiaBitmap1.getHeight () /2 + 10, paint); canvas. drawLine (xia1_X + extract ()/2-20, xia1_Y + xiaBitmap1.getHeight ()/2-10, xia1_X + xiaBitmap1.getWidth ()/2 + 10, xia1_Y + xiaBitmap1.getHeight () /2 + 20, paint); // scale (small circle) RectF oval = new RectF (zhong1_X + zhongBitmap1.getWidth ()/2-10, zhong1_Y + zhongBitmap1.getHeight () /2-10, zhong1_X + zhongBitmap1.getWidth ()/2 + 10, zhong1_Y + zhongBitmap1.getHeight ()/2 + 10); canvas. drawOval (oval, paint); // draw a baseline (circle )}}

Package com. tcjt. level2; import android. hardware. sensorListener; import android. hardware. sensorManager; import android. OS. bundle; import android. app. activity; import android. view. menu; @ SuppressWarnings ("deprecation") public class LevelActivity extends Activity {int k = 45; // sensitivity MainView mv; // host SensorManager mySensorManager; // during testing // SensorManagerSimulator mySensorManager; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_level); mv = (MainView) findViewById (R. id. mainView); mySensorManager = (SensorManager) getSystemService (SENSOR_SERVICE); // real machine} private final SensorListener mSensorLisener = new SensorListener () {@ Overridepublic void merge (int sensor, int accuracy) {} public boolean isContain (int x, int y) {// judge whether the vertex is in the circle int tempx = (int) (x + mv. zhongBitmap2.getWidth ()/2.0); int tempy = (int) (y + mv. zhongBitmap2.getWidth ()/2.0); int ox = (int) (mv. zhong1_X + mv. zhongBitmap1.getWidth ()/2.0); int oy = (int) (mv. zhong1_X + mv. zhongBitmap1.getWidth ()/2.0); if (Math. sqrt (tempx-ox) * (tempx-ox) + (tempy-oy) * (tempy-oy)> (mv. zhongBitmap1.getWidth ()/2.0-mv. zhongBitmap2.getWidth ()/2.0) {// return false if not in the circle;} else {// return true when in the circle; }}@ Overridepublic void onSensorChanged (int sensor, float [] values) {if (sensor = SensorManager. SENSOR_ORIENTATION) {double pitch = values [SensorManager. DATA_Y]; double roll = values [SensorManager. DATA_Z]; int x = 0; int y = 0; // temporary variable. Use int tempX = 0 when calculating the bubble coordinate in the middle; int tempY = 0; // The temporary variable of the following bubble // start to adjust the value of x if (Math. abs (roll) <= k) {mv. shang2_X = mv. shang1_X // The above + (int) (mv. shangBitmap1.getWidth ()-mv. shangBitmap2.getWidth ()/2.0)-(mv. shangBitmap1.getWidth ()-mv. shangBitmap2.getWidth ()/2.0) * roll)/k); x = mv. zhong1_X // The + (int) (mv. zhongBitmap1.getWidth ()-mv. zhongBitmap2.getWidth ()/2.0)-(mv. zhongBitmap1.getWidth ()-mv. zhongBitmap2.getWidth ()/2.0) * roll)/k);} else if (roll> k) {mv. shang2_X = mv. shang1_X; x = mv. zhong1_X;} else {mv. shang2_X = mv. shang1_X + mv. shangBitmap1.getWidth ()-mv. shangBitmap2.getWidth (); x = mv. zhong1_X + mv. zhongBitmap1.getWidth ()-mv. zhongBitmap2.getWidth ();} // start to adjust the value of y if (Math. abs (pitch) <= k) {mv. zuo2_Y = mv. zuo1_Y // + (int) (mv. zuoBitmap1.getHeight ()-mv. zuoBitmap2.getHeight ()/2.0) + (mv. zuoBitmap1.getHeight ()-mv. zuoBitmap2.getHeight ()/2.0) * pitch)/k); y = mv. zhong1_Y + // The intermediate (int) (mv. zhongBitmap1.getHeight ()-mv. zhongBitmap2.getHeight ()/2.0) + (mv. zhongBitmap1.getHeight ()-mv. zhongBitmap2.getHeight ()/2.0) * pitch)/k);} else if (pitch> k) {mv. zuo2_Y = mv. zuo1_Y + mv. zuoBitmap1.getHeight ()-mv. zuoBitmap2.getHeight (); y = mv. zhong1_Y + mv. zhongBitmap1.getHeight ()-mv. zhongBitmap2.getHeight ();} else {mv. zuo2_Y = mv. zuo1_Y; y = mv. zhong1_Y;} // The following tempX =-(int) (mv. xiaBitmap1.getWidth ()/2-28) * roll + (mv. xiaBitmap1.getWidth ()/2-28) * pitch)/k); tempY =-(int) (-(mv. xiaBitmap1.getWidth ()/2-28) * roll-(mv. xiaBitmap1.getWidth ()/2-28) * pitch)/k); // limits the bubble range below if (tempY> mv. xiaBitmap1.getHeight ()/2-28) {tempY = mv. xiaBitmap1.getHeight ()/2-28;} if (tempY <-mv. xiaBitmap1.getHeight ()/2 + 28) {tempY =-mv. xiaBitmap1.getHeight ()/2 + 28;} if (tempX> mv. xiaBitmap1.getWidth ()/2-28) {tempX = mv. xiaBitmap1.getWidth ()/2-28;} if (tempX <-mv. xiaBitmap1.getWidth ()/2 + 28) {tempX =-mv. xiaBitmap1.getWidth ()/2 + 28;} mv. xia2_X = tempX + mv. xia1_X + mv. xiaBitmap1.getWidth ()/2-mv. xiaBitmap2.getWidth ()/2; mv. xia2_Y = tempY + mv. xia1_Y + mv. xiaBitmap1.getHeight ()/2-mv. xiaBitmap2.getWidth ()/2; if (isContain (x, y) {// the bubble in the center changes the coordinates in the circle. zhong2_X = x; mv. zhong2_Y = y;} mv. postInvalidate (); // redraw MainView} // The sensor listener class // some code is omitted here, which will be introduced later}; @ Overrideprotected void onResume () {// Add listening mySensorManager. registerListener (mSensorLisener, SensorManager. SENSOR_ORIENTATION); super. onResume () ;}@ Overrideprotected void onPause () {// cancel listening to mySensorManager. unregisterListener (mSensorLisener); super. onPause () ;}@ Overridepublic boolean onCreateOptionsMenu (Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater (). inflate (R. menu. activity_level, menu); return true ;}}
Both examples can achieve the leveling effect. I will not post the image. You can refer to the Code in it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.