`
phenom
  • 浏览: 408913 次
  • 性别: 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  
有源码?


相关推荐

    android地图使用overlay添加标记

    `Overlay`是Android SDK中用于在地图上绘制图形或文本的对象,它允许我们在地图上添加自定义的图标或标注。 首先,我们需要在项目中引入Google Maps API。在`build.gradle`文件中添加依赖: ```groovy ...

    百度地图android sdk拖拽overlay item

    百度地图Android SDK提供了丰富的功能,其中包括在地图上添加自定义覆盖物(Overlay Item)。本文将深入探讨如何实现拖拽这些覆盖物,增强用户交互体验。 【描述】: 这篇博客文章...

    高德地图Overlay的应用以及照相功能的实现

    关于地图与Activity之间的跳转,Android使用`Intent`对象来在不同的Activity之间传递数据和控制流程。在这个项目中,开发者可能在MapActivity中设置了一个按钮或手势,当用户触发时,会启动照相功能的Activity。完成...

    DICOM图像,overlay层,包含只有一层overlay,两侧overlay,overlay加原始图像三种DICOM图像

    DICOM图像,overlay层,包含只有一层overlay,两侧overlay,overlay加原始图像三种DICOM图像。 不少DICOM开源框架对这种图像支持不够,显示有问题。便于测试系统对带有overlay图像的显示是否正确

    Android 高德地图自定义点聚合marker图片及Overlay点击选中功能

    在Android开发中,高德...在实际应用中,可能还需要考虑性能优化,比如在数据量大时使用异步处理,以及如何优雅地处理用户交互和视觉反馈。在不断实践中,开发者可以对这些功能进行扩展和优化,提供更出色的用户体验。

    Overlay附加数据处理

    Overlay附加数据处理,版权属于原作者,如有侵权请联系我网站及时删除

    Merge Overlay v1.2 汉化版(数据叠加)

    综上所述,《Merge Overlay v1.2 汉化版(数据叠加)》是一款强大的数据处理工具,其汉化版的推出无疑极大地便利了中文用户,使得他们在数据分析和决策过程中能更高效、准确地利用数据叠加这一重要技术。无论是在商业...

    关于fpga overlay的解释

    FPGA overlay是一种基于现场可编程门阵列(FPGA)的技术,它允许在一个FPGA上实现一个或多个不同的可配置硬件层,从而在用户逻辑中模拟出一种类似FPGA的行为。这种技术的出现,使得FPGA可以被重新编程以适应不同的...

    新版本的百度地图 定位 overlay 坐标 DEMO

    在Java代码中,我们可以创建自定义的`Overlay`子类,重写`draw()`方法来绘制覆盖物,然后使用`OverlayManager`将其添加到地图上。覆盖物可以是简单的标记,也可以是复杂的图形或者动画效果。 5. **DEMO运行**: 这...

    docker清理大杀器/docker的overlay、overlay2文件占用磁盘太大的解决办法

    本文讲述了如何解决 Docker 中的 overlay 和 overlay2 文件占用磁盘太大的问题,并提供了相应的解决方案。同时,文章也附带了 Docker 配置 overlay 存储驱动的前提条件和步骤。 一、 Docker 中的 overlay 和 ...

    overlayicon的代码

    在Windows Shell编程中,`overlay icon`是一种特殊的技术,它允许在文件或文件夹图标上显示一个小图标,通常用于指示状态或属性,如文件的版本控制状态、加密状态或者是否被修改过。`overlayicon`的代码主要是用来...

    主机overlay和网络overlay介绍 .pptx

    ### 主机Overlay与网络Overlay详解 #### 一、概述 随着云计算和软件定义网络(SDN)技术的发展,网络架构经历了重大变革。其中,“主机Overlay”和“网络Overlay”是两种重要的网络部署方式,它们能够更好地支持虚拟...

    overlay demo

    3. **Overlay File System**:在存储领域,overlay文件系统也是类似的概念,它将多个文件系统叠加在一起,形成一个逻辑上的单一视图。例如,Linux中的overlayfs就是这样的一个例子,它可以将两个或更多的文件系统...

    cas-overlay(MD5 数据用户校验).zip

    Overlay的概念在于,它允许开发者在一个基础项目之上添加或修改特定的配置,而不是直接修改原始源码。这样做的好处是更容易升级到新版本,因为改动只存在于项目的overlay部分。 在描述中提到的"服务端数据库配置"是...

    echarts+bmap结合可以在百度地图上展现 点图,线图,热力图 等可视化。

    当ECharts与百度地图(BMap)结合时,我们可以实现地图上的数据可视化,包括点图、线图和热力图,从而为数据分析和展示带来新的维度。 首先,让我们深入了解一下ECharts。ECharts是百度开发的一个基于SVG+Canvas的...

    基于SDN和Overlay的云计算数据中心网络.pdf

    基于SDN和Overlay的云计算数据中心网络.pdf

    SPM多重overlay方法

    多重overlay方法则是指在同一个脑模板上叠加多个SPM分析结果的技术,这对于理解不同实验条件下大脑活动的变化具有重要意义。 #### 二、SPM多重overlay方法的关键步骤 根据提供的部分内容,我们可以了解到使用SPM ...

Global site tag (gtag.js) - Google Analytics