Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android 車載的小小指南針【源碼】

Android 車載的小小指南針【源碼】

編輯:Android開發實例

在Api Demo 裡面有一個指南針的例子,路徑為com.example.android.apis.graphics-》Compass.java。源碼使用的是SensorListener 做為動力感應為指南針傳遞角度。基於此原理不斷的去畫VIEW,目前能搜索出來的代碼大致也是根據此DEMO做出修改。代碼如下:

 

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.graphics;

import android.app.Activity;
import android.content.Context;
import android.graphics.*;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Config;
import android.util.Log;
import android.view.View;

public class Compass extends GraphicsActivity {

    private static final String TAG = "Compass";

    private SensorManager mSensorManager;
    private SampleView mView;
    private float[] mValues;
    
    private final SensorListener mListener = new SensorListener() {
    
        public void onSensorChanged(int sensor, float[] values) {
            if (Config.LOGD) Log.d(TAG, "sensorChanged (" + values[0] + ", " + values[1] + ", " + values[2] + ")");
            mValues = values;
            if (mView != null) {
                mView.invalidate();
            }
        }

        public void onAccuracyChanged(int sensor, int accuracy) {
            // TODO Auto-generated method stub
            
        }
    };

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mView = new SampleView(this);
        setContentView(mView);
    }

    @Override
    protected void onResume()
    {
        if (Config.LOGD) Log.d(TAG, "onResume");
        super.onResume();
        mSensorManager.registerListener(mListener, 
                SensorManager.SENSOR_ORIENTATION,
                SensorManager.SENSOR_DELAY_GAME);
    }
    
    @Override
    protected void onStop()
    {
        if (Config.LOGD) Log.d(TAG, "onStop");
        mSensorManager.unregisterListener(mListener);
        super.onStop();
    }

    private class SampleView extends View {
        private Paint   mPaint = new Paint();
        private Path    mPath = new Path();
        private boolean mAnimate;
        private long    mNextTime;

        public SampleView(Context context) {
            super(context);

            // Construct a wedge-shaped path
            mPath.moveTo(0, -50);
            mPath.lineTo(-20, 60);
            mPath.lineTo(0, 50);
            mPath.lineTo(20, 60);
            mPath.close();
        }
    
        @Override protected void onDraw(Canvas canvas) {
            Paint paint = mPaint;

            canvas.drawColor(Color.WHITE);
            
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.FILL);

            int w = canvas.getWidth();
            int h = canvas.getHeight();
            int cx = w / 2;
            int cy = h / 2;

            canvas.translate(cx, cy);
            if (mValues != null) {            
                canvas.rotate(-mValues[0]);
            }
            canvas.drawPath(mPath, mPaint);
        }
    
        @Override
        protected void onAttachedToWindow() {
            mAnimate = true;
            super.onAttachedToWindow();
        }
        
        @Override
        protected void onDetachedFromWindow() {
            mAnimate = false;
            super.onDetachedFromWindow();
        }
    }
}

 

 

運行結果:

 

根據Api Demo的例子,我們就可以方便的實現自己想要的指南針效果了。下面是根據Api Demo給出的實現思路自己完成的一個小小指南針,要實現的效果為如下所示:

首先,項目啟動時,設置屏幕為橫屏顯示:

在配置文件下對應的Activity 加入如下代碼:

android:screenOrientation="landscape"

接著畫View 將指南針的view 參照api Demo 畫出來,由於我個人喜歡View 保存相對的獨立性,所以都是將View 盡量的標准化,即可以以編程方式引用也可以在Layout 文件中使用XML引用。下面是我指南針View 代碼:

 

package com.yaomei.view;

import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.BitmapFactory.Options;
import android.util.AttributeSet;
import android.view.View;

import com.yaomei.compass.R;

public class CompassView extends View {

    private Bitmap[] mBitmapArray = new Bitmap[4];
    InputStream is;
    private float[] mValues;
    int[] mBitmapWidth = new int[4];
    int[] mBitmapHeight = new int[4];

    public CompassView(Context context) {
        this(context, null);
        // TODO Auto-generated constructor stub
    }

    public CompassView(Context context, AttributeSet attrs) {
        super(context, attrs);

        BitmapFactory.Options opts = new Options();
        opts.inJustDecodeBounds = false;
        setBitMapArray(context, 0, opts, R.drawable.panel);
        setBitMapArray(context, 1, opts, R.drawable.compass_digree);

    }

    /**
     * 設置bitmap數組個下標的值
     * 
     * @param index
     * @param opts
     * @param resid
     */
    private void setBitMapArray(Context context, int index,
            BitmapFactory.Options opts, int resid) {
        is = context.getResources().openRawResource(resid);
        mBitmapArray[index] = BitmapFactory.decodeStream(is);
        mBitmapWidth[index] = mBitmapArray[index].getWidth();
        mBitmapHeight[index] = mBitmapArray[index].getHeight();
        mBitmapArray[index + 2] = BitmapFactory.decodeStream(is, null, opts);
        mBitmapHeight[index + 2] = mBitmapArray[index + 2].getHeight();
        mBitmapWidth[index + 2] = mBitmapArray[index + 2].getWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        int w = canvas.getWidth();
        int h = canvas.getHeight();

        int cx = w / 2;
        int cy = h / 2;

        canvas.translate(cx, cy);
        drawPictures(canvas, 0);

    }

    private void drawPictures(Canvas canvas, int idDelta) {
        if (mValues != null) {
            // Log.d(TAG, "mValues[0] = "+ mValues[0]);
            canvas.rotate(-mValues[0]);
            canvas.drawBitmap(mBitmapArray[0 + idDelta],
                    -mBitmapWidth[0 + idDelta] / 2,
                    -mBitmapHeight[0 + idDelta] / 2, null);
            canvas.rotate(360 + mValues[0]);
            canvas.drawBitmap(mBitmapArray[1 + idDelta],
                    -mBitmapWidth[1 + idDelta] / 2,
                    -mBitmapHeight[1 + idDelta] / 2, null);

        } else {
            canvas.drawBitmap(mBitmapArray[0 + idDelta],
                    -mBitmapWidth[0 + idDelta] / 2,
                    -mBitmapHeight[0 + idDelta] / 2, null);

            canvas.drawBitmap(mBitmapArray[1 + idDelta],
                    -mBitmapWidth[1 + idDelta] / 2,
                    -mBitmapHeight[1 + idDelta] / 2, null);
        }
    }
  //角度值
    public void setValue(float[] value) {
        this.mValues = value;
    }
 

}

 

通過上面的繪制VIEW就可以在布局中使用:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:gravity="center">
    <TextView android:id="@+id/title" android:textColor="@drawable/white"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="wrap_content" android:layout_height="wrap_content">
    </TextView>

    <com.yaomei.view.CompassView android:id="@+id/compass"
        android:layout_width="wrap_content" android:layout_height="wrap_content">
    </com.yaomei.view.CompassView>

</LinearLayout>

 

 

對應Activity使用SensorListener為view 傳遞角度,當然如果是在車載上面可能不是用SensorListener而是使用GPS等另外其他傳過來的參數,這個是後話。

 

package com.yaomei.compass;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.TextView;

import com.yaomei.view.CompassView;

@SuppressWarnings("deprecation")
public class CompassActivity extends Activity {

    private SensorManager mSensorManager;
    private CompassView mView;
    private String text = "";
    private Resources mRes;

    private TextView tv;
    public final SensorListener mListtenr = new SensorListener() {

        @Override
        public void onSensorChanged(int sensor, float[] values) {
            // TODO Auto-generated method stub
            synchronized (this) {
                mView.setValue(values);
                if (Math.abs(values[0] - 0.0f) < 1)
                    return;
                switch ((int) values[0]) {
                case 0:
                    text = mRes.getText(R.string.North).toString();
                    break;
                case 90:
                    text = mRes.getText(R.string.West).toString();
                    break;
                case 180:
                    text = mRes.getText(R.string.South).toString();
                    break;

                case 270:
                    text = mRes.getText(R.string.East).toString();
                    break;

                default:
                    int v = (int) values[0];
                    if (v > 0 && v < 90) {
                        text = mRes.getText(R.string.North_west).toString()
                                + " " + v + " 度";
                    }
                    if (v > 90 && v < 180) {
                        text = mRes.getText(R.string.South_west).toString()
                                + " " + (180 - v) + " 度";
                    }
                    if (v > 180 && v < 270) {

                        text = mRes.getText(R.string.South_east).toString()
                                + " " + (v - 180) + " 度";
                    }
                    if (v > 270 && v < 360) {

                        text = mRes.getText(R.string.North_east).toString()
                                + " " + (360 - v) + " 度";
                    }
                    break;
                }
                tv.setText(text);

                if (mView != null) {
                    mView.invalidate();
                }
            }
        }

        @Override
        public void onAccuracyChanged(int sensor, int accuracy) {
            // TODO Auto-generated method stub

        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mRes = this.getResources();
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.main);
        findView();

    }

    void findView() {
        tv = (TextView) findViewById(R.id.title);
        mView = (CompassView) findViewById(R.id.compass);
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();

        mSensorManager.registerListener(mListtenr,
                SensorManager.SENSOR_ORIENTATION,
                SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        mSensorManager.unregisterListener(mListtenr);
        super.onStop();
    }

}

 

apk下載:

CarCompass.7z  改成apk,可能不能打開加密了。

轉自:http://www.cnblogs.com/TerryBlog/archive/2010/11/12/1875657.html

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved