溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

android 指南針

發(fā)布時(shí)間:2020-07-06 21:09:19 來源:網(wǎng)絡(luò) 閱讀:320 作者:lg491733638 欄目:移動(dòng)開發(fā)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <LinearLayout
        android:id="@+id/view_compass"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
        <FrameLayout
            android:layout_width="fill_parent"
            android:layout_height="0.0dip"
            android:layout_weight="1.0"
            android:background="@drawable/background_compass"
            android:gravity="center" >

            <LinearLayout
                android:id="@+id/layout_direction"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="@dimen/direction_margin_top"
                android:textColor="@android:color/white"
                android:orientation="horizontal"
               /> 
               
                <com.example.compass.CompassView
                android:id="@+id/compass_pointer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="@dimen/compass_margin_top"
                android:src="@drawable/compass" />
            <LinearLayout
                android:id="@+id/layout_angle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginLeft="2.0dip"
                android:layout_marginTop="@dimen/degree_text_margin_top"
                android:orientation="horizontal" />
        </FrameLayout>
    </LinearLayout>
    <FrameLayout
        android:id="@+id/view_guide"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone" >
        <ImageView
            android:id="@+id/guide_description"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:background="@drawable/guide" />
        <ImageView
            android:id="@+id/guide_animation"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|center"
            android:layout_marginTop="195.0dip"
            android:src="@drawable/calibrate_animation" />
    </FrameLayout>
</FrameLayout>
package com.example.compass;
import java.util.Locale;
import android.graphics.drawable.AnimationDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
public class CompassActivity extends Activity {
 private static final int EXIT_TIME = 2000;// 兩次按返回鍵的間隔判斷
 private final float MAX_ROATE_DEGREE = 1.0f;// 最多旋轉(zhuǎn)一周,即360°
 private SensorManager mSensorManager;// 傳感器管理對(duì)象
 private Sensor mOrientationSensor;// 傳感器對(duì)象
 private float mDirection;// 當(dāng)前浮點(diǎn)方向
 private float mTargetDirection;// 目標(biāo)浮點(diǎn)方向
 private AccelerateInterpolator mInterpolator;// 動(dòng)畫從開始到結(jié)束,變化率是一個(gè)加速的過程,就是一個(gè)動(dòng)畫速率
 protected final Handler mHandler = new Handler();
 private boolean mStopDrawing;// 是否停止指南針旋轉(zhuǎn)的標(biāo)志位
 private boolean mChinease;// 系統(tǒng)當(dāng)前是否使用中文
 private long firstExitTime = 0L;// 用來保存第一次按返回鍵的時(shí)間
 View mCompassView;
 CompassView mPointer;// 指南針view
 LinearLayout mDirectionLayout;// 顯示方向(東南西北)的view
 LinearLayout mAngleLayout;// 顯示方向度數(shù)的view
 View mViewGuide;
 ImageView mGuideAnimation;
 @SuppressLint("HandlerLeak")
 protected Handler invisiableHandler = new Handler() {
  public void handleMessage(Message msg) {
   mViewGuide.setVisibility(View.GONE);
  }
 };
 public void onWindowFocusChanged(boolean hasFocus) {
  AnimationDrawable anim = (AnimationDrawable) mGuideAnimation
    .getDrawable();
  anim.start();
 }
 // 這個(gè)是更新指南針旋轉(zhuǎn)的線程,handler的靈活使用,每20毫秒檢測(cè)方向變化值,對(duì)應(yīng)更新指南針旋轉(zhuǎn)
 protected Runnable mCompassViewUpdater = new Runnable() {
  @Override
  public void run() {
   if (mPointer != null && !mStopDrawing) {
    if (mDirection != mTargetDirection) {
     // calculate the short routine
     float to = mTargetDirection;
     if (to - mDirection > 180) {
      to -= 360;
     } else if (to - mDirection < -180) {
      to += 360;
     }
     // limit the max speed to MAX_ROTATE_DEGREE
     float distance = to - mDirection;
     if (Math.abs(distance) > MAX_ROATE_DEGREE) {
      distance = distance > 0 ? MAX_ROATE_DEGREE
        : (-1.0f * MAX_ROATE_DEGREE);
     }
     // need to slow down if the distance is short
     mDirection = normalizeDegree(mDirection
       + ((to - mDirection) * mInterpolator
         .getInterpolation(Math.abs(distance) > MAX_ROATE_DEGREE ? 0.4f
           : 0.3f)));// 用了一個(gè)加速動(dòng)畫去旋轉(zhuǎn)圖片,很細(xì)致
     mPointer.updateDirection(mDirection);// 更新指南針旋轉(zhuǎn)
    }
    updateDirection();// 更新方向值
    mHandler.postDelayed(mCompassViewUpdater, 20);// 20毫米后重新執(zhí)行自己,比定時(shí)器好
   }
  }
 };
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  initResources();// 初始化view
  initServices();// 初始化傳感器和位置服務(wù)
 }
 @Override
 public void onBackPressed() {// 覆蓋返回鍵
  long curTime = System.currentTimeMillis();
  if (curTime - firstExitTime < EXIT_TIME) {// 兩次按返回鍵的時(shí)間小于2秒就退出應(yīng)用
   finish();
  } else {
   Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
   firstExitTime = curTime;
  }
 }
 @Override
 protected void onResume() {// 在恢復(fù)的生命周期里判斷、啟動(dòng)位置更新服務(wù)和傳感器服務(wù)
  super.onResume();
  if (mOrientationSensor != null) {
   mSensorManager.registerListener(mOrientationSensorEventListener,
     mOrientationSensor, SensorManager.SENSOR_DELAY_GAME);
  } else {
    Toast.makeText(this, "不能找到傳感器!",
    Toast.LENGTH_SHORT)
    .show();
  }
  mStopDrawing = false;
  mHandler.postDelayed(mCompassViewUpdater, 20);// 20毫秒執(zhí)行一次更新指南針圖片旋轉(zhuǎn)
 }
 @Override
 protected void onPause() {// 在暫停的生命周期里注銷傳感器服務(wù)和位置更新服務(wù)
  super.onPause();
  mStopDrawing = true;
  if (mOrientationSensor != null) {
   mSensorManager.unregisterListener(mOrientationSensorEventListener);
  }
 }
 // 方向傳感器變化監(jiān)聽
 private SensorEventListener mOrientationSensorEventListener = new SensorEventListener() {
  @Override
  public void onSensorChanged(SensorEvent event) {
   float direction = event.values[mSensorManager.DATA_X] * -1.0f;
   mTargetDirection = normalizeDegree(direction);// 賦值給全局變量,讓指南針旋轉(zhuǎn)
  }
  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }
 };
 // 初始化view
 private void initResources() {
  mViewGuide = findViewById(R.id.view_guide);
  mViewGuide.setVisibility(View.VISIBLE);
  invisiableHandler.sendMessageDelayed(new Message(), 3000);
  mGuideAnimation = (ImageView) findViewById(R.id.guide_animation);
  mDirection = 0.0f;// 初始化起始方向
  mTargetDirection = 0.0f;// 初始化目標(biāo)方向
  mInterpolator = new AccelerateInterpolator();// 實(shí)例化加速動(dòng)畫對(duì)象
  mStopDrawing = true;
  mChinease = TextUtils.equals(Locale.getDefault().getLanguage(), "zh");// 判斷系統(tǒng)當(dāng)前使用的語言是否為中文
  mCompassView = findViewById(R.id.view_compass);// 實(shí)際上是一個(gè)LinearLayout,裝指南針I(yè)mageView和位置TextView
  mPointer = (CompassView) findViewById(R.id.compass_pointer);// 自定義的指南針view
  mDirectionLayout = (LinearLayout) findViewById(R.id.layout_direction);// 頂部顯示方向名稱(東南西北)的LinearLayout
  mAngleLayout = (LinearLayout) findViewById(R.id.layout_angle);// 頂部顯示方向具體度數(shù)的LinearLayout
 }
 // 初始化傳感器和位置服務(wù)
 private void initServices() {
  // sensor manager
  mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  mOrientationSensor = mSensorManager.getSensorList(
    Sensor.TYPE_ORIENTATION).get(0);
 }
 // 調(diào)整方向傳感器獲取的值
 private float normalizeDegree(float degree) {
  return (degree + 720) % 360;
 }
 // 更新頂部方向顯示的方法
 private void updateDirection() {
  LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT);
  // 先移除layout中所有的view
  mDirectionLayout.removeAllViews();
  mAngleLayout.removeAllViews();
  // 下面是根據(jù)mTargetDirection,作方向名稱圖片的處理
  ImageView east = null;
  ImageView west = null;
  ImageView south = null;
  ImageView north = null;
  float direction = normalizeDegree(mTargetDirection * -1.0f);
  if (direction > 22.5f && direction < 157.5f) {
   // east
   east = new ImageView(this);
   east.setImageResource(mChinease ? R.drawable.e_cn : R.drawable.e);
   east.setLayoutParams(lp);
  } else if (direction > 202.5f && direction < 337.5f) {
   // west
   west = new ImageView(this);
   west.setImageResource(mChinease ? R.drawable.w_cn : R.drawable.w);
   west.setLayoutParams(lp);
  }
  if (direction > 112.5f && direction < 247.5f) {
   // south
   south = new ImageView(this);
   south.setImageResource(mChinease ? R.drawable.s_cn : R.drawable.s);
   south.setLayoutParams(lp);
  } else if (direction < 67.5 || direction > 292.5f) {
   // north
   north = new ImageView(this);
   north.setImageResource(mChinease ? R.drawable.n_cn : R.drawable.n);
   north.setLayoutParams(lp);
  }
  // 下面是根據(jù)系統(tǒng)使用語言,更換對(duì)應(yīng)的語言圖片資源
  if (mChinease) {
   if (east != null) {
    mDirectionLayout.addView(east);
   }
   if (west != null) {
    mDirectionLayout.addView(west);
   }
   if (south != null) {
    mDirectionLayout.addView(south);
   }
   if (north != null) {
    mDirectionLayout.addView(north);
   }
  } else {
   // north/south should be before east/west
   if (south != null) {
    mDirectionLayout.addView(south);
   }
   if (north != null) {
    mDirectionLayout.addView(north);
   }
   if (east != null) {
    mDirectionLayout.addView(east);
   }
   if (west != null) {
    mDirectionLayout.addView(west);
   }
  }
  // 下面是根據(jù)方向度數(shù)顯示度數(shù)圖片數(shù)字
  int direction2 = (int) direction;
  boolean show = false;
  if (direction2 >= 100) {
   mAngleLayout.addView(getNumberImage(direction2 / 100));
   direction2 %= 100;
   show = true;
  }
  if (direction2 >= 10 || show) {
   mAngleLayout.addView(getNumberImage(direction2 / 10));
   direction2 %= 10;
  }
  mAngleLayout.addView(getNumberImage(direction2));
  // 下面是增加一個(gè)°的圖片
  ImageView degreeImageView = new ImageView(this);
  degreeImageView.setImageResource(R.drawable.degree);
  degreeImageView.setLayoutParams(lp);
  mAngleLayout.addView(degreeImageView);
 }
 // 獲取方向度數(shù)對(duì)應(yīng)的圖片,返回ImageView
 private ImageView getNumberImage(int number) {
  ImageView p_w_picpath = new ImageView(this);
  LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT);
  switch (number) {
  case 0:
   p_w_picpath.setImageResource(R.drawable.number_0);
   break;
  case 1:
   p_w_picpath.setImageResource(R.drawable.number_1);
   break;
  case 2:
   p_w_picpath.setImageResource(R.drawable.number_2);
   break;
  case 3:
   p_w_picpath.setImageResource(R.drawable.number_3);
   break;
  case 4:
   p_w_picpath.setImageResource(R.drawable.number_4);
   break;
  case 5:
   p_w_picpath.setImageResource(R.drawable.number_5);
   break;
  case 6:
   p_w_picpath.setImageResource(R.drawable.number_6);
   break;
  case 7:
   p_w_picpath.setImageResource(R.drawable.number_7);
   break;
  case 8:
   p_w_picpath.setImageResource(R.drawable.number_8);
   break;
  case 9:
   p_w_picpath.setImageResource(R.drawable.number_9);
   break;
  }
  p_w_picpath.setLayoutParams(lp);
  return p_w_picpath;
 }
}
package com.example.compass;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class CompassView extends ImageView {
 private float mDirection;// 方向旋轉(zhuǎn)浮點(diǎn)數(shù)
 private Drawable compass;// 圖片資源
 // 三個(gè)構(gòu)造器
 public CompassView(Context context) {
  super(context);
  mDirection = 0.0f;// 默認(rèn)不旋轉(zhuǎn)
  compass = null;
 }
 public CompassView(Context context, AttributeSet attrs) {
  super(context, attrs);
  mDirection = 0.0f;
  compass = null;
 }
 public CompassView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  mDirection = 0.0f;
  compass = null;
 }
 @Override
 protected void onDraw(Canvas canvas) {
  if (compass == null) {
   compass = getDrawable();// 獲取當(dāng)前view的圖片資源
   compass.setBounds(0, 0, getWidth(), getHeight());// 圖片資源在view的位置,此處相當(dāng)于充滿view
  }
  canvas.save();
  canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);// 繞圖片中心點(diǎn)旋轉(zhuǎn),
  compass.draw(canvas);// 把旋轉(zhuǎn)后的圖片畫在view上,即保持旋轉(zhuǎn)后的樣子
  canvas.restore();// 保存一下
 }
 /**
  * 自定義更新方向的方法
  * 
  * @param direction
  *            傳入的方向
  */
 public void updateDirection(float direction) {
  mDirection = direction;
  invalidate();// 重新刷新一下,更新方向
 }
}

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI