Android定位&地圖&導航——基於百度地圖,實現自定義圖標繪制並點擊時彈出泡泡


一、問題描述

  上一次我們使用百度地圖實現基本的定位功能,接下來我們繼續實現搜索和定位,並使用LocationOverlay繪制定位位置,同時展示如何使用自定義圖標繪制並點擊時彈出泡泡

  如圖所示:

 

二、編寫MyApplication類
 public class MyApplication extends Application {
    private static MyApplication mInstance = null;
    public boolean m_bKeyRight = true;
    public BMapManager mBMapManager = null;
    public static final String strKey = "申請的應用key";
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        initEngineManager(this);
    }
    public void initEngineManager(Context context) {
        if (mBMapManager == null) {
            mBMapManager = new BMapManager(context);
        }
        if (!mBMapManager.init(strKey,new MyGeneralListener())) {
     Toast.makeText(MyApplication.getInstance().getApplicationContext(), "BMapManager  初始化錯誤!", Toast.LENGTH_LONG).show();
        }
}
    
    public static MyApplication getInstance() {
        return mInstance;
    }
    // 常用事件監聽,用來處理通常的網絡錯誤,授權驗證錯誤等
    public static class MyGeneralListener implements MKGeneralListener {
        @Override
        public void onGetNetworkState(int iError) {
            if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
     Toast.makeText(MyApplication.getInstance().getApplicationContext(), "您的網絡出錯啦!",Toast.LENGTH_LONG).show();
            }else if (iError == MKEvent.ERROR_NETWORK_DATA) {
             Toast.makeText(MyApplication.getInstance().getApplicationContext(), "輸入正確的檢索條件!",Toast.LENGTH_LONG).show();
            }
        }
        @Override
        public void onGetPermissionState(int iError) {
            //非零值表示key驗證未通過
            if (iError != 0) {
                //授權Key錯誤:
    Toast.makeText(MyApplication.getInstance().getApplicationContext(), 
                        "請在 DemoApplication.java文件輸入正確的授權Key,並檢查您的網絡連接是否正常!error: "+iError, Toast.LENGTH_LONG).show();
                MyApplication.getInstance().m_bKeyRight = true;
            }
            else{
                MyApplication.getInstance().m_bKeyRight = true;
    //Toast.makeText(DemoApplication.getInstance().getApplicationContext(), "key認證成功", Toast.LENGTH_LONG).show();
            }
        }
    }
}
三、編寫MyLocationMapView,繼承MapView重寫onTouchEvent實現泡泡處理操作
public class MyLocationMapView extends MapView {
    public 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;
    }
}
三、編寫主程序MainActivity

  編寫主程序MainActivity,用來展示如何結合定位SDK實現定位,並使用MyLocation Overlay繪制定位位置 同時展示如何使用自定義圖標繪制並點擊時彈出泡泡。

public class MainActivity extends Activity {
    private  EditText txtAddr;
    // 定位相關
    LocationClient mLocClient;
    LocationData locData = null;
    public MyLocationListenner myListener = new MyLocationListenner();
    public MyApplication app;
    //定位圖層
    locationOverlay myLocationOverlay = null;
    //彈出泡泡圖層
    private PopupOverlay   pop  = null;//彈出泡泡圖層,瀏覽節點時使用
    private TextView  popupText = null;//泡泡view
    private View viewCache = null;
//地圖相關,使用繼承MapView的MyLocationMapView目的是重寫touch事件實現泡泡處理
    //如果不處理touch事件,則無需繼承,直接使用MapView即可
    public MyLocationMapView mMapView = null;    // 地圖View
    private MapController mMapController = null;
    private MKSearch mMKSearch = null;//用於信息檢索服務 
    //UI相關
    OnCheckedChangeListener radioButtonListener = null;
    TextView requestLocButton ,btSerach;
    boolean isRequest = false;//是否手動觸發請求定位
    boolean isFirstLoc = true;//是否首次定位
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**
         * 使用地圖sdk前需先初始化BMapManager.
         * BMapManager是全局的,可為多個MapView共用,它需要地圖模塊創建前創建,
         * 並在地圖地圖模塊銷毀后銷毀,只要還有地圖模塊在使用,BMapManager就不應該銷毀
         */
        app = (MyApplication)this.getApplication();
        if (app.mBMapManager == null) {
            app.mBMapManager = new BMapManager(getApplicationContext());
            /**
             * 如果BMapManager沒有初始化則初始化BMapManager
             */
            app.mBMapManager.init(MyApplication.strKey,new MyApplication.MyGeneralListener());
        }
        setContentView(R.layout.activity_main);
        
           txtAddr=(EditText)findViewById(R.id.txtAddr);//關鍵字輸入框
           
      //監聽搜索單擊事件
           btSerach= (TextView)findViewById(R.id.btOk);
        btSerach.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mMKSearch.poiSearchInCity("", txtAddr.getText().toString());                      
            }
        });
        //定位按鈕
        requestLocButton = (TextView)findViewById(R.id.btget);
        requestLocButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                requestLocClick();
            }
        });
        
        //地圖初始化
        mMapView = (MyLocationMapView)findViewById(R.id.bmapView);
        mMapView.setTraffic(true);//設置地圖模式為交通視圖(也可為衛星視圖) 
        mMapController = mMapView.getController();
        mMapView.getController().setZoom(15);
        mMapView.getController().enableClick(true);
        mMapView.setBuiltInZoomControls(true);
      //信息檢索初始化
        mMKSearch = new MKSearch(); 
        mMKSearch.init(app.mBMapManager, new MKSearchListener() {
            @Override
            public void onGetAddrResult(MKAddrInfo arg0, int arg1) {
            }
            @Override
            public void onGetBusDetailResult(MKBusLineResult arg0, int arg1) {
            }
            @Override
            public void onGetDrivingRouteResult(MKDrivingRouteResult arg0,
                    int arg1) {
            }
            @Override
            public void onGetPoiDetailSearchResult(int arg0, int arg1) {
            }
            @Override
            public void onGetPoiResult(MKPoiResult res, int type, int error) {
                if (error == MKEvent.ERROR_RESULT_NOT_FOUND) {
                    Toast.makeText(MainActivity.this, "抱歉,未找到結果",
                            Toast.LENGTH_LONG).show();
                    return;
                } else if (error != 0 || res == null) {
                    Toast.makeText(MainActivity.this, "搜索出錯啦.."+error,
                            Toast.LENGTH_LONG).show();
                    return;
                }
                PoiOverlay poiOverlay = new PoiOverlay(MainActivity.this,
                        mMapView);
                poiOverlay.setData(res.getAllPoi());
                mMapView.getOverlays().clear();
                mMapView.getOverlays().add(poiOverlay);
                mMapView.refresh();
                for (MKPoiInfo info : res.getAllPoi()) {
                    if (info.pt != null) {
                        mMapView.getController().animateTo(info.pt);
                        break;
                    }
                }
            }

            @Override
            public void onGetShareUrlResult(MKShareUrlResult arg0, int arg1,
                    int arg2) {
            }
            @Override
            public void onGetSuggestionResult(MKSuggestionResult arg0, int arg1){
            }
            @Override
            public void onGetTransitRouteResult(MKTransitRouteResult arg0,
                    int arg1) {
            }
            @Override
            public void onGetWalkingRouteResult(MKWalkingRouteResult arg0,
                    int arg1) {
            }
        });
        createPaopao();
        //定位初始化
        mLocClient = new LocationClient( this );
        locData = new LocationData();
        mLocClient.registerLocationListener( myListener );
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);//打開gps
        option.setAddrType("all");//返回的定位結果包含地址信息
        option.disableCache(false);//禁止啟用緩存定位
        option.setCoorType("bd09ll");     //設置坐標類型
        option.setScanSpan(1000);
        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(MainActivity.this, "正在定位……", Toast.LENGTH_SHORT).show();
    }
    /**
     * 創建彈出泡泡圖層
     */
    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) {
            }
        };
        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的方向信息, 如果定位 SDK 未返回方向信息,用戶可以自己實現羅盤功能添加方向信息。
            locData.direction = location.getDerect();
            //更新定位數據
            myLocationOverlay.setData(locData);
            //更新圖層數據執行刷新后生效
            mMapView.refresh();
            //是手動觸發請求或首次定位時,移動到定位點
            if (isRequest || isFirstLoc){
                //移動地圖到定位點
                //Log.d("LocationOverlay", "receive location, animate to it");
                mMapController.animateTo(new GeoPoint((int)(locData.latitude* 1e6), (int)(locData.longitude *  1e6)));
                isRequest = false;
                myLocationOverlay.setLocationMode(LocationMode.FOLLOWING);
            }
            //首次定位完成
            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(mLocClient.getLastKnownLocation().getAddrStr());
            pop.showPopup(BMapUtil.getBitmapFromView(popupText),new GeoPoint((int)(locData.latitude*1e6), (int)(locData.longitude*1e6)),8);
            return true;
          }
          
      }
    @Override
    protected void onPause() {
        mMapView.onPause();
        if(app.mBMapManager!=null){  
            app.mBMapManager.stop();  
     } 
        super.onPause();
    }
    
    @Override
    protected void onResume() {
        mMapView.onResume();
        if(app.mBMapManager!=null){  
            app.mBMapManager.start();  
    }
        super.onResume();
    }
    @Override
    protected void onDestroy() {
        //退出時銷毀定位
        if (mLocClient != null)
            mLocClient.stop();
        mMapView.destroy();
        if(app.mBMapManager!=null){  
            app.mBMapManager.destroy();  
            app.mBMapManager=null;  
    }  
        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;
    }

}

MainActivity的布局文件如下:

<?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" >
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <com.jerehedu.ljb.MyLocationMapView
            android:id="@+id/bmapView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:clickable="true" />
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/edit_bg_all" >
            <EditText
                android:id="@+id/txtAddr"
                android:layout_width="fill_parent"
                android:layout_height="40dp"
                android:layout_centerVertical="true"
                android:layout_marginRight="2dp"
                android:layout_toLeftOf="@+id/btOk"
                android:background="@drawable/edit_bg_all"
                android:completionThreshold="2"
                android:drawableLeft="@drawable/qz_icon_seabar_search"
                android:hint="請輸入搜索關鍵字" />
            <TextView
                android:id="@+id/btOk"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginRight="2dp"
                android:layout_toLeftOf="@+id/s2"
                android:text="搜索"
                android:textSize="18sp" />
            <ImageView
                android:id="@+id/s2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginRight="2dp"
                android:layout_toLeftOf="@+id/btget"
                android:src="@drawable/slide_center" />
            <TextView
                android:id="@+id/btget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:text="定位"
                android:textSize="18sp" />
        </RelativeLayout>
    </FrameLayout>
</RelativeLayout>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM