天天看點

react native android 高德地圖原生代碼編寫react native android 高德地圖原生代碼編寫

react native android 高德地圖原生代碼編寫

  • react native android 高德地圖原生代碼編寫
    • android代碼
      • MyAmapView
        • 高德地圖注意事項
        • 代碼
      • AMapViewManager
        • 代碼注解
        • viewManager如何被外部的js調用的
        • error
        • 代碼
      • AMapModule
        • 代碼注解
        • 代碼
      • AMapPackage
      • MainApplication
    • js代碼

android代碼

MyAmapView

高德地圖注意事項

  • key授權失敗

    請注意包含高德key的meta-data标簽是否被包含在application标簽中

  • 高德地圖無法顯示
    1. 先檢視一下rn中地圖view是否占了位置沒有顯示,設定rn中的view的背景顔色可檢視,rnview的大小設定沒.如果占了位置,檢查是否調用

      mapView.onCreate();

    2. 使用frameLayout請檢查是否調用

      this.addView()

  • 以下就是部分代碼

代碼

因為公司原因,貼出部分代碼,有需要的可以直接從裡面拷貝一些代碼來用
package com.aiyunbao.aMap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.aiyunbao.R;
import com.aiyunbao.marker.MarkerUtil;
import com.aiyunbao.poi.PoiSearchBiz;
import com.aiyunbao.utils.SensorEventHelper;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.Circle;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.services.core.LatLonPoint;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.ThemedReactContext;

import static com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_RIGHT;
import static com.amap.api.maps.AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM;

/**
 * Created by aiyun-pc1 on 2017/5/8.
 */

public class MyAMapView extends FrameLayout implements AMap.OnMyLocationChangeListener, AMap.OnMapClickListener,
        AMap.OnMapLongClickListener, AMap.OnCameraChangeListener, AMap.OnMarkerClickListener,
        AMap.OnMarkerDragListener, AMap.OnInfoWindowClickListener, AMap.InfoWindowAdapter, LocationSource {

    private final ThemedReactContext reactContext;
    private final ViewGroup.LayoutParams PARAM;
    private MapView MAPVIEW;
    private AMap aMap;
    private UiSettings mUiSettings;
    public AMapLocationClientOption mLocationOption = null;
    private AMapLocationClient mlocationClient;
    private long startTime;

    private OnLocationChangedListener mListener;

    private boolean mFirstFix = false;

    private static final int STROKE_COLOR = Color.argb(, , , );
    private static final int FILL_COLOR = Color.argb(, , , );
    /**
     * 傳感器
     */
    private SensorEventHelper mSensorHelper;
    private Marker mLocMarker;
    private Circle mCircle;
    /**
     * 螢幕中心點的大頭針
     */
    private Marker screenPosition;

    public MyAMapView(ThemedReactContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        PARAM = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        init();
    }

    public AMap getAmap() {
        if (aMap == null) {
            aMap = MAPVIEW.getMap();
        }
        return aMap;
    }

    /**
     * 初始化控件,定位位置
     */
    private void init() {
        //定位箭頭旋轉
        mSensorHelper = new SensorEventHelper(reactContext);
        if (mSensorHelper != null) {
            mSensorHelper.registerSensorListener();
        }
        MAPVIEW = new MapView(reactContext);
        MAPVIEW.setLayoutParams(PARAM);
        this.addView(MAPVIEW);
        MAPVIEW.onCreate(reactContext.getCurrentActivity().getIntent().getExtras());

        setUpMap();

    }

    /**
     * 設定一些amap的屬性
     */
    private void setUpMap() {

        aMap = MAPVIEW.getMap();
        aMap.setMapType(AMap.MAP_TYPE_NORMAL);// 矢量地圖模式

        //控件互動
        mUiSettings = aMap.getUiSettings();//執行個體化UiSettings類
        mUiSettings.setZoomControlsEnabled(false);//顯示縮放按鈕
        //縮放按鈕  右邊界中部:ZOOM_POSITION_RIGHT_CENTER 右下:ZOOM_POSITION_RIGHT_BUTTOM。
        mUiSettings.setZoomPosition(ZOOM_POSITION_RIGHT_BUTTOM);
        //Logo的位置 左下:LOGO_POSITION_BOTTOM_LEFT 底部居中:LOGO_POSITION_BOTTOM_CENTER 右下:LOGO_POSITION_BOTTOM_RIGHT
        mUiSettings.setLogoPosition(LOGO_POSITION_BOTTOM_RIGHT);
        mUiSettings.setCompassEnabled(false);//指南針
        mUiSettings.setZoomGesturesEnabled(true);//手勢縮放
        mUiSettings.setScaleControlsEnabled(true);//比例尺


        //        changeCamera(
        //                CameraUpdateFactory.newCameraPosition(new CameraPosition(
        //                        latLng, ZOOMLEVEL, 30, 0)));//建立view時候傳入之前定位到目前坐标位置把地圖中心移動過去


        //        addLocationMarker(latLng, RADIUS, mLocMarker);


        initBluePoint();
        initListener();
        screenPosition = MarkerUtil.addMarkerInScreenCenter(aMap, "purple_pin", reactContext);
    }

    private void initListener() {
        aMap.setOnMapClickListener(this);// 對amap添加單擊地圖事件監聽器
        aMap.setOnMapLongClickListener(this);// 對amap添加長按地圖事件監聽器
        aMap.setOnCameraChangeListener(this);// 對amap添加移動地圖事件監聽器
        aMap.setOnMarkerClickListener(this);// marker點選事件監聽器
        aMap.setOnMarkerDragListener(this);// 設定marker可拖拽事件監聽器
        //        aMap.setOnMapLoadedListener(this);// 設定amap加載成功事件監聽器
        aMap.setOnMarkerClickListener(this);// 設定點選marker事件監聽器
        aMap.setOnInfoWindowClickListener(this);// 設定點選infoWindow事件監聽器
        aMap.setInfoWindowAdapter(this);// 設定自定義InfoWindow樣式
        aMap.setOnMyLocationChangeListener(this);//設定SDK 自帶定位消息監聽
    }

    /**
     * Activity onResume後調用view的onAttachedToWindow
     */
    @Override
    protected void onAttachedToWindow() {
        //        init();
        super.onAttachedToWindow();
    }

    /**
     * view生命周期onDetachedFromWindow
     */
    @Override
    protected void onDetachedFromWindow() {
        this.removeView(MAPVIEW);
        MAPVIEW.onDestroy();
        super.onDetachedFromWindow();
    }

    /**
     * 對應onResume、對應onPause
     *
     * @param hasWindowFocus
     */
    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {

        super.onWindowFocusChanged(hasWindowFocus);

        if (hasWindowFocus) {
            //            對應onResume
            MAPVIEW.onResume();
        } else {
            //對應onPause
            MAPVIEW.onPause();

        }

    }

    /**
     * 定位到裝置定位位置
     */
    public void startLocation() {
        startTime = System.currentTimeMillis();
        Log.i("Test", "startTime:" + startTime);
        if (mlocationClient == null) {
            Log.i("Test", "mlocationClient = null");
            mlocationClient = new AMapLocationClient(reactContext);

            mLocationOption = new AMapLocationClientOption();
            //設定定位監聽
            //            mlocationClient.setLocationListener(this);
            //設定為高精度定位模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            mLocationOption.setOnceLocation(true);
            //            mLocationOption.setOnceLocationLatest(true);
            mLocationOption.setLocationCacheEnable(true);//定位緩存政策
            //            mLocationOption.setInterval(10);
            //            mLocationOption.setInterval(3*60*1000);
            //設定定位參數
            mlocationClient.setLocationOption(mLocationOption);

            // 此方法為每隔固定時間會發起一次定位請求,為了減少電量消耗或網絡流量消耗,
            // 注意設定合适的定位時間的間隔(最小間隔支援為2000ms),并且在合适時間調用stopLocation()方法來取消定位請求
            // 在定位結束後,在合适的生命周期調用onDestroy()方法
            // 在單次定位情況下,定位無論成功與否,都無需調用stopLocation()方法移除請求,定位sdk内部會移除

        }
        mlocationClient.startLocation();
    }

    /**
     * 激活定位
     */
    @Override
    public void activate(OnLocationChangedListener listener) {
        mListener = listener;
        if (mlocationClient == null) {
            mlocationClient = new AMapLocationClient(reactContext);
            mLocationOption = new AMapLocationClientOption();
            //設定定位監聽
            //            mlocationClient.setLocationListener(this);
            //設定為高精度定位模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //設定定位參數
            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 onLocationChanged(AMapLocation amapLocation) {
    //        if (amapLocation != null) {
    //            if (amapLocation.getErrorCode() == 0) {
    //                //定位成功回調資訊,設定相關消息
    //                amapLocation.getLocationType();//擷取目前定位結果來源,如網絡定位結果,詳見定位類型表
    //                amapLocation.getLatitude();//擷取緯度
    //                amapLocation.getLongitude();//擷取經度
    //                amapLocation.getAccuracy();//擷取精度資訊
    //                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //                Date date = new Date(amapLocation.getTime());
    //                df.format(date);//定位時間
    //                mListener.onLocationChanged(amapLocation);// 顯示系統小藍點
    //
    //                LatLng location = new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude());
    //                if (!mFirstFix) {
    //                    mFirstFix = true;
    //                    addCircle(location, amapLocation.getAccuracy());//添加定位精度圓
    //                    addMarker(location);//添加定位圖示
    //                    mSensorHelper.setCurrentMarker(mLocMarker);//定位圖示旋轉
    //                } else {
    //                    mCircle.setCenter(location);
    //                    mCircle.setRadius(amapLocation.getAccuracy());
    //                    mLocMarker.setPosition(location);
    //                }
    //                aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 18));
    //            } else {
    //                //顯示錯誤資訊ErrCode是錯誤碼,errInfo是錯誤資訊,詳見錯誤碼表。
    //                Log.e("定位失敗", "location Error, ErrCode:"
    //                        + amapLocation.getErrorCode() + ", errInfo:"
    //                        + amapLocation.getErrorInfo());
    //            }
    //        }
    //    }

    @Override
    public void onMyLocationChange(Location location) {
        // 定位回調監聽
        if (location != null) {
            Log.e("amap", "onMyLocationChange 定位成功, lat: " + location.getLatitude() + " lon: " + location.getLongitude());
            Bundle bundle = location.getExtras();
            if (bundle != null) {
                int errorCode = bundle.getInt(MyLocationStyle.ERROR_CODE);
                String errorInfo = bundle.getString(MyLocationStyle.ERROR_INFO);
                // 定位類型,可能為GPS WIFI等,具體可以參考官網的定位SDK介紹
                int locationType = bundle.getInt(MyLocationStyle.LOCATION_TYPE);

                /*
                errorCode
                errorInfo
                locationType
                */
                Log.e("amap", "定位資訊, code: " + errorCode + " errorInfo: " + errorInfo + " locationType: " + locationType);
            } else {
                Log.e("amap", "定位資訊, bundle is null ");

            }

        } else {
            Log.e("amap", "定位失敗");
        }
    }

    @Deprecated
    private void addCircle(LatLng latlng, double radius) {
        CircleOptions options = new CircleOptions();
        options.strokeWidth(f);
        options.fillColor(FILL_COLOR);
        options.strokeColor(STROKE_COLOR);
        options.center(latlng);
        options.radius(radius);
        mCircle = aMap.addCircle(options);
    }

    @Deprecated
    private void addMarker(LatLng latlng) {
        if (mLocMarker != null) {
            return;
        }
        Bitmap bMap = BitmapFactory.decodeResource(this.getResources(),
                R.drawable.navi_map_gps_locked);
        BitmapDescriptor des = BitmapDescriptorFactory.fromBitmap(bMap);

        //      BitmapDescriptor des = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps_locked);
        MarkerOptions options = new MarkerOptions();
        options.icon(des);
        options.anchor(f, f);
        options.position(latlng);
        mLocMarker = aMap.addMarker(options);
        mLocMarker.setTitle("我的位置");
    }

    /**
     * 初始化定位的小藍點
     */
    private void initBluePoint() {
        MyLocationStyle myLocationStyle = new MyLocationStyle();//初始化定位藍點樣式類
        //設定預設定位按鈕是否顯示,非必需設定。
        aMap.getUiSettings().setMyLocationButtonEnabled(true);

        // 設定為true表示啟動顯示定位藍點,false表示隐藏定位藍點并不進行定位,預設是false。
        // 不知道為什麼它會一直回到目前位置
        aMap.setMyLocationEnabled(true);
        //隻定位一次。
        //        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        //定位一次,且将視角移動到地圖中心點。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
        //連續定位、且将視角移動到地圖中心點,定位藍點跟随裝置移動。(1秒1次定位)
        //        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW) ;
        //連續定位、且将視角移動到地圖中心點,地圖依照裝置方向旋轉,定位點會跟随裝置移動。(1秒1次定位)
        //        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE);
        //連續定位、且将視角移動到地圖中心點,定位點依照裝置方向旋轉,并且會跟随裝置移動。(1秒1次定位)預設執行此種模式。
        //        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);

        //設定連續定位模式下的定位間隔,隻在連續定位模式下生效,單次定位模式下不會生效。機關為毫秒。
        myLocationStyle.interval();
        // 自定義定位藍點圖示
        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.
                fromResource(R.drawable.gps_point));
        // 自定義精度範圍的圓形邊框顔色
        myLocationStyle.strokeColor(STROKE_COLOR);
        //自定義精度範圍的圓形邊框寬度
        myLocationStyle.strokeWidth();
        // 設定圓形的填充顔色
        myLocationStyle.radiusFillColor(FILL_COLOR);
        //        myLocationStyle.anchor(float u, float v);//設定定位藍點圖示的錨點方法。
        aMap.setMyLocationStyle(myLocationStyle);//設定定位藍點的Style

    }

    /**
     * 對單擊地圖事件回調
     */
    @Override
    public void onMapClick(LatLng point) {
        Log.d("tapped, point", point.toString());
        WritableMap event = Arguments.createMap();
        event.putString("LatLng", point.toString());

    }

    /**
     * 對長按地圖事件回調
     */
    @Override
    public void onMapLongClick(LatLng point) {
        Log.d("long pressed, point", point.toString());
    }

    /**
     * 對正在移動地圖事件回調
     */
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        Log.d("onCameraChange:", cameraPosition.toString());
        //大頭針跳動動畫
        MarkerUtil.startJumpAnimation(aMap, screenPosition, reactContext);
        LatLonPoint lp = new LatLonPoint(cameraPosition.target.latitude, cameraPosition.target.longitude);
        PoiSearchBiz poiSearchBiz = new PoiSearchBiz(reactContext, null);
        poiSearchBiz.doSearchQuery("key", "", , , lp, null, null);
    }

    /**
     * 對移動地圖結束事件回調
     */
    @Override
    public void onCameraChangeFinish(CameraPosition cameraPosition) {
        Log.d("onCameraChangeFinish", cameraPosition.toString());

    }


    /**
     * 根據動畫按鈕狀态,調用函數animateCamera或moveCamera來改變可視區域
     */
    public void changeCamera(CameraUpdate update) {

        aMap.moveCamera(update);

    }


    /**
     * 對marker标注點點選響應事件
     */
    @Override
    public boolean onMarkerClick(final Marker marker) {
        Log.d("marker标注點點選響應事件", marker.getTitle());
        return false;
    }


    /**
     * 監聽點選infowindow視窗事件回調
     */
    @Override
    public void onInfoWindowClick(Marker marker) {
        Log.d("監聽點選infowindow視窗事件回調", "你點選了infoWindow視窗" + marker.getTitle());
    }

    /**
     * 監聽拖動marker時事件回調
     */
    @Override
    public void onMarkerDrag(Marker marker) {
        Log.d(marker.getTitle() + "拖動時目前位置", "(lat,lng)\n("
                + marker.getPosition().latitude + ","
                + marker.getPosition().longitude + ")");
    }

    /**
     * 監聽拖動marker結束事件回調
     */
    @Override
    public void onMarkerDragEnd(Marker marker) {
        Log.d("監聽拖動marker結束事件回調", marker.getTitle() + "停止拖動");
    }

    /**
     * 監聽開始拖動marker事件回調
     */
    @Override
    public void onMarkerDragStart(Marker marker) {
        Log.d("監聽開始拖動marker事件回調", "開始拖動");
    }


    /**
     * 監聽自定義infowindow視窗的infocontents事件回調
     */
    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }

    /**
     * 監聽自定義infowindow視窗的infowindow事件回調
     */
    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }


}
           

AMapViewManager

代碼注解

  • 監聽view的listener
@Nullable
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        Map<String, Map<String, String>> map = new HashMap<>();
        //mapBuilder.put("Android裡面的方法名", MapBuilder.of("registrationName", "JS端的方法名"));
        //Android裡面的方法名類似于廣播的action
        map.put("onMapInitialed", MapBuilder.of("registrationName", "onMapInitialed"));
        return map;
    }
           

viewManager如何被外部的js調用的

  1. viewManager通過Module來暴露方法
  2. 通過屬性的更新來調用
/**
     * 設定線路規劃參數
     */
    @ReactProp(name = "drivingRoutePlan")
    @SuppressWarnings("unused")
    public void setDrivingRoutePlan(MyAMapView myAMapView, ReadableMap drivingRoutePlan) {
        try {
            double latitude = drivingRoutePlan.getDouble("latitude");
            double longitude = drivingRoutePlan.getDouble("longitude");
            int mode = drivingRoutePlan.getInt("mode");
            DriveRouteBiz driveRouteBiz = new DriveRouteBiz(reactContext, myAMapView);
            driveRouteBiz.searchRouteResult(ROUTE_TYPE_DRIVE, mode, latitude, longitude);
        } catch (NoSuchKeyException e) {
        }
    }
           

error

  1. 屬性不能更新

    js代碼沒問題,請檢查被調用的android方法是否有空指針

代碼

package com.aiyunbao;

import android.support.annotation.Nullable;

import com.aiyunbao.aMap.MyAMapView;
import com.aiyunbao.route.DriveRouteBiz;
import com.amap.api.maps.CameraUpdateFactory;
import com.facebook.react.bridge.NoSuchKeyException;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;

import java.util.HashMap;
import java.util.Map;

import static com.aiyunbao.route.DriveRouteBiz.ROUTE_TYPE_DRIVE;
import static com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_CENTER;
import static com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_LEFT;
import static com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_RIGHT;


/**
 * Created by aiyun-pc1 on 2017/5/8.
 * 普通地圖view,提供定位 poi搜尋 位址轉碼 marker标記
 */

public class AMapViewManager extends ViewGroupManager<MyAMapView> {


    private static ReactApplicationContext reactContext;

    private Map<String, Object> constants;

    public AMapViewManager(ReactApplicationContext reactContext) {
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "RCTAMapView";
    }

    @Override
    protected MyAMapView createViewInstance(ThemedReactContext reactContext) {
        setConstants();
        MyAMapView view = new MyAMapView(reactContext);
        return view;
    }


    public void setConstants() {
        constants = new HashMap<>();
        //Logo的位置
        constants.put("LOGO_POSITION_BOTTOM_LEFT", LOGO_POSITION_BOTTOM_LEFT);
        constants.put("LOGO_POSITION_BOTTOM_CENTER", LOGO_POSITION_BOTTOM_CENTER);
        constants.put("LOGO_POSITION_BOTTOM_RIGHT", LOGO_POSITION_BOTTOM_RIGHT);
    }


    /**
     * 是否顯示使用者目前位置(預設為開啟)
     */
    @ReactProp(name = "showsUserLocation", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setShowsUserLocation(MyAMapView myAMapView, Boolean showsUserLocation) {
        // 設定為true表示啟動顯示定位藍點,false表示隐藏定位藍點并不進行定位,
        myAMapView.getAmap().setMyLocationEnabled(showsUserLocation);
    }
    //
    //    @ReactProp(name = "userLocationRepresentation", defaultBoolean = true)
    //    @SuppressWarnings("unused")
    //    public void setUserLocationRepresentation(MyAMapView myAMapView, Boolean userLocationRepresentation) {
    //
    //    }

    /**
     * 跟随模式
     */
    @ReactProp(name = "userTrackingMode", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setUserTrackingMode(MyAMapView myAMapView, Boolean userTrackingMode) {

    }

    /**
     * logo
     * //Logo的位置
     * 左下:LOGO_POSITION_BOTTOM_LEFT
     * 底部居中:LOGO_POSITION_BOTTOM_CENTER
     * 右下:LOGO_POSITION_BOTTOM_RIGHT
     */
    @ReactProp(name = "logoCenterAndroid")
    @SuppressWarnings("unused")
    public void setLog(MyAMapView myAMapView, String logoCenterAndroid) {
        myAMapView.getAmap().getUiSettings().setLogoPosition((Integer) constants.get(logoCenterAndroid));
    }

    /**
     * 比例尺
     */
    @ReactProp(name = "showsScale")
    @SuppressWarnings("unused")
    public void setShowsScale(final MyAMapView myAMapView, final Boolean showsScale) {
        //控制比例尺控件是否顯示
        myAMapView.getAmap().getUiSettings().setScaleControlsEnabled(showsScale);
    }

    /**
     * 縮放手勢
     */
    @ReactProp(name = "zoomEnabled", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setZoomEnabled(MyAMapView myAMapView, Boolean zoomEnabled) {
        myAMapView.getAmap().getUiSettings().setZoomGesturesEnabled(zoomEnabled);
    }

    /**
     * 滑動手勢
     */
    @ReactProp(name = "scrollEnabled", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setScrollEnabled(MyAMapView myAMapView, Boolean scrollEnabled) {
        myAMapView.getAmap().getUiSettings().setScrollGesturesEnabled(scrollEnabled);
    }

    /**
     * 旋轉手勢
     */
    @ReactProp(name = "rotateEnabled", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setRotateEnabled(MyAMapView myAMapView, Boolean rotateEnabled) {
        myAMapView.getAmap().getUiSettings().setRotateGesturesEnabled(rotateEnabled);
    }

    /**
     * 傾斜手勢
     */
    @ReactProp(name = "rotateCameraEnabled", defaultBoolean = true)
    @SuppressWarnings("unused")
    public void setRotateCameraEnabled(MyAMapView myAMapView, Boolean rotateCameraEnabled) {
        myAMapView.getAmap().getUiSettings().setTiltGesturesEnabled(rotateCameraEnabled);
    }

    /**
     * 縮放級别
     */
    @ReactProp(name = "zoomLevel")
    @SuppressWarnings("unused")
    public void setZoomLevel(MyAMapView myAMapView, float zoomLevel) {
        myAMapView.getAmap().moveCamera(CameraUpdateFactory.zoomTo(zoomLevel));
    }

    /**
     * 設定中心大頭針
     */
    @ReactProp(name = "startAnnotation")
    @SuppressWarnings("unused")
    public void setStartAnnotation(MyAMapView myAMapView, ReadableMap startAnnotation) {

    }

    /**
     *
     */
    @ReactProp(name = "destinationAnnotation")
    @SuppressWarnings("unused")
    public void setDestinationAnnotation(MyAMapView myAMapView, ReadableMap destinationAnnotation) {

    }

    /**
     * 設定線路規劃參數
     */
    @ReactProp(name = "drivingRoutePlan")
    @SuppressWarnings("unused")
    public void setDrivingRoutePlan(MyAMapView myAMapView, ReadableMap drivingRoutePlan) {
        try {
            double latitude = drivingRoutePlan.getDouble("latitude");
            double longitude = drivingRoutePlan.getDouble("longitude");
            int mode = drivingRoutePlan.getInt("mode");
            DriveRouteBiz driveRouteBiz = new DriveRouteBiz(reactContext, myAMapView);
            driveRouteBiz.searchRouteResult(ROUTE_TYPE_DRIVE, mode, latitude, longitude);
        } catch (NoSuchKeyException e) {
        }
        /**
         * {
         latitude: PropTypes.number,
         longitude: PropTypes.number,
         waypoints: PropTypes.arrayOf(PropTypes.shape(

         )),
         strategy: PropTypes.number,
         startPlan: PropTypes.bool,
         mode: PropTypes.number

         }
         */
    }

    //
    //    context.getJSModule(RCTEventEmitter.class).receiveEvent(id, "Android裡面的方法名",map);

    //    某方法(value){    alert('收到!');}
    //    render() {
    //        return (
    //                <View style={styles.container}>
    //        <MyWidget  style={styles.welcome
    //                JS端的方法名={this.某方法.bind(this)}>      </MyWidget>    </View>  );}
    @Nullable
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        Map<String, Map<String, String>> map = new HashMap<>();
        //mapBuilder.put("Android裡面的方法名", MapBuilder.of("registrationName", "JS端的方法名"));
        map.put("onMapInitialed", MapBuilder.of("registrationName", "onMapInitialed"));
        map.put("onRegionChange", MapBuilder.of("registrationName", "onRegionChange"));
        map.put("onRegionChangeComplete", MapBuilder.of("registrationName", "onRegionChangeComplete"));
        map.put("onDrivingRoutePlanComplete", MapBuilder.of("registrationName", "onDrivingRoutePlanComplete"));
        map.put("onDrivingRoutePlanFailed", MapBuilder.of("registrationName", "onDrivingRoutePlanFailed"));
        map.put("onRegionChangeCompleteWithReGeoResult", MapBuilder.of("registrationName", "onRegionChangeCompleteWithReGeoResult"));
        map.put("onRegionChangeCompleteWithReGeoResultFailed", MapBuilder.of("registrationName", "onRegionChangeCompleteWithReGeoResultFailed"));
        map.put("onFailToLocateUser", MapBuilder.of("registrationName", "onFailToLocateUser"));
        return map;
    }


    /**
     *
     * @param id viewId
     * @param eventName Android原生事件名
     * @param event 傳回的參數
     */
    public static void sendEvent(int id, String eventName, @Nullable WritableMap event) {
        reactContext.getJSModule(RCTEventEmitter.class)
                .receiveEvent(id, eventName, event);
    }
}
           

AMapModule

代碼注解

  • 幫助viewManager暴露一下方法給外部js使用
/**
     * 跳轉到指定的位置
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void changeCamera(int tag, ReadableMap readableMap) {
        mapView = ((MyAMapView) reactContext.getCurrentActivity().findViewById(tag));
        LatLng latLng = new LatLng(readableMap.getDouble(longitude), readableMap.getDouble(latitude));
        mapView.changeCamera(
                CameraUpdateFactory.newCameraPosition(new CameraPosition(latLng
                        , , , )));
        MarkerUtil.addMarkersToMap(mapView.getAmap(), latLng, "title", "");
    }
           
  • tag為js傳過來的id

    findNodeHandle(this) 傳遞View Id給RN module

mapView = ((MyAMapView) reactContext.getCurrentActivity().findViewById(tag));
           

代碼

package com.aiyunbao;

import android.app.Activity;
import android.content.Intent;

import com.aiyunbao.Geocoder.GeocoderBiz;
import com.aiyunbao.aMap.MyAMapView;
import com.aiyunbao.activty.DirveNaviActivity;
import com.aiyunbao.location.LocationBiz;
import com.aiyunbao.marker.MarkerUtil;
import com.aiyunbao.poi.PoiSearchBiz;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.poisearch.PoiSearch;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;

/**
 * Created by aiyun-pc1 on 2017/5/9.
 *
 */

public class AMapModule extends ReactContextBaseJavaModule {

    private ReactApplicationContext reactContext;

    private MyAMapView mapView;

    private final String longitude = "lng";
    private final String latitude = "lat";
    //poi搜尋
    private PoiSearch.Query query;
    private PoiSearch poiSearch;
    private PoiSearchBiz poiSearchBiz;
    //地理編碼
    private GeocoderBiz geocoderBiz;


    public AMapModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "AMap";
    }


    private void setMyAMapView(int tag) {
        if (mapView == null) {
            mapView = ((MyAMapView) reactContext.getCurrentActivity().findViewById(tag));
        }
    }

    private void setGeocoderBiz() {
        if (geocoderBiz == null) {
            geocoderBiz = new GeocoderBiz(reactContext);
        }
    }

    /**
     * 跳轉到指定的位置
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void changeCamera(int tag, ReadableMap readableMap) {
        mapView = ((MyAMapView) reactContext.getCurrentActivity().findViewById(tag));
        LatLng latLng = new LatLng(readableMap.getDouble(longitude), readableMap.getDouble(latitude));
        mapView.changeCamera(
                CameraUpdateFactory.newCameraPosition(new CameraPosition(latLng
                        , , , )));
        MarkerUtil.addMarkersToMap(mapView.getAmap(), latLng, "title", "");
    }


    /**
     * 在地圖上添加marker
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void addMarkersToMap(int tag, ReadableMap readableMap) {
        setMyAMapView(tag);
        LatLng latLng = new LatLng(readableMap.getDouble(longitude), readableMap.getDouble(latitude));
        MarkerUtil.addMarkersToMap(mapView.getAmap(), latLng);
    }

    /**
     * 在地圖上添加marker,并繪制地圖上的資訊視窗
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void addMarkersWithInfoToMap(int tag, ReadableMap readableMap, String title, String detail) {
        setMyAMapView(tag);
        LatLng latLng = new LatLng(readableMap.getDouble(longitude), readableMap.getDouble(latitude));
        MarkerUtil.addMarkersToMap(mapView.getAmap(), latLng, title, detail);
    }

    /**
     * 清空地圖上所有已經标注的marker
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void clearAllMarker(int tag) {
        setMyAMapView(tag);
        MarkerUtil.clearMarker(mapView.getAmap());
    }

    /**
     * 開始進行poi搜尋
     *
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void getPOISearchResult(ReadableMap params, Callback result, Callback error) {
        /**
         *  {
         //         keywords: "武侯祠",
         //         city: "成都",
         //         offset: 10,
         //     },
         */
        String keywords = params.getString("keywords");
        String city = params.getString("city");
        double latitude = ;
        double longitude = ;
        int radius = ;
        int pageSize = params.getInt("offset");
        LatLonPoint latLonPoint = new LatLonPoint(latitude, longitude);
        if (poiSearchBiz == null)
            poiSearchBiz = new PoiSearchBiz(reactContext, mapView);
        poiSearchBiz.doSearchQuery(keywords, city, pageSize, radius, latLonPoint, result, error);
    }


    /**
     * 開始進行poi搜尋
     *
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void getPOIAroundSearchResult(ReadableMap params, Callback result, Callback error) {
        /**
         *   keywords: "天府廣場",
         //         city: "成都",
         //         latitude: 30.648623,
         //         longitude: 104.040568,
         //         radius: 3000
         */
        String keywords = params.getString("keywords");
        String city = params.getString("city");
        double latitude = params.getDouble("latitude");
        double longitude = params.getDouble("longitude");
        int radius = params.getInt("radius");
        int pageSize = ;
        LatLonPoint latLonPoint = new LatLonPoint(latitude, longitude);
        if (poiSearchBiz == null)
            poiSearchBiz = new PoiSearchBiz(reactContext, mapView);
        poiSearchBiz.doSearchQuery(keywords, city, pageSize, radius, latLonPoint, result, error);
    }



    /**
     * 跳轉到指定的poi結果頁中
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void selectPoiPage(int page, Callback callback) {
        if (poiSearchBiz != null) {
            poiSearchBiz.selectPoiPage(page, callback);
        } else {
            callback.invoke("請先使用poi查詢再跳轉指定的結果頁");
        }
    }

    /**
     * poi搜尋自動提示
     *
     * @param newText
     * @param city        傳入null或者“”代表在全國進行檢索,否則按照傳入的city進行檢索
     * @param tipCallback
     */
    @ReactMethod
    @SuppressWarnings("unused")
    public void poiInputTip(int tag, String newText, String city, Callback tipCallback) {
        setMyAMapView(tag);
        poiSearchBiz = new PoiSearchBiz(reactContext, mapView);
        poiSearchBiz.poiInputTip(newText, city, tipCallback);
    }

//    @ReactMethod
//    @SuppressWarnings("unused")
//    public void searchRouteResult(int tag) {
//        setMyAMapView(tag);
//        DriveRouteBiz driveRouteBiz = new DriveRouteBiz(reactContext, mapView);
//        driveRouteBiz.searchRouteResult(ROUTE_TYPE_DRIVE, RouteSearch.DrivingDefault);
//    }

    @ReactMethod
    @SuppressWarnings("unused")
    public void driveNavi(int tag) {
        try {
            Activity currentActivity = getCurrentActivity();
            if (null != currentActivity) {
                Intent intent = new Intent(currentActivity, DirveNaviActivity.class);
                intent.putExtra("data", "data");
                currentActivity.startActivity(intent);
            }
        } catch (Exception e) {
            throw new JSApplicationIllegalArgumentException(
                    "Could not open the activity : " + e.getMessage());
        }
    }

    @ReactMethod
    @SuppressWarnings("unused")
    public void startLocationOneTime(Boolean isOnceLocation, Callback callback, Callback error) {
        LocationBiz locationBiz = new LocationBiz(reactContext);
        locationBiz.startLocation(isOnceLocation, callback, error);
    }

    @ReactMethod
    @SuppressWarnings("unused")
    public void getGeoCoding(String name, Callback callback) {
        setGeocoderBiz();
        geocoderBiz.getGeoCoding(name, callback);
    }

    @ReactMethod
    @SuppressWarnings("unused")
    public void getReGeoCoding(double lat, double lng, Callback callback) {
        setGeocoderBiz();
        geocoderBiz.getReGeoCoding(lat, lng, callback);
    }

    @ReactMethod
    public void startLocationOneTime() {

    }

}
           

AMapPackage

package com.aiyunbao;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Created by aiyun-pc1 on 2017/5/8.
 */

public class AMapPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(
                new AMapModule(reactContext)
        );
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
                new AMapViewManager(reactContext),
                new ANaviMapViewManager(reactContext)
        );
    }
}
           

MainApplication

package com.aiyunbao;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {


    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    new AMapPackage()
            );
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}
           

js代碼

/**
 * Created by aiyun-pc1 on 2017/5/8.
 */

import React, {Component, PropTypes} from 'react';
import {
  NativeAppEventEmitter,
  NativeModules,
  Platform,
  StyleSheet,
  requireNativeComponent,
  View,
  findNodeHandle,

} from 'react-native';

const MapManager = NativeModules.AMapModuleAndroid;
const MapView = requireNativeComponent('RCTAMapView', AMapViewTest);

export default class AMapViewTest extends Component {


  static propTypes = {

    ...View.propTypes, // 包含預設的View的屬性
    LatLng: PropTypes.object,
    PAGESIZE: PropTypes.number,
    RADIUS: PropTypes.number,
    QUERYTYPE: PropTypes.string,
    UISETTING: PropTypes.object,
    onPoiSearch: PropTypes.func.isRequired,
    onMapViewCenterChangeFinish: PropTypes.func,
    onMapInitialed: PropTypes.func
  };

  static defaultProps = {};
  _onMapInitialed = (event) => {
    if (!this.props.onMapInitialed) {
      return;
    }
    this.props.onMapInitialed(event.nativeEvent);
  };

  render() {
    return (
      <MapView
        {...this.props}
        onMapInitialed={this._onMapInitialed}
      />

    );
  }


  // findNodeHandle(this) 傳遞View Id給RN module

  // getCenterLocation() {
  //     MapManager.getCenterLocation(findNodeHandle(this))
  // }

  /**
   * 39.90403, 116.407525 // 北京市經緯度
   39.983456, 116.3154950// 北京市中關村經緯度
   31.238068, 121.501654 // 上海市經緯度
   39.989614, 116.481763 // 方恒國際中心經緯度
   30.679879, 104.064855 // 成都市經緯度
   34.341568, 108.940174 // 西安市經緯度
   34.7466, 113.625367 // 鄭州市經緯度
   * @constructor
   */
  testMapMethod() {
    let latlng = {
      'lng': 34.7466,
      'lat': 113.625367
    };
    let latlng1 = {
      'lng': 34.341568,
      'lat': 108.940174
    };
    let latlng2 = {
      'lng': 30.679879,
      'lat': 104.064855
    };
    let latlng3 = {
      'lng': 39.989614,
      'lat': 116.481763
    };
    // MapManager.test(findNodeHandle(this));
    // MapManager.changeCamera(findNodeHandle(this), latlng);
    // MapManager.addMarkersWithInfoToMap(findNodeHandle(this), latlng, '鄭州市經緯度', '鄭州市經緯度');
    // MapManager.addMarkersWithInfoToMap(findNodeHandle(this), latlng1, '西安市經緯度', '西安市經緯度');
    // MapManager.addMarkersWithInfoToMap(findNodeHandle(this), latlng2, '成都市經緯度', '成都市經緯度');
    // MapManager.addMarkersToMap(findNodeHandle(this), latlng3);
    MapManager.driveNavi(findNodeHandle(this));

  }

  /**
   * 開始進行poi搜尋
   * @param keyWord
   * @param area 地區可以傳空字元,空字元代表全國
   * @param pageSize
   */
  searchPoi(keyWord, area, pageSize) {
    MapManager.searchPoi(findNodeHandle(this), keyWord, area, pageSize);
  }

  /**
   * 跳轉到指定的poi結果頁中
   * @param page
   * @param callback
   */
  selectPoiPage(page, callback) {
    MapManager.selectPoiPage(page, callback);
  }

  /**
   * poi搜尋自動提示
   * @param newText
   * @param city 傳入null或者“”代表在全國進行檢索,否則按照傳入的city進行檢索
   * @param callback
   */
  poiInputTip(newText, city, callback) {
    MapManager.poiInputTip(findNodeHandle(this), newText, city, callback);
  }

  searchRouteResult() {
    MapManager.searchRouteResult(findNodeHandle(this));
  }

  startSmoothMove() {
    MapManager.startSmoothMove(findNodeHandle(this));
  }


}

           
react native android 高德地圖原生代碼編寫react native android 高德地圖原生代碼編寫
react native android 高德地圖原生代碼編寫react native android 高德地圖原生代碼編寫
  • 以上代碼并不是最終修訂版,還有一些原生的高德地圖類沒上傳 如果需要幫助可以在文章中回複我

參考了以下大神的部落格

1. http://blog.csdn.net/qq_20738965/article/details/53363142