`
phenom
  • 浏览: 406166 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

关于地图上使用的Overlay(类似遇见),加异步数据

 
阅读更多
遇见中使用百度地图可以在地图上显示头像功能,然后点击头像又会弹出气泡。
现在就来说一说这种效果的一种实现方式。 虽然我不知道他们如何处理的,但经过试验,效果差不多了。
使用的也是百度地图。
下载BaiduMapApi_Sample_Android_1.3.3.zip,目前官方最新版本。
直接使用里面的示例程序,ItemizedOverlayDemo就有气泡的效果,但里面的pop.png不是一个nine9patch文件,不能缩放。需要修改。
附件里面传一个可以缩放的图片。ps功底不好,图不是很好看。

新建一个Activity:TItemizedOverlay extends MapActivity,可以直接把示例中的复制过来。
修改里面的oncreate:overitem=new OverItemT(marker, this, 3);
        //mMapView.getOverlays().add(overitem); //添加ItemizedOverlay实例到mMapView
不需要的是OverItemT。这是作为地图上的遮罩。

另外加入
Drawable markerDrawable=drawBitmap("test1");
        mMapView.getOverlays().add(new MyOverItem(markerDrawable,TItemizedOverlay.this,new GeoPoint((int) (39.90923*1e6), (int) (116.397428*1e6))));
        markerDrawable=drawBitmap("test2");
        mMapView.getOverlays().add(new MyOverItem(markerDrawable,TItemizedOverlay.this,new GeoPoint((int) (39.90923*1e6), (int) (116.357428*1e6))));
        markerDrawable=drawBitmap("test3");
        mMapView.getOverlays().add(new MyOverItem(markerDrawable,TItemizedOverlay.this,new GeoPoint((int) (39.90923*1e6), (int) (116.437428*1e6))));
三个点覆盖层。
因为ItemizedOverlay的构造方法中,只能用Drawable,所以我们要做的是,生成一个Drawable,然后传入。现在先处理同步的,就是数据已经存在的了。后面再说异步下载图片,如何将新下载的图片做成Drawable,然后再放到地图上。
Drawable drawBitmap(String title){
        Bitmap bmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.marker_view, null);
        TextView titleView=(TextView) layout.findViewById(R.id.title);
        titleView.setText(title);
        layout.setDrawingCacheEnabled(true);
        layout.measure(View.MeasureSpec.makeMeasureSpec(canvas.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(canvas.getHeight(), View.MeasureSpec.EXACTLY));
        layout.layout(0, 0, layout.getMeasuredWidth(), layout.getMeasuredHeight());
        Paint paint = new Paint();
        canvas.drawBitmap(layout.getDrawingCache(), 0, 0, paint);

        Drawable drawable = new BitmapDrawable(bmp);
        return drawable;
    }

这里通过布局文件引入,将需要的画成一个图。只是简单的处理画出来和图片大小是100*100的,动态的决定布局占用的大小更复杂一些。
因为遇见的效果就是一张图片。所以使用布局方面就可以简单的放一张图片,然后下面再有一张背景就可以了。 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:background="@drawable/pop_bg">

    <TextView android:id="@+id/title" android:maxWidth="120dp"
        android:text="testaa" android:textSize="20sp"
        android:textColor="@android:color/black" android:padding="4dp"
        android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</LinearLayout>  
这里使用的文字,如果文字太多,而没有处理实际需要的大小就不好看了。

然后一个Overlay
class MyOverItem extends ItemizedOverlay<OverlayItem> {

        private Drawable marker;
        private Context mContext;
        GeoPoint mPoint;
        OverlayItem mItem;

        public MyOverItem(Drawable marker, Context context, GeoPoint point) {
            //super(boundCenterBottom(marker));
super((marker));这里不要对齐,因为对齐后弹出的气泡会发生覆盖

            this.marker=marker;
            this.mContext=context;
            mPoint=point;
            mItem=new OverlayItem(point, "", "");

            populate();  //createItem(int)方法构造item。一旦有了数据,在调用其它方法前,首先调用这个方法
        }

        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {
            
            super.draw(canvas, mapView, shadow);
            //调整一个drawable边界,使得(0,0)是这个drawable底部最后一行中心的一个像素
            //boundCenterBottom(marker);同样不能对齐
        }

        @Override
        protected OverlayItem createItem(int i) {
            return mItem;
        }

        @Override
        public int size() {
            return 1;
        }

        // 处理当点击事件
        @Override
        protected boolean onTap(int i) {//点击后就会弹出另一个气泡了。
            setFocus(mItem);
            // 更新气泡位置,并使之显示
            TextView title=(TextView) mPopView.findViewById(R.id.title);
            title.setText("lat:"+mPoint.getLatitudeE6()+" long:"+mPoint.getLongitudeE6());
            mMapView.updateViewLayout(mPopView,
                new MapView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
                    mPoint, MapView.LayoutParams.BOTTOM_CENTER));
            mPopView.setVisibility(View.VISIBLE);
            /*Toast.makeText(this.mContext, mItem.getSnippet(), Toast.LENGTH_SHORT).show();*/
            return true;
        }

        @Override
        public boolean onTap(GeoPoint arg0, MapView arg1) {
            // 消去弹出的气泡
            mPopView.setVisibility(View.GONE);
            return super.onTap(arg0, arg1);
        }
    }

mPopView=super.getLayoutInflater().inflate(R.layout.popview, null);布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:padding="2.0dip"
    android:background="@drawable/map_mark_bg" android:gravity="center_horizontal"
    android:layout_width="54dp" android:layout_height="81dp">
这个高与宽需要指定,具体值与背景图片有关。就要是背景图片下面的三角形要显示出来。
    <ImageView android:id="@+id/top_icon"
        android:src="@drawable/ic_launcher"
        android:layout_width="50dp" android:layout_height="50dp"/>
</LinearLayout>

最后的效果图就是:
[img]http://dl.iteye.com/upload/attachment/0071/5306/483e5585-88b2-354c-8780-56bedac54101.png[/img]
修改后的效果图:
[img]http://dl.iteye.com/upload/attachment/0071/5573/ee5fc596-1850-326b-96b2-3df67fb9a78f.png[/img]

除 了上面的之外,其实在地图上加一些点,不直接使用它的Overlay也是可以的,对每个点加一个点击事件,每个点放的位置坐标需要知道。由于放的是drawable不是layout,所以自定义方面复杂一点。

对于异步的处理;提供示例代码:
源码不是个人的,不能给的,认包涵。
提供思路:
oncreate()里面添加一个setMarker();方法
这个方法主要是执行数据的获取:
private void setMarker() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                AssetManager assetManager=getAssets();
                try {
                    InputStream inputStream=assetManager.open("store.json");
                    String js=HttpUtils.parseInputStream(inputStream);
                    ArrayList<StoreBean> storeBeans=JsonParser.parseStoreBeans(js);
                    updateOverlay(storeBeans);
在这里可以获取网络资源,也可以获取固定的资源,我不下载了,直接获取assets里面的
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (T8Exception e) {
                    e.printStackTrace();
                } finally {
                    //assetManager.close();
                }
            }

        }).start();
    }

private void updateOverlay(ArrayList<StoreBean> storeBeans) {
        if(null==storeBeans||storeBeans.size()<1){
            Log.d("","没有取得商店数据。");
            return;
        }

        StoreBean first=storeBeans.get(0);
        Message message=Message.obtain();
        message.what=FIRST;//这里定义一个位置的中心,如果你在进入地图时已经有了中心点这就不需要了。
        message.obj=first;
        mHandler.sendMessage(message);

        MyOverItem item;
        ArrayList<MyOverItem> overItems=new ArrayList<MyOverItem>();
        for (StoreBean bean : storeBeans) {
            item=new MyOverItem(mMarkerDrawable, StoreMap.this, new GeoPoint((int) (bean.lat), (int) (bean.llong)), bean);
            myOverItemHashMap.put(bean.url, item);
            overItems.add(item);
        }

        if (overItems.size()>0) {
            message=Message.obtain();
            message.obj=overItems;
            message.what=ALL;
            mHandler.sendMessage(message);

            Log.d("", "现在处理图片下载。");下面是模拟的,
            try {
                Thread.sleep(4000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            downloadAndUpdateOverlay(storeBeans);
        }
    }

主要的过程是:先获取地图上的点,如果没有坐标点,就没有标记了。这个数据来源可以在进入地图后获取,也可以在进入前intent带进来的。
2.获取地图的点后立即更新地图,并画上默认的图片。
3.异步线程获取地图点对应的图片或其它数据。
4.更新异步线程获取的地图点对应的数据,就可以展现出气泡了。

这里采用了单线程来处理多个图片资源的下载,如果网络慢的话,可能图片的展示也慢,可以使用线程池来处理。
private void downloadAndUpdateOverlay(ArrayList<StoreBean> storeBeans) {
        for (StoreBean bean : storeBeans) {
            try {
                if (!loadImg) {
                    break;
                }
                Log.d("", "bean:"+bean);
                String url=bean.url;

                Bitmap img=App.getmImageLoader(StoreMap.this).getLargeBitmap(url, App.mCacheDir);

                Drawable markerDrawable;
                MyOverItem myOverItem;
                Message message;
                if (null!=img) {
                    markerDrawable=drawBitmapLayout(img);
                    myOverItem=new MyOverItem(markerDrawable, StoreMap.this, new GeoPoint((int) (bean.lat), (int) (bean.llong)), bean);
                    message=Message.obtain();
                    message.what=OTHER;//表示非定位的点,如果在进入地图已经获取了中心点,这里就直接处理为普通的坐标点就可以了。
                    message.obj=myOverItem;
                    mHandler.sendMessage(message);
                }

                myOverItemHashMap.remove(bean.url);移除已经下载的坐标点。
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Handler mHandler=new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int what=msg.what;
            switch (what) {
                case FIRST:
                    try {
                        StoreBean bean=(StoreBean) msg.obj;
                        mMapView.getController().setCenter(new GeoPoint((int) bean.lat, (int) bean.llong));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case OTHER: {
                    MyOverItem myOverItem=(MyOverItem) msg.obj;
                    mMapView.getOverlays().add(myOverItem);
                    mMapView.postInvalidate();
                    break;
                }

                case ALL:
                    ArrayList<MyOverItem> myOverItems=(ArrayList<MyOverItem>) msg.obj;
                    mMapView.getOverlays().addAll(myOverItems);
                    mMapView.postInvalidate();
                    break;

                case UPDATE: {
                    MyOverItem myOverItem=(MyOverItem) msg.obj;
                    List<Overlay> overlays=mMapView.getOverlays();
                    MyOverItem item;
                    Overlay overlay;
                    for (int i=0; i<overlays.size(); i++) {
                        overlay=overlays.get(i);
                        if (overlay instanceof MyOverItem) {
                            item=(MyOverItem) overlay;
                            if (item.mBean.id==myOverItem.mBean.id) {
                                Log.d("", "更新的覆盖物是:"+myOverItem);
                                overlays.remove(i);
                                mMapView.getOverlays().add(myOverItem);
                                mMapView.postInvalidate();
                                break;
                            }
                        }
                    }
                    break;
                }
            }
        }
    };



  • 大小: 620 Bytes
  • 大小: 163.7 KB
  • 大小: 146.7 KB
分享到:
评论
2 楼 imesong 2013-03-07  
贴个图看看啊!
1 楼 jiahui524 2012-11-08  
有源码?


相关推荐

Global site tag (gtag.js) - Google Analytics