<?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(安卓)利用Matrix实现图片随手指平移、旋转、缩放
  2. 深入探讨 Android(安卓)传感器
  3. 工程师淘金:开发Android主攻四大方向
  4. 工程师淘金:开发Android主攻四大方向
  5. Android(安卓)传感器
  6. Android(安卓)开发新方向 Android(安卓)Wear ——概述
  7. 工程师淘金:开发Android主攻四大方向
  8. Android实现图片缩放与旋转
  9. 屏幕方向android:screenOrientation

随机推荐

  1. Android(安卓)XML 中schema和自定义属性
  2. 在ListView中增加HeaderView和FootView
  3. Android(安卓)TextView中标点符号或英文
  4. 关于Android串口通讯总结
  5. BroadcastReceiver与Notification的综合
  6. 关于android的零碎问题的整理
  7. 观察:Android与潮流一起,机遇无处不在
  8. 1与2(CSS与HTML).1—— 一个比较通用的网站
  9. Android序列化详解及最佳实践(Serialize&P
  10. Android让VideoView填充满屏幕/父布局并