Android百度地圖之定位圖層

jopen 11年前發布 | 104K 次閱讀 Android Android開發 移動開發

使用百度地圖結合GPS進行定位一文中,我們已經介紹了利用GPS結合百度地圖進行定位,另外我們也可以使用百度SDK里面集成的方法,直接進行定位,這樣就不需要我們自己去寫GPS定位的方法了,代碼原型來自百度Demo,代碼如下:

Activity:

package com.home;

import android.app.Activity;
import android.content.Context;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.RadioGroup.OnCheckedChangeListener;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.LocationData;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationOverlay;
import com.baidu.mapapi.map.PopupClickListener;
import com.baidu.mapapi.map.PopupOverlay;
import com.baidu.platform.comapi.basestruct.GeoPoint;

/**
 * 此demo用來展示如何結合定位SDK實現定位,并使用MyLocationOverlay繪制定位位置 同時展示如何使用自定義圖標繪制并點擊時彈出泡泡
 * 
 */
public class LocationOverlayActivity extends Activity {

    // 定位相關
    LocationClient mLocClient;
    LocationData locData = null;
    public MyLocationListenner myListener = new MyLocationListenner();

    // 定位圖層
    locationOverlay myLocationOverlay = null;
    // 彈出泡泡圖層
    private PopupOverlay pop = null;// 彈出泡泡圖層,瀏覽節點時使用
    private TextView popupText = null;// 泡泡view
    private View viewCache = null;

    // 地圖相關,使用繼承MapView的MyLocationMapView目的是重寫touch事件實現泡泡處理
    // 如果不處理touch事件,則無需繼承,直接使用MapView即可
    MyLocationMapView mMapView = null; // 地圖View
    private MapController mMapController = null;

    // UI相關
    OnCheckedChangeListener radioButtonListener = null;
    Button requestLocButton = null;
    boolean isRequest = false;// 是否手動觸發請求定位
    boolean isFirstLoc = true;// 是否首次定位

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_locationoverlay);
        CharSequence titleLable = "定位功能";
        setTitle(titleLable);
        requestLocButton = (Button) findViewById(R.id.button1);
        OnClickListener btnClickListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                // 手動定位請求
                requestLocClick();
            }
        };
        requestLocButton.setOnClickListener(btnClickListener);

        RadioGroup group = (RadioGroup) this.findViewById(R.id.radioGroup);
        radioButtonListener = new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if (checkedId == R.id.defaulticon) {
                    // 傳入null則,恢復默認圖標
                    modifyLocationOverlayIcon(null);
                }
                if (checkedId == R.id.customicon) {
                    // 修改為自定義marker
                    modifyLocationOverlayIcon(getResources().getDrawable(
                            R.drawable.icon_geo));
                }
            }
        };
        group.setOnCheckedChangeListener(radioButtonListener);

        // 地圖初始化
        mMapView = (MyLocationMapView) findViewById(R.id.bmapView);
        mMapController = mMapView.getController();
        mMapView.getController().setZoom(14);
        mMapView.getController().enableClick(true);
        mMapView.setBuiltInZoomControls(true);
        // 創建 彈出泡泡圖層
        createPaopao();

        // 定位初始化
        mLocClient = new LocationClient(this);
        locData = new LocationData();
        mLocClient.registerLocationListener(myListener);
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);// 打開gps
        option.setCoorType("bd09ll"); // 設置坐標類型
        option.setScanSpan(5000);
        mLocClient.setLocOption(option);
        mLocClient.start();

        // 定位圖層初始化
        myLocationOverlay = new locationOverlay(mMapView);
        // 設置定位數據
        myLocationOverlay.setData(locData);
        // 添加定位圖層
        mMapView.getOverlays().add(myLocationOverlay);
        myLocationOverlay.enableCompass();
        // 修改定位數據后刷新圖層生效
        mMapView.refresh();

    }

    /**
     * 手動觸發一次定位請求
     */
    public void requestLocClick() {
        isRequest = true;
        mLocClient.requestLocation();
        Toast.makeText(LocationOverlayActivity.this, "正在定位……",
                Toast.LENGTH_SHORT).show();
    }

    /**
     * 修改位置圖標
     * 
     * @param marker
     */
    public void modifyLocationOverlayIcon(Drawable marker) {
        // 當傳入marker為null時,使用默認圖標繪制
        myLocationOverlay.setMarker(marker);
        // 修改圖層,需要刷新MapView生效
        mMapView.refresh();
    }

    /**
     * 創建彈出泡泡圖層
     */
    public void createPaopao() {
        viewCache = getLayoutInflater()
                .inflate(R.layout.custom_text_view, null);
        popupText = (TextView) viewCache.findViewById(R.id.textcache);
        // 泡泡點擊響應回調
        PopupClickListener popListener = new PopupClickListener() {
            @Override
            public void onClickedPopup(int index) {
                Log.v("click", "clickapoapo");
            }
        };
        pop = new PopupOverlay(mMapView, popListener);
        MyLocationMapView.pop = pop;
    }

    /**
     * 定位SDK監聽函數
     */
    public class MyLocationListenner implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            if (location == null)
                return;

            locData.latitude = location.getLatitude();
            locData.longitude = location.getLongitude();
            // 如果不顯示定位精度圈,將accuracy賦值為0即可
            locData.accuracy = location.getRadius();
            locData.direction = location.getDerect();
            // 更新定位數據
            myLocationOverlay.setData(locData);
            // 更新圖層數據執行刷新后生效
            mMapView.refresh();
            // 是手動觸發請求或首次定位時,移動到定位點
            if (isRequest || isFirstLoc) {
                // 移動地圖到定位點
                mMapController.animateTo(new GeoPoint(
                        (int) (locData.latitude * 1e6),
                        (int) (locData.longitude * 1e6)));
                isRequest = false;
            }
            // 首次定位完成
            isFirstLoc = false;
        }

        public void onReceivePoi(BDLocation poiLocation) {
            if (poiLocation == null) {
                return;
            }
        }
    }

    // 繼承MyLocationOverlay重寫dispatchTap實現點擊處理
    public class locationOverlay extends MyLocationOverlay {

        public locationOverlay(MapView mapView) {
            super(mapView);
        }

        @Override
        protected boolean dispatchTap() {
            // 處理點擊事件,彈出泡泡
            popupText.setBackgroundResource(R.drawable.popup);
            popupText.setText("我的位置");
            pop.showPopup(BMapUtil.getBitmapFromView(popupText), new GeoPoint(
                    (int) (locData.latitude * 1e6),
                    (int) (locData.longitude * 1e6)), 8);
            return true;
        }

    }

    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }

    @Override
    protected void onResume() {
        mMapView.onResume();
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        // 退出時銷毀定位
        if (mLocClient != null)
            mLocClient.stop();
        mMapView.destroy();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mMapView.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

}

/**
 * 繼承MapView重寫onTouchEvent實現泡泡處理操作
 * 
 * @author Administrator
 * 
 */
class MyLocationMapView extends MapView {
    static PopupOverlay pop = null;// 彈出泡泡圖層,點擊圖標使用

    public MyLocationMapView(Context context) {
        super(context);
    }

    public MyLocationMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyLocationMapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!super.onTouchEvent(event)) {
            // 消隱泡泡
            if (pop != null && event.getAction() == MotionEvent.ACTION_UP)
                pop.hidePop();
        }
        return true;
    }
}

地圖工具類:

package com.home;

import android.graphics.Bitmap;
import android.view.View;

public class BMapUtil {

    /**
     * 從view 得到圖片
     * 
     * @param view
     * @return
     */
    public static Bitmap getBitmapFromView(View view) {
        view.destroyDrawingCache();
        view.measure(View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
                .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.setDrawingCacheEnabled(true);
        Bitmap bitmap = view.getDrawingCache(true);
        return bitmap;
    }
}


配置文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.home"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />
    <!-- 使用網絡功能所需權限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
    </uses-permission>

    <!-- 讀取手機的當前狀態權限,沒有的話會報錯,這個是使用百度地圖API必須的 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>

    <!-- Cache功能需要讀寫外部存儲器 ,若沒這個權限,地圖加載不出來 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>
    <!-- 使用GPS需要的權限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!--
             添加屏幕支持
      android:anyDensity="true" 
            這個屬性指明應用程序是否包含了能夠適用于任何屏幕密度的資源。
            對于支持Android1.6(API Level 4)和更高版本的應用程序,這個屬性的默認值是true,
            并且除非絕對的確認這是應用程序正常工作所必須的,否則不應該把它設置為false。
            只是在應用程序直接操作位圖時才需要禁止這個屬性。

      android:largeScreens="true"
              這個屬性用于指示應用程序是否支持較大外形的屏幕。
              一個large類型的屏幕被定義成一個比normal類型的手持設備的屏幕明顯還要大的屏幕,
              并且為了讓應用程序能夠良好的使用,使用這個屬性時要特別小心,盡管可以依賴系統來調整尺寸,
              以便能夠填充屏幕。
              這個屬性的默認值實際上在某些版本之間是不同的,因此最好在任何時候都明確的聲明這個屬性。
              如果設置為false,系統會啟用屏幕兼容模式,這時要格外的小心。

      android:normalScreens="true"
              這個屬性用于指示應用程序是否支持普通外形的屏幕。
              典型的是HVGA中等密度的屏幕,但是WQVGA低密度和WVGA高密度屏幕也被認為是普通屏幕。
              這個屬性的默認值是true。

      android:smallScreens="true" 
              這個屬性用于指定應用程序是否支持較小外形的屏幕。
              一個small類型的屏幕被定義成一個比normal(傳統的HVGA)類型的屏幕還要小的屏幕。
              外部服務(如Google Play)不會把不支持小屏的應用程序提供給小屏設備,
              因為很少有能夠確保該應用程序在小屏幕的設備上正常工作的平臺。這個屬性的默認值是true。

      android:resizeable="true" 
              這個屬性用于指示針對不同的屏幕尺寸,應用程序是否可以調整尺寸。默認值是true。
    -->
    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true" />

    <application
        android:name="com.home.DemoApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.home.LocationOverlayActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
        </service>
    </application>

</manifest>

注意:該配置文件與之前的有個區別,多了一個service,它是百度jar包下的一個服務類,這是定位必須要的,不然就不能定位。

Application類同之前一樣。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.home.MyLocationMapView
        android:id="@+id/bmapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="80dip"
        android:background="#D000"
        android:minWidth="100dip"
        android:orientation="vertical"
        android:padding="2dp" >

        <RadioGroup
            android:id="@+id/radioGroup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="定位icon" >

            <RadioButton
                android:id="@+id/defaulticon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:checked="true"
                android:text="默認圖標" >
            </RadioButton>

            <RadioButton
                android:id="@+id/customicon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="自定義圖標" >
            </RadioButton>
        </RadioGroup>
    </LinearLayout>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="25dp"
        android:layout_marginTop="10dip"
        android:background="@drawable/custom_loc" />

</RelativeLayout>

custom_text_view.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/popleft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/popup_side"
        android:gravity="center"
        android:text="更新位置"
        android:textColor="#3814ed"
        android:textSize="12sp"
        android:textStyle="bold" />

    <LinearLayout
        android:id="@+id/popinfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textcache"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/popup_middle"
            android:gravity="center"
            android:textColor="@android:color/black"
            android:textSize="12sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/popdown"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/popup_down"
            android:textColor="@android:color/black"
            android:textSize="12sp" />
    </LinearLayout>

    <TextView
        android:id="@+id/popright"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/popup_side"
        android:gravity="center"
        android:text="更新marker"
        android:textColor="#3814ed"
        android:textSize="12sp"
        android:textStyle="bold" />

</LinearLayout>

附上圖片效果:

d8.png

來自:http://blog.csdn.net/u010142437/article/details/11577077

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!