标签:
点我下载源码
5月12日更新到V5版:http://download.csdn.net/detail/weidi1989/5364243
今天,在小米的开源项目中下载了一个指南针源码学习了一下,感觉不仅界面做得很漂亮,代码也是很精致,所以我在研究了之后,加了比较多的注释,果断跟大家分享一下,很精简的几段代码,仔细品味可以学到很多东西,我稍微总结一下:
①.handler的灵活运用,每20秒后执行一次自己,用来检测方向变化值,更新指南针旋转。
②.传感器和谷歌位置服务的使用。
③.自定义View,这里面是自定义一个ImageView,自己增加一个旋转图片的方法。
④.Android动画Interpolator插入器:AccelerateInterpolator加速插入器的运用。顺便说一下另外几个插入器:
——AccelerateInterpolator:动画从开始到结束,变化率是一个加速的过程。
——DecelerateInterpolator:动画从开始到结束,变化率是一个减速的过程。
——CycleInterpolator:动画从开始到结束,变化率是循环给定次数的正弦曲线。
——AccelerateDecelerateInterpolator:动画从开始到结束,变化率是先加速后减速的过程。
——LinearInterpolator:动画从开始到结束,变化率是线性变化。
AccelerateInterpolator有一个方法:getInterpolation(float input);
⑤.巧妙的数字替换成对应的数字图片和根据本地语言使用对应的图片资源(图片资源国际化,哈哈)。还有一些其他的小知识,朋友们,自己下载去研究吧!
下面看一下效果图(我的是模拟器,木有传感器也木有定位的):
下面我们来看一下这个界面的布局文件(main.xml):
这其中用到了一个自定义view,其实就是中间那个可以旋转的指南针,我们也来看看它的代码(CompassView.java):
- 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();
- compass.setBounds(0, 0, getWidth(), getHeight());
- }
-
- canvas.save();
- canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);
- compass.draw(canvas);
- canvas.restore();
- }
-
-
- public void updateDirection(float direction) {
- mDirection = direction;
- invalidate();
- }
-
- }
接下来就只剩下一个Activity了,其实总体结构还是很简单的,CompassActivity.java:
- public class CompassActivity extends Activity {
- private static final int EXIT_TIME = 2000;
- private final float MAX_ROATE_DEGREE = 1.0f;
- private SensorManager mSensorManager;
- private Sensor mOrientationSensor;
- private LocationManager mLocationManager;
- private String mLocationProvider;
- 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;
- TextView mLocationTextView;
- LinearLayout mDirectionLayout;
- LinearLayout mAngleLayout;
-
-
- protected Runnable mCompassViewUpdater = new Runnable() {
- @Override
- public void run() {
- if (mPointer != null && !mStopDrawing) {
- if (mDirection != mTargetDirection) {
-
-
- float to = mTargetDirection;
- if (to - mDirection > 180) {
- to -= 360;
- } else if (to - mDirection < -180) {
- to += 360;
- }
-
-
- float distance = to - mDirection;
- if (Math.abs(distance) > MAX_ROATE_DEGREE) {
- distance = distance > 0 ? MAX_ROATE_DEGREE
- : (-1.0f * MAX_ROATE_DEGREE);
- }
-
-
- 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);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- initResources();
- initServices();
- }
-
- @Override
- public void onBackPressed() {
- long curTime = System.currentTimeMillis();
- if (curTime - firstExitTime < EXIT_TIME) {
- finish();
- } else {
- Toast.makeText(this, R.string.exit_toast, Toast.LENGTH_SHORT)
- .show();
- firstExitTime = curTime;
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (mLocationProvider != null) {
- updateLocation(mLocationManager
- .getLastKnownLocation(mLocationProvider));
- mLocationManager.requestLocationUpdates(mLocationProvider, 2000,
- 10, mLocationListener);
- } else {
- mLocationTextView.setText(R.string.cannot_get_location);
- }
- if (mOrientationSensor != null) {
- mSensorManager.registerListener(mOrientationSensorEventListener,
- mOrientationSensor, SensorManager.SENSOR_DELAY_GAME);
- } else {
- Toast.makeText(this, R.string.cannot_get_sensor, Toast.LENGTH_SHORT)
- .show();
- }
- mStopDrawing = false;
- mHandler.postDelayed(mCompassViewUpdater, 20);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mStopDrawing = true;
- if (mOrientationSensor != null) {
- mSensorManager.unregisterListener(mOrientationSensorEventListener);
- }
- if (mLocationProvider != null) {
- mLocationManager.removeUpdates(mLocationListener);
- }
- }
-
-
- private void initResources() {
- mDirection = 0.0f;
- mTargetDirection = 0.0f;
- mInterpolator = new AccelerateInterpolator();
- mStopDrawing = true;
- mChinease = TextUtils.equals(Locale.getDefault().getLanguage(), "zh");
-
- mCompassView = findViewById(R.id.view_compass);
- mPointer = (CompassView) findViewById(R.id.compass_pointer);
- mLocationTextView = (TextView) findViewById(R.id.textview_location);
- mDirectionLayout = (LinearLayout) findViewById(R.id.layout_direction);
- mAngleLayout = (LinearLayout) findViewById(R.id.layout_angle);
-
- mPointer.setImageResource(mChinease ? R.drawable.compass_cn
- : R.drawable.compass);
- }
-
-
- private void initServices() {
-
- mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
- mOrientationSensor = mSensorManager
- .getDefaultSensor(Sensor.TYPE_ORIENTATION);
-
-
- mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- Criteria criteria = new Criteria();
- criteria.setAccuracy(Criteria.ACCURACY_FINE);
- criteria.setAltitudeRequired(false);
- criteria.setBearingRequired(false);
- criteria.setCostAllowed(true);
- criteria.setPowerRequirement(Criteria.POWER_LOW);
- mLocationProvider = mLocationManager.getBestProvider(criteria, true);
-
- }
-
-
- private void updateDirection() {
- LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT);
-
- mDirectionLayout.removeAllViews();
- mAngleLayout.removeAllViews();
-
-
- 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 = 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 = new ImageView(this);
- west.setImageResource(mChinease ? R.drawable.w_cn : R.drawable.w);
- west.setLayoutParams(lp);
- }
-
- if (direction > 112.5f && direction < 247.5f) {
-
- 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 = 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 {
-
- 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);
- }
-
-
- private ImageView getNumberImage(int number) {
- ImageView image = new ImageView(this);
- LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT);
- switch (number) {
- case 0:
- image.setImageResource(R.drawable.number_0);
- break;
- case 1:
- image.setImageResource(R.drawable.number_1);
- break;
- case 2:
- image.setImageResource(R.drawable.number_2);
- break;
- case 3:
- image.setImageResource(R.drawable.number_3);
- break;
- case 4:
- image.setImageResource(R.drawable.number_4);
- break;
- case 5:
- image.setImageResource(R.drawable.number_5);
- break;
- case 6:
- image.setImageResource(R.drawable.number_6);
- break;
- case 7:
- image.setImageResource(R.drawable.number_7);
- break;
- case 8:
- image.setImageResource(R.drawable.number_8);
- break;
- case 9:
- image.setImageResource(R.drawable.number_9);
- break;
- }
- image.setLayoutParams(lp);
- return image;
- }
-
-
- private void updateLocation(Location location) {
- if (location == null) {
- mLocationTextView.setText(R.string.getting_location);
- } else {
- StringBuilder sb = new StringBuilder();
- double latitude = location.getLatitude();
- double longitude = location.getLongitude();
-
- if (latitude >= 0.0f) {
- sb.append(getString(R.string.location_north,
- getLocationString(latitude)));
- } else {
- sb.append(getString(R.string.location_south,
- getLocationString(-1.0 * latitude)));
- }
-
- sb.append(" ");
-
- if (longitude >= 0.0f) {
- sb.append(getString(R.string.location_east,
- getLocationString(longitude)));
- } else {
- sb.append(getString(R.string.location_west,
- getLocationString(-1.0 * longitude)));
- }
- mLocationTextView.setText(sb.toString());
- }
- }
-
-
- private String getLocationString(double input) {
- int du = (int) input;
- int fen = (((int) ((input - du) * 3600))) / 60;
- int miao = (((int) ((input - du) * 3600))) % 60;
- return String.valueOf(du) + "°" + String.valueOf(fen) + "′"
- + String.valueOf(miao) + "″";
- }
-
-
- private SensorEventListener mOrientationSensorEventListener = new SensorEventListener() {
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- float direction = event.values[0] * -1.0f;
- mTargetDirection = normalizeDegree(direction);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
- };
-
-
- private float normalizeDegree(float degree) {
- return (degree + 720) % 360;
- }
-
-
- LocationListener mLocationListener = new LocationListener() {
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- if (status != LocationProvider.OUT_OF_SERVICE) {
- updateLocation(mLocationManager
- .getLastKnownLocation(mLocationProvider));
- } else {
- mLocationTextView.setText(R.string.cannot_get_location);
- }
- }
-
- @Override
- public void onProviderEnabled(String provider) {
- }
-
- @Override
- public void onProviderDisabled(String provider) {
- }
-
- @Override
- public void onLocationChanged(Location location) {
- updateLocation(location);
- }
- };
- }
好了,核心代码就这些了,其实思路还是很简单,最后,感谢各位看到文章最后,祝愿各位程序猿们好好学习,天天向上!
Android之指南针(电子罗盘)学习
标签:
原文地址:http://www.cnblogs.com/welhzh/p/4190939.html