(第23讲) 示例23--瓦片图功能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(第23讲) 示例23--瓦片图功能相关的知识,希望对你有一定的参考价值。

分类:C#、android、百度地图应用; 日期:2016-02-04

一、简介

地图SDK自v3.6.0起,新增瓦片图层(tileOverlay), 该图层支持开发者添加自有瓦片数据,包括本地加载和在线下载两种方式。该图层可随地图的平移、缩放、旋转等操作做相应的变换,它仅位于底图之上(即瓦片图层将会遮挡底图,不遮挡其他图层),瓦片图层的添加顺序不会影响其他图层(例如:POI搜索图层、我的位置图层等)的叠加关系,适用于开发者拥有某一区域的地图,并希望使用此区域地图覆盖相应位置的百度地图。

1、瓦片划分规则

百度地图SDK会根据不同的比例尺将地图划分成若干个瓦片,并且以中心点经纬度(0,0)开始计算瓦片,当地图显示缩放级别增大时,每一个瓦片被划分成4个瓦片。如:

地图级别为0时,只有1张瓦片;

地图级别为1时,会分成 1 * 4 = 4 张瓦片;

依次类推。

当地图级别为n时,总共划分的瓦片为:4的n次方。

为了保证瓦片的显示效果,第n级的瓦片显示的地图level范围为[n - 0.5, n + 0.5)

2、本地加载和在线下载

瓦片图层分为本地加载和在线下载两种绘制方式。

(1)本地加载方式,将图片打包于应用内(保存到Assets文件夹下),适用于图片较小且不需要频繁变更的情况。

(2)在线下载,将图片存放于开发者提供的服务中,提供给SDK一个URL模板,通过URLTileLayer调用在线瓦片图层的URL。

二、运行截图

简介:瓦片图层支持开发者添加自有瓦片数据,包括在线下载和本地加载两种方式。

详述:

(1)在线下载方式

(2)本地加载方式

本示例运行截图如下:

技术分享

三、设计步骤

1、添加demo23_tile_overlay.xml文件

在layout文件夹下添加该文件,代码不再列出。

2、添加Demo23TileOverlay.cs文件

在SrcSdkDemos文件夹下添加该文件,然后将代码改为下面的内容:

using System;
using Android.App;
using Android.OS;
using Android.Widget;
using Com.Baidu.Mapapi.Map;
using Com.Baidu.Mapapi.Model;
using Android.Graphics;
using Android.Util;
namespace BdMapV371Demos.SrcSdkDemos
{
    /// <summary>
    /// TileOverlay 测试demo
    /// </summary>
    [Activity(Label = "@string/demo_name_tileoverlay")]
    public class Demo23TileOverlay : Activity, BaiduMap.IOnMapLoadedCallback
    {
        private TextureMapView mMapView;
        private BaiduMap mBaiduMap;
        // 设置瓦片图的在线缓存大小,默认为20 M
        public const int TileTmpOnlineCache = 20 * 1024 * 1024;
        public string onlineUrl = "http://api0.map.bdimg.com/customimage/tile"
            + "?&x={x}&y={y}&z={z}&udt=20150601&customid=light";
        private TileOverlay tileOverlay;
        private MapStatusUpdate mMapStatusUpdate;
        private bool mapLoaded = false;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.demo23_tile_overlay);
            mMapView = FindViewById<TextureMapView>(Resource.Id.mapview);
            mBaiduMap = mMapView.Map;
            mBaiduMap.SetOnMapLoadedCallback(this);

            MapStatus.Builder builder = new MapStatus.Builder();
            builder.Zoom(16.0f);
            builder.Target(new LatLng(39.914935D, 116.403119D));
            mMapStatusUpdate = MapStatusUpdateFactory.NewMapStatus(builder.Build());
            mBaiduMap.SetMapStatus(mMapStatusUpdate);

            Button btnOnline = FindViewById<Button>(Resource.Id.online);
            Button btnOffline = FindViewById<Button>(Resource.Id.offline);
            CheckBox hidePoiInfo = FindViewById<CheckBox>(Resource.Id.hide_poiinfo);
            // 设置在线方法监听
            btnOnline.Click += delegate
            {
                OnlineTile();
            };
            // 设置离线方法监听
            btnOffline.Click += delegate
            {
                OfflineTile();
            };
            hidePoiInfo.CheckedChange += (s, e) =>
            {
                if (e.IsChecked)
                {
                    mBaiduMap.ShowMapPoi(false);//仅显示交通图
                }
                else
                {
                    mBaiduMap.ShowMapPoi(true);
                }
            };
            Button btnClearTile = FindViewById<Button>(Resource.Id.btnClearTile);
            btnClearTile.Click += delegate
            {
                RemoveTile();
            };
        }
        private void RemoveTile()
        {
            if (tileOverlay != null && mBaiduMap != null)
            {
                tileOverlay.RemoveTileOverlay();
            }
        }

        /// <summary>使用瓦片图的在线方式</summary>
        private void OnlineTile()
        {
            RemoveTile();
            // 构造显示瓦片图范围,当前为世界范围
            LatLng northeast = new LatLng(80, 180);
            LatLng southwest = new LatLng(-80, -180);
            LatLngBounds bounds = new LatLngBounds.Builder()
                    .Include(northeast)
                    .Include(southwest)
                    .Build();
            var tileProvider = new MyUrlTileProvider(this);
            // 通过option指定相关属性,向地图添加在线瓦片图对象
            TileOverlayOptions options = new TileOverlayOptions()
                .TileProvider(tileProvider)
                .SetMaxTileTmp(TileTmpOnlineCache)
                .SetPositionFromBounds(bounds);
            tileOverlay = mBaiduMap.AddTileLayer(options);
            if (mapLoaded)
            {
                //mBaiduMap.MapType = BaiduMap.MapTypeNormal;
                mBaiduMap.SetMaxAndMinZoomLevel(21.0f, 3.0f);
                mBaiduMap.SetMapStatusLimits(new LatLngBounds.Builder()
                    .Include(northeast).Include(southwest)
                    .Build());
                mBaiduMap.SetMapStatus(mMapStatusUpdate);
            }
        }

        /// <summary>瓦片图的离线添加</summary>
        private void OfflineTile()
        {
            RemoveTile();
            //// 构造显示瓦片图范围,当前为世界范围
            LatLng northeast = new LatLng(80, 180);
            LatLng southwest = new LatLng(-80, -180);
            var tileProvider = new MyFileTileProvider(this);
            // 通过option指定相关属性,向地图添加离线瓦片图对象
            LatLngBounds bounds = new LatLngBounds.Builder()
                 .Include(northeast).Include(southwest).Build();
            //// 设置离线瓦片图属性option
            TileOverlayOptions options = new TileOverlayOptions()
                .TileProvider(tileProvider)
                .SetPositionFromBounds(bounds);
            mBaiduMap.MapType = BaiduMap.MapTypeSatellite;
            tileOverlay = mBaiduMap.AddTileLayer(options);
            if (mapLoaded)
            {
                mBaiduMap.MapType = BaiduMap.MapTypeNormal;
                LatLng northeast1 = new LatLng(39.94001804746338, 116.41224644234747);
                LatLng southwest1 = new LatLng(39.90299859954822, 116.38359947963427);
                LatLngBounds.Builder builder = new LatLngBounds.Builder();
                builder.Include(northeast1)
                       .Include(southwest1);
                mBaiduMap.SetMapStatusLimits(builder.Build());
                mBaiduMap.SetMaxAndMinZoomLevel(17.0f, 16.0f);
                mBaiduMap.SetMapStatus(mMapStatusUpdate);
            }
        }

        //实现接口
        public void OnMapLoaded()
        {
            mapLoaded = true;
        }
        protected override void OnPause()
        {
            base.OnPause();
            mMapView.OnPause();
        }
        protected override void OnResume()
        {
            base.OnResume();
            mMapView.OnResume();
        }
        protected override void OnDestroy()
        {
            base.OnDestroy();
            mMapView.OnDestroy();
        }
    }

    // 定义瓦片图的在线Provider,并实现相关接口
    public class MyUrlTileProvider : UrlTileProvider
    {
        private Demo23TileOverlay a;
        public MyUrlTileProvider(Demo23TileOverlay a)
        {
            this.a = a;
        }
        public override int MaxDisLevel
        {
            get { return 21; }  //显示瓦片图的最大级别
        }
        public override int MinDisLevel
        {
            get { return 3; }//显示瓦片图的最小级别
        }
        public override string TileUrl
        {
            get { return a.onlineUrl; }
        }
    }
    /// <summary>
    /// 定义瓦片图的离线Provider,并实现相关接口
    /// </summary>
    public class MyFileTileProvider : FileTileProvider
    {
        private Demo23TileOverlay a;
        public MyFileTileProvider(Demo23TileOverlay a)
        {
            this.a = a;
        }
        public override int MaxDisLevel
        {
            get { return 21; }
        }
        public override int MinDisLevel
        {
            get { return 3; }
        }
        public override Tile GetTile(int x, int y, int z)
        {
            // 根据地图某一状态下x、y、z加载指定的瓦片图
            string filedir = string.Format(
                "LocalTileImage/{0}/{0}_{1}_{2}.jpg", z, x, y);
            Android.Graphics.Bitmap bm = null;
            System.IO.Stream inputStream = null;
            try
            {
                inputStream = a.Assets.Open(filedir);
                bm = BitmapFactory.DecodeStream(inputStream);
            }
            catch (Exception e)
            {
                Log.Debug("MyFileTileProvider", "瓦片图加载错误。\\n" + e.StackTrace);
                return null;
            }
            if (bm == null)
            {
                Log.Debug("MyFileTileProvider", "bm为null");
                return null;
            }
            byte[] bytes = new byte[bm.ByteCount];
            inputStream.Read(bytes, 0, bytes.Length);
            // 瓦片图尺寸必须满足256 * 256
            var offlineTile = new Tile(bm.Width, bm.Height, bytes);
            bm.Recycle();
            return offlineTile;
        }
    }
}

3、修改MainActivity.cs文件

在MainActivity.cs文件的demos字段定义中,去掉【示例23】下面的注释。

运行观察效果。

以上是关于(第23讲) 示例23--瓦片图功能的主要内容,如果未能解决你的问题,请参考以下文章

第23讲: Scala高阶函数实战详解

(第20讲) 示例20—全景图完整示例

如何使用多个 NavHost 片段创建深层链接

arcgis 瓦片图加载规则(转载)

利用线程池下载百度地图瓦片图

# 20182328 2019-2020-1 《数据结构与面向对象程序设计》第23周学习总结