<?xmlversion="1.0"encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/view_compass"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"><FrameLayoutandroid:layout_width="fill_parent"android:layout_height="0.0dip"android:layout_weight="1.0"android:background="@drawable/background_compass"android:gravity="center"><LinearLayoutandroid: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.CompassViewandroid: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"/><LinearLayoutandroid: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><FrameLayoutandroid:id="@+id/view_guide"android:layout_width="fill_parent"android:layout_height="fill_parent"android:visibility="gone"><ImageViewandroid:id="@+id/guide_description"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_gravity="center"android:background="@drawable/guide"/><ImageViewandroid: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>packagecom.example.compass;importjava.util.Locale;importandroid.graphics.drawable.AnimationDrawable;importandroid.hardware.Sensor;importandroid.hardware.SensorEvent;importandroid.hardware.SensorEventListener;importandroid.hardware.SensorManager;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Message;importandroid.text.TextUtils;importandroid.view.View;importandroid.view.ViewGroup.LayoutParams;importandroid.view.animation.AccelerateInterpolator;importandroid.widget.ImageView;importandroid.widget.LinearLayout;importandroid.widget.Toast;importandroid.annotation.SuppressLint;importandroid.app.Activity;importandroid.content.Context;publicclassCompassActivityextendsActivity{privatestaticfinalintEXIT_TIME=2000;//两次按返回键的间隔判断privatefinalfloatMAX_ROATE_DEGREE=1.0f;//最多旋转一周,即360°privateSensorManagermSensorManager;//传感器管理对象privateSensormOrientationSensor;//传感器对象privatefloatmDirection;//当前浮点方向privatefloatmTargetDirection;//目标浮点方向privateAccelerateInterpolatormInterpolator;//动画从开始到结束,变化率是一个加速的过程,就是一个动画速率protectedfinalHandlermHandler=newHandler();privatebooleanmStopDrawing;//是否停止指南针旋转的标志位privatebooleanmChinease;//系统当前是否使用中文privatelongfirstExitTime=0L;//用来保存第一次按返回键的时间ViewmCompassView;CompassViewmPointer;//指南针viewLinearLayoutmDirectionLayout;//显示方向(东南西北)的viewLinearLayoutmAngleLayout;//显示方向度数的viewViewmViewGuide;ImageViewmGuideAnimation;@SuppressLint("HandlerLeak")protectedHandlerinvisiableHandler=newHandler(){publicvoidhandleMessage(Messagemsg){mViewGuide.setVisibility(View.GONE);}};publicvoidonWindowFocusChanged(booleanhasFocus){AnimationDrawableanim=(AnimationDrawable)mGuideAnimation.getDrawable();anim.start();}//这个是更新指南针旋转的线程,handler的灵活使用,每20毫秒检测方向变化值,对应更新指南针旋转protectedRunnablemCompassViewUpdater=newRunnable(){@Overridepublicvoidrun(){if(mPointer!=null&&!mStopDrawing){if(mDirection!=mTargetDirection){//calculatetheshortroutinefloatto=mTargetDirection;if(to-mDirection>180){to-=360;}elseif(to-mDirection<-180){to+=360;}//limitthemaxspeedtoMAX_ROTATE_DEGREEfloatdistance=to-mDirection;if(Math.abs(distance)>MAX_ROATE_DEGREE){distance=distance>0?MAX_ROATE_DEGREE:(-1.0f*MAX_ROATE_DEGREE);}//needtoslowdownifthedistanceisshortmDirection=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毫米后重新执行自己,比定时器好}}};@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initResources();//初始化viewinitServices();//初始化传感器和位置服务}@OverridepublicvoidonBackPressed(){//覆盖返回键longcurTime=System.currentTimeMillis();if(curTime-firstExitTime<EXIT_TIME){//两次按返回键的时间小于2秒就退出应用finish();}else{Toast.makeText(this,"再按一次退出",Toast.LENGTH_SHORT).show();firstExitTime=curTime;}}@OverrideprotectedvoidonResume(){//在恢复的生命周期里判断、启动位置更新服务和传感器服务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毫秒执行一次更新指南针图片旋转}@OverrideprotectedvoidonPause(){//在暂停的生命周期里注销传感器服务和位置更新服务super.onPause();mStopDrawing=true;if(mOrientationSensor!=null){mSensorManager.unregisterListener(mOrientationSensorEventListener);}}//方向传感器变化监听privateSensorEventListenermOrientationSensorEventListener=newSensorEventListener(){@OverridepublicvoidonSensorChanged(SensorEventevent){floatdirection=event.values[mSensorManager.DATA_X]*-1.0f;mTargetDirection=normalizeDegree(direction);//赋值给全局变量,让指南针旋转}@OverridepublicvoidonAccuracyChanged(Sensorsensor,intaccuracy){}};//初始化viewprivatevoidinitResources(){mViewGuide=findViewById(R.id.view_guide);mViewGuide.setVisibility(View.VISIBLE);invisiableHandler.sendMessageDelayed(newMessage(),3000);mGuideAnimation=(ImageView)findViewById(R.id.guide_animation);mDirection=0.0f;//初始化起始方向mTargetDirection=0.0f;//初始化目标方向mInterpolator=newAccelerateInterpolator();//实例化加速动画对象mStopDrawing=true;mChinease=TextUtils.equals(Locale.getDefault().getLanguage(),"zh");//判断系统当前使用的语言是否为中文mCompassView=findViewById(R.id.view_compass);//实际上是一个LinearLayout,装指南针ImageView和位置TextViewmPointer=(CompassView)findViewById(R.id.compass_pointer);//自定义的指南针viewmDirectionLayout=(LinearLayout)findViewById(R.id.layout_direction);//顶部显示方向名称(东南西北)的LinearLayoutmAngleLayout=(LinearLayout)findViewById(R.id.layout_angle);//顶部显示方向具体度数的LinearLayout}//初始化传感器和位置服务privatevoidinitServices(){//sensormanagermSensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);mOrientationSensor=mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION).get(0);}//调整方向传感器获取的值privatefloatnormalizeDegree(floatdegree){return(degree+720)%360;}//更新顶部方向显示的方法privatevoidupdateDirection(){LayoutParamslp=newLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);//先移除layout中所有的viewmDirectionLayout.removeAllViews();mAngleLayout.removeAllViews();//下面是根据mTargetDirection,作方向名称图片的处理ImageVieweast=null;ImageViewwest=null;ImageViewsouth=null;ImageViewnorth=null;floatdirection=normalizeDegree(mTargetDirection*-1.0f);if(direction>22.5f&&direction<157.5f){//easteast=newImageView(this);east.setImageResource(mChinease?R.drawable.e_cn:R.drawable.e);east.setLayoutParams(lp);}elseif(direction>202.5f&&direction<337.5f){//westwest=newImageView(this);west.setImageResource(mChinease?R.drawable.w_cn:R.drawable.w);west.setLayoutParams(lp);}if(direction>112.5f&&direction<247.5f){//southsouth=newImageView(this);south.setImageResource(mChinease?R.drawable.s_cn:R.drawable.s);south.setLayoutParams(lp);}elseif(direction<67.5||direction>292.5f){//northnorth=newImageView(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/southshouldbebeforeeast/westif(south!=null){mDirectionLayout.addView(south);}if(north!=null){mDirectionLayout.addView(north);}if(east!=null){mDirectionLayout.addView(east);}if(west!=null){mDirectionLayout.addView(west);}}//下面是根据方向度数显示度数图片数字intdirection2=(int)direction;booleanshow=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));//下面是增加一个°的图片ImageViewdegreeImageView=newImageView(this);degreeImageView.setImageResource(R.drawable.degree);degreeImageView.setLayoutParams(lp);mAngleLayout.addView(degreeImageView);}//获取方向度数对应的图片,返回ImageViewprivateImageViewgetNumberImage(intnumber){ImageViewimage=newImageView(this);LayoutParamslp=newLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);switch(number){case0:image.setImageResource(R.drawable.number_0);break;case1:image.setImageResource(R.drawable.number_1);break;case2:image.setImageResource(R.drawable.number_2);break;case3:image.setImageResource(R.drawable.number_3);break;case4:image.setImageResource(R.drawable.number_4);break;case5:image.setImageResource(R.drawable.number_5);break;case6:image.setImageResource(R.drawable.number_6);break;case7:image.setImageResource(R.drawable.number_7);break;case8:image.setImageResource(R.drawable.number_8);break;case9:image.setImageResource(R.drawable.number_9);break;}image.setLayoutParams(lp);returnimage;}}packagecom.example.compass;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.drawable.Drawable;importandroid.util.AttributeSet;importandroid.widget.ImageView;publicclassCompassViewextendsImageView{privatefloatmDirection;//方向旋转浮点数privateDrawablecompass;//图片资源//三个构造器publicCompassView(Contextcontext){super(context);mDirection=0.0f;//默认不旋转compass=null;}publicCompassView(Contextcontext,AttributeSetattrs){super(context,attrs);mDirection=0.0f;compass=null;}publicCompassView(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);mDirection=0.0f;compass=null;}@OverrideprotectedvoidonDraw(Canvascanvas){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();//保存一下}/***自定义更新方向的方法**@paramdirection*传入的方向*/publicvoidupdateDirection(floatdirection){mDirection=direction;invalidate();//重新刷新一下,更新方向}}

更多相关文章

  1. 工程师淘金:开发Android主攻四大方向
  2. android:screenOrientation 强制屏幕方向
  3. Android加速度传感器
  4. Android在应用中固定屏幕方向

随机推荐

  1. Android(安卓)原生项目集成React Native
  2. 短信监听,自动获短信取验证码
  3. Android(安卓)屏幕适配全攻略
  4. Android实现不同Active页面间的跳转
  5. 【MAC版】Android(安卓)ADB server didn'
  6. batT脚本如何自动执行 adb shell 以后的
  7. 2020Android初中级面试知识点记录——And
  8. Android中 View not attached to window
  9. Android(安卓)4.0 截屏(Screenshot)代码
  10. Android(安卓)App 性能优化