百度地图4.1_1开发教程(3)Marker

本章将讲述如何利用Marker在地图生成点,并实现点击Marker弹出该点对应的信息。
1.点击点获取坐标
2.在我的项目里,会将地图上的一些飞机作为Marker,点击并弹出该飞机对应的详情
3.点击地图其他区域,将清除所有飞机类的marker
4.地图的触摸,单击等监听
最终效果图如下:(实际项目中,请注意美观)

最终效果图

获取坐标

首先,在布局加上显示坐标的控件,这里用一个textView来显示
<TextView
        android:id="@+id/activity_main_tv_detail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"
        android:hint="点击显示当前地理详情"/>
接下来在类里调用API:
//地图触摸事件
        mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener()
        {

            @Override
            public void onTouch(MotionEvent motionEvent)
            {

            }
        });
        // 地图单击事件
        mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener()
        {

            @Override
            public void onMapClick(LatLng latLng)
            {
                currentPt = latLng;
                updateMapState();
            }

            @Override
            public boolean onMapPoiClick(MapPoi mapPoi)
            {
                if (tv_detail.getText() == null || "".equals(tv_detail.getText()))
                {

                }
                currentPt = mapPoi.getPosition();
                updateMapState();
                return false;
            }
        });
    /**
     * 更新地图状态显示面板
     */
    private void updateMapState()
    {
        if (tv_detail == null)
        {
            return;
        }
        String state = "";
        if (currentPt == null)
        {
            state = "点击、长按、双击地图以获取经纬度和地图状态";
        } else
        {
            state = String.format("当前经度: %f 当前纬度:%f",
                    currentPt.longitude, currentPt.latitude);
        }
        state += "\n";
        MapStatus ms = mBaiduMap.getMapStatus();
        state += String.format(
                "zoom=%.1f rotate=%d overlook=%d",
                ms.zoom, (int) ms.rotate, (int) ms.overlook);
        tv_detail.setText(state);
    }
至此,获取地图的坐标就完成了。


## 显示Marker、地图触摸事件、移除Marker等 ##
接下来,我们实现一个稍微复杂的功能,如图上底部所示,点击SwitchCompat,动态在地图上显示一堆点(marker),点击marker,展现该点的详细信息
在布局加入:

    <LinearLayout
        android:id="@+id/activity_main_ll_bottomlayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:showDividers="middle">

        <android.support.v7.widget.SwitchCompat
            android:id="@+id/activity_main_sc_marker"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@color/colorPrimary"
            android:padding="10dp"
            android:text="一堆点"
            android:textColor="@android:color/white"
            android:textOff="-.-"
            android:textOn="^.^"
            toggle:showText="true"/>

    </LinearLayout>

    <!-- 飞机信息 -->
    <LinearLayout
        android:id="@+id/activity_main_flightinfo_ll_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:animateLayoutChanges="true"
        android:background="@android:color/white"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical"
        android:padding="10dp"
        android:visibility="gone">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="10dp">

            <TextView
                android:id="@+id/activity_main_flightinfo_tv_num"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="飞机编号:"
                android:textSize="18sp"/>

            <TextView
                android:id="@+id/activity_main_flightinfo_tv_model"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="飞机型号"
                android:textSize="18sp"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="10dp">

            <TextView
                android:id="@+id/activity_main_flightinfo_tv_startPlace"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="出发地:"
                android:textSize="18sp"/>

            <TextView
                android:id="@+id/activity_main_flightinfo_tv_endPlace"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="抵达地:"
                android:textSize="18sp"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="10dp">

            <TextView
                android:id="@+id/pop_window_flight_info_tv_startTime"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="出发时间:"
                android:textSize="18sp"/>

            <TextView
                android:id="@+id/pop_window_flight_info_tv_endTime"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="抵达时间:"
                android:textSize="18sp"/>
        </LinearLayout>
    </LinearLayout>
飞机详情信息此时是隐藏的,只有在单机到marker的时候才显示出来。
接下来,显示飞机信息一定要有实体类。新建MarkerInfo:
注:省略Getter and Setter方法,请自行生成,或拷贝文章末尾的Demo
    // 飞机编号
    private String num;
    // 飞机型号
    private String model;
    // 出发地
    private String startPlace;
    // 抵达地
    private String endPlace;
    // 出发时间
    private String startTime;
    // 抵达时间
    private String endTime;
    // 纬度
    private double latitude;
    // 经度
    private double longitude;

    public static List<MarkerInfo> mMarkerInfos= new ArrayList<>();; // 飞机信息列表

    public MarkerInfo()
    {

    }

    public MarkerInfo(  String num, String model, String startPlace, String endPlace,
                      String startTime, String endTime , double latitude, double longitude)
    {
        super();
        this.num = num;
        this.model = model;
        this.startPlace = startPlace;
        this.endPlace = endPlace;
        this.startTime = startTime;
        this.endTime = endTime;
        this.latitude = latitude;
        this.longitude = longitude;
    }
    
    static // 模拟数据,在地图上添加3个marker,所对应的数据
    {
        mMarkerInfos.add(new MarkerInfo(  "bh101", "model1", "北京", "天津", "10:00", "11:00",
                39.963175, 116.400244 ));
        mMarkerInfos.add(new MarkerInfo(  "bh102", "model2", "北京", "石家庄", "10:00", "11:30",
                39.963175, 116.400244 ));
        mMarkerInfos.add(new MarkerInfo(  "bh103", "model3", "北京", "呼和浩特", "10:00", "12:00",
                39.963175, 116.400244 ));
    }

    public String getNum()
    {
        return num;
    }
下面准备工作结束

在类里申明控件和findViewById,此处省略若干行代码
接下来申明
    // 报告点
    private List<Marker> markerList; // 飞机点列表
    private Marker mMarker; // 飞机点

    private BitmapDescriptor marker_flight;
    private InfoWindow mInfoWindow;
list存放我们的marker,如果不用list,将来移除的marker只能是一个点,而不是所有,因此,添加和移除都需要遍历
        sc_marker.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                if(isChecked)
                {
                    if (markerList == null) // 如果markerList为空,说明此时没有生成报告点
                    {
                        addFlightInfo(MarkerInfo.mMarkerInfos); // 添加报告点的方法
                    }
                } else
                {
                    if (markerList != null)
                    {
                        for (int i = 0; i < markerList.size(); i++)
                        {
                            markerList.get(i).remove();
                        }
                        markerList = null;
                    }
                }
            }
        });
为开关控件添加监听,当选中状态的时候,如果列表没有marker,则走添加marker的方法,在取消状态的时候,仅当list不为空的时候,才去移除marker,在移除结束后,将list置为空是我自己的写法以防意外发生。如果你逻辑比较强认为这里不需要加,也可以。
接下来看一下添加 marker的方法:
    /**
     * 添加飞机信息
     *
     * @param flightInfos
     */
    private void addFlightInfo(List<MarkerInfo> flightInfos)
    {
        LatLng latlng = null;
        OverlayOptions overlayOptions = null;
        markerList = new ArrayList<>();
        marker_flight = BitmapDescriptorFactory
                .fromResource(R.mipmap.ic_flight); // 飞机图标
        for (MarkerInfo infos : flightInfos)
        {

            latlng = new LatLng(infos.getLatitude(), infos.getLongitude()); // 经纬度
            overlayOptions = new MarkerOptions().position(latlng).icon(marker_flight).zIndex(9).animateType(MarkerOptions.MarkerAnimateType.grow);
            mMarker = (Marker) (mBaiduMap.addOverlay(overlayOptions));

            Bundle bundle = new Bundle();
            bundle.putSerializable("info", infos);
            mMarker.setExtraInfo(bundle);
            markerList.add(mMarker);
        }
        // 将地图移动到最后一个经纬度位置
        MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latlng);
        mBaiduMap.setMapStatus(u);
    }
我们在调用方法的时候,把MarkerInfo里的模拟数据加载进来,在循环中将对应的经纬度取出来,放在latlng对象中,在new MarkerOptions的时候,将坐标传了进去,并设置了飞机图标、marker所在层级、生长动画,最后使用mBaiduMap的addOverlay方法,添加marker,最后,使用bundle对象将infos的内容保存到了marker中。这样,就生成了一堆飞机点。
接下来,我们看一下点击时间:
// mark事件监听
        mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener()
        {

            @Override
            public boolean onMarkerClick(Marker marker)
            {
                MarkerInfo info = (MarkerInfo) marker.getExtraInfo().get("info");

                InfoWindow.OnInfoWindowClickListener listener = null;
                TextView text = new TextView(getApplicationContext());
                text.setBackgroundResource(R.mipmap.location_tips);
                text.setPadding(30, 30, 30, 30);
                text.setTextColor(getResources().getColor(android.R.color.white));
                text.setText(info.getNum());
                // 将marker所在的经纬度的信息转化成屏幕上的坐标
                LatLng ll = marker.getPosition();
                listener = new InfoWindow.OnInfoWindowClickListener()
                {
                    @Override
                    public void onInfoWindowClick()
                    {
                        mBaiduMap.hideInfoWindow();
                    }
                };
                mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(text), ll, -47, listener);
                // 设置详细信息到布局
                setInfoToLayout(ll_info, info);
                ll_info.setVisibility(View.VISIBLE); // 显示飞机详情布局
                mBaiduMap.showInfoWindow(mInfoWindow); // 显示弹窗
                return true;
            }
        });
首先,marker.getExtraInfo().get("info")取得了marker对应的数据,这里我们动态添加了一个TextView,显示飞机的型号。,在listener中,如果点击到了弹出的textView,就让它消失,最后,setInfoToLayout()来将bundle里的数据显示到详情布局中,并设为可见状态,最后showInfoWindow显示出来,就基本完成了。下面看一下setInfoToLayout(ll_info, info);方法:

    /**
     * 为布局添加飞机详情信息
     *
     * @param ll_info
     * @param info
     */
    private void setInfoToLayout(LinearLayout ll_info, MarkerInfo info)
    {
        ViewHolder viewHolder = null;
        if (ll_info.getTag() == null)
        {
            viewHolder = new ViewHolder();
            viewHolder.tv_num = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_num);
            viewHolder.tv_model = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_model);
            viewHolder.tv_startPlace = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_startPlace);
            viewHolder.tv_endPlace = (TextView) ll_info.findViewById(R.id.activity_main_flightinfo_tv_endPlace);
            viewHolder.tv_startTime = (TextView) ll_info.findViewById(R.id.pop_window_flight_info_tv_startTime);
            viewHolder.tv_endTime = (TextView) ll_info.findViewById(R.id.pop_window_flight_info_tv_endTime);
            ll_info.setTag(viewHolder);
        }
        viewHolder = (ViewHolder) ll_info.getTag();
        viewHolder.tv_num.setText("飞机编号:" + info.getNum());
        viewHolder.tv_model.setText("飞机型号:" + info.getModel());
        viewHolder.tv_startPlace.setText("出发地:" + info.getStartPlace());
        viewHolder.tv_endPlace.setText("抵达地:" + info.getEndPlace());
        viewHolder.tv_startTime.setText("出发时间:" + info.getStartTime());
        viewHolder.tv_endTime.setText("抵达时间:" + info.getEndTime());

    }

    private class ViewHolder
    {
        TextView tv_num, tv_model, tv_startPlace, tv_endPlace, tv_startTime, tv_endTime;
    }

至此,功能就实现了,但是每次弹出详情只能点击TextView才能消失,感觉这样做体验不太舒服,因此,可以在地图的触摸时间加入对应的事件:
//地图触摸事件
        mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener()
        {

            @Override
            public void onTouch(MotionEvent motionEvent)
            {
                ll_info.setVisibility(View.GONE);
                mBaiduMap.hideInfoWindow();
            }
        });
ok,到此已经完成了本章的内容。如果有帮到你,请点赞。有疑问的可以留言,我会抽时间帮忙解决。
Demo下载地址

http://download.csdn.net/detail/u012552275/9680875

参考文章:

http://blog.csdn.net/lmj623565791/article/details/37737213


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值