• 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>
  • 相关阅读:
    理解inode
    贝叶斯公式与拼写检查器
    《C程序设计语言》第四章 函数和程序结构
    MIT《计算机科学与编程导论》课堂笔记
    很牛的牛顿迭代法
    开发一个小工具重温C#经典问题
    斯坦福《编程方法学》环境搭建及常见问题
    看Sybase官方手册学索引工作原理
    学习编程的方法、软件和工具
    大师里奇留给了我们什么
  • 原文地址:https://www.cnblogs.com/jerehedu/p/5139569.html
Copyright © 2020-2023  润新知