1. 程式人生 > >Android高德地圖的自定義底圖(午夜藍主題風格地圖)

Android高德地圖的自定義底圖(午夜藍主題風格地圖)

官網上介紹:地址連結
從 3D 地圖 SDK V4.1.3版本開始支援自定義地圖底圖功能。
功能說明:支援對部分地圖元素自定義顏色,包括:填充色、邊框色、文字顏色。
先上圖,我自己做出來的自定義地圖(底圖)
這裡寫圖片描述

效果圖就是以上這樣,下面來說一下實現的步驟
1.高德環境整合
整合步驟請進高德開發者平臺去安裝步驟進行
注意:自定義的圖層所需的地圖是3D地圖
2.佈局檔案

?xml version="1.0" encoding="utf-8"?>
<RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="zph.zhjx.com.chat.ui.TrackActivity"> <include android:id="@+id/headview1" layout="@layout/headview1"/> <com.amap.api.maps
.MapView android:layout_below="@+id/headview1" android:id="@+id/tracked_map" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true" > </com.amap.api.maps.MapView> </RelativeLayout>

3.核心程式碼
支援自定義的具體元素和專案,請見下表:

featureType(地圖元素) geometry.fill(填充色) geometry.stroke(邊框色) labels.text.fill(文字填充色) labels.text.stroke(文字邊框色)
land(陸地) ✔️
water (水系) ✔️
green (綠地) ✔️
building (樓塊) ✔️ ✔️
Highway (高速及城市主道路) ✔️ ✔️ ✔️ ✔️
Local (普通道路) ✔️
Railway (鐵路) ✔️ ✔️
Subway (地鐵) ✔️ ✔️
Boundary (行政區) ✔️ ✔️
Districtlabel (行政區文字) ✔️ ✔️
Poilabel (所有文字,除行政區&道路文字) ✔️ ✔️

根據支援自定義的具體元素和專案,我編寫的JSON配置檔案如下:
style_json.json
在Android studio中java目錄下建立assets資料夾
將style_json.json放置到該目錄下

[
  {
    "featureType":"land",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#08304B"
    }
  },
  {
    "featureType":"land",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#021019"
    }
  },
  {
    "featureType":"land",
    "elementType":"labels.text.fill",
    "stylers":{
      "color":"#847F7F"
    }
  },
  {
    "featureType":"water",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#021019"
    }
  },
  {
    "featureType":"water",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#08304B"
    }
  },
  {
    "featureType":"green",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#b0d3dd"
    }
  },
  {
    "featureType":"green",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#33A1C9"
    }
  },
  {
    "featureType":"building",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#021019"
    }
  },
  {
    "featureType":"building",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":""
    }
  },
  {
    "featureType":"highway",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#a6cfcf"
    }
  },
  {
    "featureType":"highway",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#7dabb3"
    }
  },
  {
    "featureType":"highway",
    "elementType":"labels.text.fill",
    "stylers":{
      "color":"#8B4513"
    }
  },
  {
    "featureType":"highway",
    "elementType":"labels.text.stroke",
    "stylers":{
      "color":"#33A1C9"
    }
  },
  {
    "featureType":"arterial",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#a6cfcf"
    }
  },
  {
    "featureType":"arterial",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#a6cfcf"
    }
  },
  {
    "featureType":"arterial",
    "elementType":"labels.text.fill",
    "stylers":{
      "color":"#8B4513"
    }
  },
  {
    "featureType":"arterial",
    "elementType":"labels.text.stroke",
    "stylers":{
      "color":"#8B4513"
    }
  },
  {
    "featureType":"local",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#f1f1f1"
    }
  },
  {
    "featureType":"railway",
    "elementType":"geometry.fill",
    "stylers":{
      "color":""
    }
  },
  {
    "featureType":"railway",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":""
    }
  },
  {
    "featureType":"subway",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#33A1C9"
    }
  },
  {
    "featureType":"subway",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#33A1C9"
    }
  },
  {
    "featureType":"boundary",
    "elementType":"geometry.fill",
    "stylers":{
      "color":"#33A1C9"
    }
  },
  {
    "featureType":"boundary",
    "elementType":"geometry.stroke",
    "stylers":{
      "color":"#f1f1f1"
    }
  },
  {
    "featureType":"poilabel",
    "elementType":"labels.text.fill",
    "stylers":{
      "color":"#f5f5f5"

    }
  },
  {
    "featureType":"poilabel",
    "elementType":"labels.text.stroke",
    "stylers":{
      "color":""
    }
  },
  {
    "featureType":"districtlable",
    "elementType":"labels.text.fill",
    "stylers":{
      "color":"#00affe"
    }
  },
  {
    "featureType":"districtlable",
    "elementType":"labels.text.stroke",
    "stylers":{
      "color":""
    }
  }
]

設定檔案路徑
官網說明如下:

1、將配置好的樣式檔案放入任意路徑,比如”/sdcard/custom_config”
2、設定地圖樣式檔案的路徑,通過以下方法設定自定義地圖樣式檔案的絕對路徑:
百度地圖的自定義底圖是要求在地圖初始話之前要進行樣式路徑設定,在高德地圖中可以不這樣做
我的設計是將assets中的style_json.json檔案讀寫到手機的資料夾下面,然後設定路徑為手機的路徑
首先是本地檔案工具類建立

public class FileUtil {
    private static int bufferd = 1024;

    private FileUtil() {
    }

    /*
     * <!-- 在SDCard中建立與刪除檔案許可權 --> <uses-permission
     * android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!--
     * 往SDCard寫入資料許可權 --> <uses-permission
     * android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     */

    // =================get SDCard information===================
    public static boolean isSdcardAvailable() {
        String status = Environment.getExternalStorageState();
        if (status.equals(Environment.MEDIA_MOUNTED)) {
            return true;
        }
        return false;
    }

    public static long getSDAllSizeKB() {
        // get path of sdcard
        File path = Environment.getExternalStorageDirectory();
        StatFs sf = new StatFs(path.getPath());
        // get single block size(Byte)
        long blockSize = sf.getBlockSize();
        // 獲取所有資料塊數
        long allBlocks = sf.getBlockCount();
        // 返回SD卡大小
        return (allBlocks * blockSize) / 1024; // KB
    }

    /**
     * free size for normal application
     *
     * @return
     */
    public static long getSDAvalibleSizeKB() {
        File path = Environment.getExternalStorageDirectory();
        StatFs sf = new StatFs(path.getPath());
        long blockSize = sf.getBlockSize();
        long avaliableSize = sf.getAvailableBlocks();
        return (avaliableSize * blockSize) / 1024;// KB
    }

    // =====================File Operation==========================
    public static boolean isFileExist(String director) {
        File file = new File(Environment.getExternalStorageDirectory()
                + File.separator + director);
        return file.exists();
    }

    /**
     * create multiple director
     *
     * @param director
     * @return
     */
    public static boolean createFile(String director) {
        if (isFileExist(director)) {
            return true;
        } else {
            File file = new File(Environment.getExternalStorageDirectory()
                    + File.separator + director);
            if (!file.mkdirs()) {
                return false;
            }
            return true;
        }
    }

    public static File writeToSDCardFile(String directory, String fileName,
                                         String content, boolean isAppend) {
        return writeToSDCardFile(directory, fileName, content, "", isAppend);
    }

    /**
     *
     * @param directory
     *            (you don't need to begin with
     *            Environment.getExternalStorageDirectory()+File.separator)
     * @param fileName
     * @param content
     * @param encoding
     *            (UTF-8...)
     * @param isAppend
     *            : Context.MODE_APPEND
     * @return
     */
    public static File writeToSDCardFile(String directory, String fileName,
                                         String content, String encoding, boolean isAppend) {
        // mobile SD card path +path
        File file = null;
        OutputStream os = null;
        try {
            if (!createFile(directory)) {
                return file;
            }
            file = new File(Environment.getExternalStorageDirectory()
                    + File.separator + directory + File.separator + fileName);
            os = new FileOutputStream(file, isAppend);
            if (encoding.equals("")) {
                os.write(content.getBytes());
            } else {
                os.write(content.getBytes(encoding));
            }
            os.flush();
        } catch (IOException e) {
            Log.e("FileUtil", "writeToSDCardFile:" + e.getMessage());
        } finally {
            try {
                if(os != null){
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * write data from inputstream to SDCard
     */
    public File writeToSDCardFromInput(String directory, String fileName,
                                       InputStream input) {
        File file = null;
        OutputStream os = null;
        try {
            if (createFile(directory)) {
                return file;
            }
            file = new File(Environment.getExternalStorageDirectory()
                    + File.separator + directory + fileName);
            os = new FileOutputStream(file);
            byte[] data = new byte[bufferd];
            int length = -1;
            while ((length = input.read(data)) != -1) {
                os.write(data, 0, length);
            }
            // clear cache
            os.flush();
        } catch (Exception e) {
            Log.e("FileUtil", "" + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * this url point to image(jpg)
     *
     * @param url
     * @return image name
     */
    public static String getUrlLastString(String url) {
        String[] str = url.split("/");
        int size = str.length;
        return str[size - 1];
    }
}

然後,在Activity中進行核心程式碼編寫

package zph.zhjx.com.chat.ui;

import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.bumptech.glide.Glide;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import zph.zhjx.com.chat.R;
import zph.zhjx.com.chat.base.BaseActivity;
import zph.zhjx.com.chat.dao.People;
import zph.zhjx.com.chat.util.BitmapUtil;
import zph.zhjx.com.chat.util.DBUtil;
import zph.zhjx.com.chat.util.FileUtil;
import zph.zhjx.com.chat.view.CircleImageView;

public class TrackActivity extends BaseActivity implements  AMap.OnMapLoadedListener, AMap.OnMapTouchListener, LocationSource, AMapLocationListener, View.OnClickListener, AMap.OnCameraChangeListener {
    private View headview;
    private LinearLayout back;
    private TextView title;
    private MapView mapview;
    private AMap aMap;
    private OnLocationChangedListener mListener;
    private AMapLocationClient mlocationClient;
    private AMapLocationClientOption mLocationOption;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_track);

        initview();
        initMap(savedInstanceState);
    }
    /**
     * 初始化地圖
     * */
    private void initMap(Bundle savedInstanceState) {
        mapview.onCreate(savedInstanceState);
        if (aMap == null) {
            aMap = mapview.getMap();
            Log.i("TAG","11111");
            mapview.setSelected(true);
            setBlueMap();
        }
        aMap.setLocationSource(this);// 設定定位監聽
        aMap.setOnMapLoadedListener(this);
        aMap.setOnMapTouchListener(this);
        aMap.setOnCameraChangeListener(this);
    }

    private void setBlueMap() {
        //進行JSON的檔案讀取然後寫入到本地
        InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(getAssets().open("style_json/style_json.json"),"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        BufferedReader br = new BufferedReader(isr);
        String line;
        StringBuilder builder = new StringBuilder();
        try {
            while((line = br.readLine()) != null){
                builder.append(line);
            }

            br.close();
            isr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //寫入到本地目錄中
        FileUtil.writeToSDCardFile("style_json","style.json",builder.toString(),true);
        //載入個性化的地圖底圖資料
        aMap.setCustomMapStylePath(Environment.getExternalStorageDirectory()
                + File.separator+"style_json/style.json");
        //開啟自定義樣式
        aMap.setMapCustomEnable(true);
        aMap.getUiSettings().setMyLocationButtonEnabled(false);// 設定預設定位按鈕是否顯示
        aMap.setMyLocationEnabled(true);// 設定為true表示顯示定位層並可觸發定位,false表示隱藏定位層並不可觸發定位,預設是false
    }

    private void initview() {
        mapview= (MapView) findViewById(R.id.tracked_map);
        headview=findViewById(R.id.headview1);
        back= (LinearLayout) headview.findViewById(R.id.headview_left_layout);
        back.setOnClickListener(this);
        title= (TextView) headview.findViewById(R.id.headview_left_textview);
        title.setText("行為軌跡"+"");

    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
        if (mlocationClient == null) {
            mlocationClient = new AMapLocationClient(this);
            mLocationOption = new AMapLocationClientOption();
            //設定定位監聽
            mlocationClient.setLocationListener(this);
            //設定為高精度定位模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //設定多少秒去重新整理位置
            mLocationOption.setInterval(10*1000);
            //設定定位引數
            mlocationClient.setLocationOption(mLocationOption);
            // 此方法為每隔固定時間會發起一次定位請求,為了減少電量消耗或網路流量消耗,
            // 注意設定合適的定位時間的間隔(最小間隔支援為2000ms),並且在合適時間呼叫stopLocation()方法來取消定位請求
            // 在定位結束後,在合適的生命週期呼叫onDestroy()方法
            // 在單次定位情況下,定位無論成功與否,都無需呼叫stopLocation()方法移除請求,定位sdk內部會移除
            mlocationClient.startLocation();
        }
    }

    @Override
    public void deactivate() {
        //停止定位
        mListener = null;
        if (mlocationClient != null) {
            mlocationClient.stopLocation();
            mlocationClient.onDestroy();
        }
        mlocationClient = null;
    }

    @Override
    public void onMapLoaded() {

    }

    @Override
    public void onTouch(MotionEvent motionEvent) {

    }

    @Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (mListener != null && amapLocation != null) {
            if (amapLocation != null && amapLocation.getErrorCode() == 0) {
                mListener.onLocationChanged(amapLocation);// 顯示系統小藍點
                //TODO
                //當定位好了以後,拿到經緯度
                double lat = amapLocation.getLatitude();
                double lng = amapLocation.getLongitude();
                LatLng latlng = new LatLng(lat, lng);
                //移動到定位處
                CameraUpdate movecity = CameraUpdateFactory.newLatLngZoom(latlng,9);
                aMap.moveCamera(movecity);
                deactivate();
//                showListView();
            } else {
                String errText = "定位失敗," + amapLocation.getErrorCode() + ": " + amapLocation.getErrorInfo();
                Log.i("TAG", errText);
            }
        }
        else{

        }
    }



    /**
     * 方法必須重寫
     */
    @Override
    protected void onResume() {
        super.onResume();
        mapview.onResume();
    }

    /**
     * 方法必須重寫
     */
    @Override
    protected void onPause() {
        super.onPause();
        mapview.onPause();
        deactivate();
    }

    /**
     * 方法必須重寫
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapview.onSaveInstanceState(outState);
//        initMap(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        initMap(savedInstanceState);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.headview_left_layout:
                this.finish();
                break;

        }
    }

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if(horizontalScrollView.getVisibility()==View.VISIBLE){
            horizontalScrollView.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void onCameraChangeFinish(CameraPosition cameraPosition) {
        if(horizontalScrollView.getVisibility()==View.INVISIBLE){
            horizontalScrollView.setVisibility(View.VISIBLE);
        }
        Log.i("TAG","當前地圖的層級:"+aMap.getCameraPosition().zoom);
    }
}

以上是全部內容,其中不包含在Android studio中的高德地圖環境整合。

相關推薦

Android地圖定義午夜主題風格地圖

官網上介紹:地址連結 從 3D 地圖 SDK V4.1.3版本開始支援自定義地圖底圖功能。 功能說明:支援對部分地圖元素自定義顏色,包括:填充色、邊框色、文字顏色。 先上圖,我自己做出來的自定義地圖(底圖) 效果圖就是以上這樣,下面來說一下實現的步驟

Android 定義Camera相機封裝工具類賊簡單

背景 目前公司的專案都是,針對生物認證來進行一些驗證之類的功能,比方說,互動式活體檢測,人臉1v1(對比),人臉1vN(搜尋)。用系統自帶的相機?當然是不夠用了,不夠用那就自定義啦,就像是前幾天七夕,沒物件怎麼辦,當然是new一個了。對了結尾還提供了一個呼叫極

Android中ListView實現圖文並列並且定義分割線完善仿微信APP

昨天的(今天凌晨)的博文《Android中Fragment和ViewPager那點事兒》中,我們通過使用Fragment和ViewPager模仿實現了微信的佈局框架。今天我們來通過使用ListView實現其中聯絡人一欄的基本檢視,效果如下: 要實現上圖的效果,我們要用到兩

node_01_定義模塊先創建package.json

避免 col 定義 help res 字符 npm 單引號 pac package.json必須是json格式 你必須確保所有的字符串,包括屬性名,都是使用雙引號而不是單引號  {       "name": "163",   "version": "1.

定義python命令python命令列之argparser

目錄 1、argparser.ArgumentParser([,description]) 2、ArgumentParser.add_argument(): 3、args = parser.parse_args(): 4、optional之short options :我看的論文裡面

c++ map定義比較函式按key和按value

按key: //自定義map的key typedef struct UrlKey { uint64_t dwBussID; uint64_t dwVersion; uint64

關於Laravel 定義HTTP錯誤404,500等錯誤

使用Dingo: 1、在......\vendor\dingo\api\src\Exception\Handler.php中修改建構函式 2、將.env檔案中的API_DEBUG改為false 不使用Dingo: 修改....\app\Exceptions\Handler

c#定義配置節點web.config、app.config

這裡提供一個例項的完整寫法,深入瞭解的話請參考官方的文件 1.專案引用System.Configuration 2.編寫PositionConfigurationSection,程式碼如下: public class PositionConfigurationSection: Confi

springboot配置fastJson定義序列化解決js精度丟失問題

最近的專案中碰到了js精度丟失的問題,專案中一個Long型的數值傳遞到前臺後出現了精度丟失,資料不對了,檢查發現是js的問題。解決方案:json序列化時將Long轉成string再傳遞到前臺,重寫configureMessageConverters

定義滾動條原生,相容ie8以上

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title> </head> &l

關於地圖怎麽搜索定義地理位自己定義標位置

js html 因為我在前端定義圖標位置(經緯度),現在想通過高德地圖AMap.Autocomplete自動提示:提示我自定義(地理圖標)高德地圖有說明,這個附錄要怎麽去調用?關於高德地圖怎麽搜索自定義地理位(自己定義圖標位置)

Android 地圖定義地圖覆蓋物Marker

先上效果圖,攝像頭和攝像頭上的預警事件紅點就是一個自定義佈局作為地圖的marker的圖示。                camera_red.png (素材圖) 官方提供的API參考手冊:http://

地圖定義點聚合樣式Android

寫了Android高德地圖的點聚合功能 不廢話:直接上程式碼 private ClusterOverlay mClusterOverlay; private int clusterRadius = 100; private void dianjuheP

Android實現地圖定義樣式

放置Android工程下的assets資料夾,在assets資料夾裡面建立了一個styleMap子資料夾。將裡面的檔案寫到sd卡中。 寫出檔案程式碼: try { // 先獲取系統

ArcGIS API for JavaScript3.x 學習筆記[5] 加載在線地圖

alex apt arcgis lex 添加 declare 學習 created ade /** * Created by WanderGIS on 2015/7/15. */ define(["dojo/_base/declare", "esri/geom

地圖---定義飄窗

第一步繼承類MainActivity extends Activity implements OnInfoWindowClickListener,InfoWindowAdapter //給定位的mark新增infoWindow aMap.setOnInfoWindowClickList

地圖定義 marker 佈局里加載網路圖片不顯示的問題

服務端返回一組 marker 陣列,for 迴圈裡新增自定義佈局 marker到地圖上 要注意兩個原因不顯示 marker 1,要在圖片載入完後再把 佈局view新增到 marker 上 2,markerOption必須是 for 迴圈裡的變數,不能是全域性變數,不然

地圖定義Marker點選時出現的InfoWindow

1.自定義InfoWindowAdapter: package com.onetoo.www.onetoo.abapter.home; import android.content.Context;

Vue地圖定義覆蓋物使用例項-content的使用

本例使用content實現在高德地圖上自定義覆蓋物,即自定義marker。先看如下效果: 標題 在地圖上顯示三種顏色的marker:綠色,紫色,橙色。當點選其中的一個marker時,該Marker顏色變為藍色,size變大,並旋轉45度。再次點選其他marker時,之前

AMap地圖定義指標,定位mapview新方法!

最近公司需要做範圍內打卡的功能,所以研究了下高德地圖的SDK,首先註冊申請key就不多講了,百度有很詳細的資料,下面主要記錄下實現方法。demo地址在最下方:下載後自行更新cocoapod檔案下載依