您好,登錄后才能下訂單哦!
<?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;// 最多旋轉一周,即360° private SensorManager mSensorManager;// 傳感器管理對象 private Sensor mOrientationSensor;// 傳感器對象 private float mDirection;// 當前浮點方向 private float mTargetDirection;// 目標浮點方向 private AccelerateInterpolator mInterpolator;// 動畫從開始到結束,變化率是一個加速的過程,就是一個動畫速率 protected final Handler mHandler = new Handler(); private boolean mStopDrawing;// 是否停止指南針旋轉的標志位 private boolean mChinease;// 系統當前是否使用中文 private long firstExitTime = 0L;// 用來保存第一次按返回鍵的時間 View mCompassView; CompassView mPointer;// 指南針view LinearLayout mDirectionLayout;// 顯示方向(東南西北)的view LinearLayout mAngleLayout;// 顯示方向度數的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(); } // 這個是更新指南針旋轉的線程,handler的靈活使用,每20毫秒檢測方向變化值,對應更新指南針旋轉 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)));// 用了一個加速動畫去旋轉圖片,很細致 mPointer.updateDirection(mDirection);// 更新指南針旋轉 } updateDirection();// 更新方向值 mHandler.postDelayed(mCompassViewUpdater, 20);// 20毫米后重新執行自己,比定時器好 } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initResources();// 初始化view initServices();// 初始化傳感器和位置服務 } @Override public void onBackPressed() {// 覆蓋返回鍵 long curTime = System.currentTimeMillis(); if (curTime - firstExitTime < EXIT_TIME) {// 兩次按返回鍵的時間小于2秒就退出應用 finish(); } else { Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show(); firstExitTime = curTime; } } @Override protected void onResume() {// 在恢復的生命周期里判斷、啟動位置更新服務和傳感器服務 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毫秒執行一次更新指南針圖片旋轉 } @Override protected void onPause() {// 在暫停的生命周期里注銷傳感器服務和位置更新服務 super.onPause(); mStopDrawing = true; if (mOrientationSensor != null) { mSensorManager.unregisterListener(mOrientationSensorEventListener); } } // 方向傳感器變化監聽 private SensorEventListener mOrientationSensorEventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { float direction = event.values[mSensorManager.DATA_X] * -1.0f; mTargetDirection = normalizeDegree(direction);// 賦值給全局變量,讓指南針旋轉 } @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;// 初始化目標方向 mInterpolator = new AccelerateInterpolator();// 實例化加速動畫對象 mStopDrawing = true; mChinease = TextUtils.equals(Locale.getDefault().getLanguage(), "zh");// 判斷系統當前使用的語言是否為中文 mCompassView = findViewById(R.id.view_compass);// 實際上是一個LinearLayout,裝指南針ImageView和位置TextView mPointer = (CompassView) findViewById(R.id.compass_pointer);// 自定義的指南針view mDirectionLayout = (LinearLayout) findViewById(R.id.layout_direction);// 頂部顯示方向名稱(東南西北)的LinearLayout mAngleLayout = (LinearLayout) findViewById(R.id.layout_angle);// 頂部顯示方向具體度數的LinearLayout } // 初始化傳感器和位置服務 private void initServices() { // sensor manager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mOrientationSensor = mSensorManager.getSensorList( Sensor.TYPE_ORIENTATION).get(0); } // 調整方向傳感器獲取的值 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(); // 下面是根據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); } // 下面是根據系統使用語言,更換對應的語言圖片資源 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); } } // 下面是根據方向度數顯示度數圖片數字 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)); // 下面是增加一個°的圖片 ImageView degreeImageView = new ImageView(this); degreeImageView.setImageResource(R.drawable.degree); degreeImageView.setLayoutParams(lp); mAngleLayout.addView(degreeImageView); } // 獲取方向度數對應的圖片,返回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;// 方向旋轉浮點數 private Drawable compass;// 圖片資源 // 三個構造器 public CompassView(Context context) { super(context); mDirection = 0.0f;// 默認不旋轉 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();// 獲取當前view的圖片資源 compass.setBounds(0, 0, getWidth(), getHeight());// 圖片資源在view的位置,此處相當于充滿view } canvas.save(); canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);// 繞圖片中心點旋轉, compass.draw(canvas);// 把旋轉后的圖片畫在view上,即保持旋轉后的樣子 canvas.restore();// 保存一下 } /** * 自定義更新方向的方法 * * @param direction * 傳入的方向 */ public void updateDirection(float direction) { mDirection = direction; invalidate();// 重新刷新一下,更新方向 } }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。