react-native 原生封装地图组件,rn调用

本文详细介绍了如何在React Native应用中封装并调用原生Android和iOS的地图组件,实现rn组件与原生平台的完美结合,提供地图功能。

1.rn组件

/* @flow*/
import React from 'react'
import { requireNativeComponent } from 'react-native'

const RCTMap = requireNativeComponent('MAMapView', null)

type propTypes = {
    data:any
};

function AMapView(props:propTypes) {
  return (<RCTMap {...props} />)
}

export default AMapView

2 原生android

package com.kuaibao.skuaidi.react.modules.map;

import android.content.Context;

import com.amap.api.maps2d.MapView;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;

/**
 * Created by kit on 16/12/15.
 */
public class MAMapView extends MapView implements LifecycleEventListener{
    public MAMapView(Context context) {
        super(context);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        onCreate(null);
        ((ReactContext)getContext()).addLifecycleEventListener(this);

//        ViewGroup child = (ViewGroup) getChildAt(0);
//        com.amap.api.mapcore2d.b b = (com.amap.api.mapcore2d.b) child.getChildAt(0);
//        com.amap.api.mapcore2d.aa aa = b.j.e();
//        try {
//            b.a(aa);
//        } catch (RemoteException e) {
//            e.printStackTrace();
//        }

    }

    @Override
    protected void onDetachedFromWindow() {
        ((ReactContext)getContext()).removeLifecycleEventListener(this);
        super.onDetachedFromWindow();
        onDestroy();
    }

    @Override
    public void onHostResume() {
        onResume();
    }

    @Override
    public void onHostPause() {
        onPause();
    }

    @Override
    public void onHostDestroy() {
        onDestroy();
    }
}
package com.kuaibao.skuaidi.react.modules.map;

import android.content.Context;

import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.overlay.WalkRouteOverlay;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkPath;
import com.amap.api.services.route.WalkRouteResult;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.kuaibao.skuaidi.activity.picksendmapmanager.utils.ToastUtil;
import com.kuaibao.skuaidi.util.Utility;

/**
 * Created by kit on 16/12/15.
 */
public class MapViewManager extends SimpleViewManager<MAMapView>{

  private Context mContext;
  private RouteSearch mRouteSearch;

  /**
     * @return the name of this view manager. This will be the name used to reference this view
     * manager from JavaScript in createReactNativeComponentClass.
     */
    @Override
    public String getName() {
        return "MAMapView";
    }




    /**
     * Subclasses should return a new View instance of the proper type.
     *
     * @param reactContext
     */
    @Override
    protected MAMapView createViewInstance(ThemedReactContext reactContext) {
        mContext = reactContext;
        return new MAMapView(reactContext);
    }
    @ReactProp(name="data")
    public void data(MAMapView mapView , ReadableArray data){
       // ReadableArray data = data.
//        MarkerOptions markerOption = new MarkerOptions();
        ReadableMap startLocation = data.getMap(0);
        ReadableMap endLocation = data.getMap(1);

        if (Utility.isEmpty(startLocation.getString("latitude")) || Utility.isEmpty(endLocation.getString("latitude"))) return;

      double startLatitude = Double.valueOf(startLocation.getString("latitude")) ;
      double startLongitude = Double.valueOf(startLocation.getString("longitude"));
//        String startName = endLocation.getString("name");

      double endLatitude = Double.valueOf(endLocation.getString("latitude")) ;
      double endLongitude = Double.valueOf(endLocation.getString("longitude"));
//        String endName = endLocation.getString("name");



      LatLonPoint startLat = new LatLonPoint(startLatitude,startLongitude);
      LatLonPoint endLat = new LatLonPoint(endLatitude,endLongitude);

//      AMapUtil.convertToLatLng();

      LatLng startLat1 = new LatLng(startLatitude, startLongitude);
//      LatLng endLat1 = new LatLng(endLongitude, endLatitude);

      AMap aMap = mapView.getMap();//得到aMap对象
         //   LatLng latLng = new LatLng(45.71701,126.64256);//构造一个位置
      aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startLat1,11));

      mRouteSearch = new RouteSearch(mContext);

      final RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startLat, endLat);

      RouteSearch.WalkRouteQuery query = new RouteSearch.WalkRouteQuery(fromAndTo);

      mRouteSearch.calculateWalkRouteAsyn(query);

      mRouteSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
        @Override
        public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

        }

        @Override
        public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {

        }

        @Override
        public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {
          mapView.getMap().clear();
          if (i == AMapException.CODE_AMAP_SUCCESS) {
            if (walkRouteResult != null && walkRouteResult.getPaths() != null) {
              if (walkRouteResult.getPaths().size() > 0) {
//                RideRouteOverlay rideRouteOverlay = new RideRouteOverlay(this, aMap, ridePath, start, end);
//                rideRouteOverlay.removeFromMap();
//                rideRouteOverlay.addToMap();
//                rideRouteOverlay.zoomToSpan();

                //                RideRouteOverlay rideRouteOverlay = new RideRouteOverlay(this, aMap, ridePath, start, end);
                //                rideRouteOverlay.removeFromMap();
                //                rideRouteOverlay.addToMap();
                //                rideRouteOverlay.zoomToSpan();
                //                mWalkRouteResult = result;
                final WalkPath walkPath = walkRouteResult.getPaths()
                  .get(0);
                WalkRouteOverlay walkRouteOverlay = new WalkRouteOverlay(
                  mContext, mapView.getMap(), walkPath,
                  walkRouteResult.getStartPos(),
                  walkRouteResult.getTargetPos());

                walkRouteOverlay.removeFromMap();
                walkRouteOverlay.addToMap();
                walkRouteOverlay.zoomToSpan();
                walkRouteOverlay.setNodeIconVisibility(false);
//                mBottomLayout.setVisibility(View.VISIBLE);
//                int dis = (int) walkPath.getDistance();
//                int dur = (int) walkPath.getDuration();
//                String des = AMapUtil.getFriendlyTime(dur) + "(" + AMapUtil.getFriendlyLength(dis) + ")";
//                mRotueTimeDes.setText(des);
//                mRouteDetailDes.setVisibility(View.GONE);
//                mBottomLayout.setOnClickListener(new View.OnClickListener() {
//                  @Override
//                  public void onClick(View v) {
//                    //显示详细的路径,怎么走 走多少米往哪个方向走等
//                    Intent intent = new Intent(mContext,
//                      WalkRouteDetailActivity.class);
//                    intent.putExtra("walk_path", walkPath);
//                    intent.putExtra("walk_result",
//                      mWalkRouteResult);
//                    startActivity(intent);
//                  }
//                });
//              } else if (result != null && result.getPaths() == null) {
//                ToastUtil.showDefaultToast(mContext, R.string.no_result);
//              }
            } /*else {
              ToastUtil.showDefaultToast(mContext, R.string.no_result);
            }*/
          } else {
            ToastUtil.showerror(mContext, i);
          }

        }

      }

        @Override
        public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {

        }});

       /* markerOption.position(lat);
        markerOption.title(name);

        markerOption.draggable(true);
        markerOption.icon(

                BitmapDescriptorFactory.fromBitmap(BitmapFactory
                        .decodeResource(mapView.getResources(),
                                R.mipmap.loc)));
        markerOption.visible(true);
        mapView.getMap().addMarker(markerOption).showInfoWindow();
        mapView.getMap().getUiSettings().setCompassEnabled(false);
        mapView.getMap().getUiSettings().setZoomControlsEnabled(false);
        mapView.getMap().getUiSettings().setScaleControlsEnabled(false);
        mapView.getMap().setMyLocationEnabled(false);
        mapView.getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(lat , 17));*/

    }
}

2 原生ios

//
//  AMapViewManager.m
//  FirstRN
//
//  Created by Kit on 16/12/3.
//  Copyright © 2016年 Facebook. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "KBAMapViewManager.h"
#import <MAMapKit/MAMapKit.h>

@interface KBAMapViewManager()<MAMapViewDelegate,AMapSearchDelegate>

@end
@implementation KBAMapViewManager

RCT_EXPORT_MODULE(MAMapView)

-(UIView *)view
{
    UIWindow *window = [UIApplication sharedApplication].keyWindow ;
    self.mapView =[[MAMapView alloc] initWithFrame:window.rootViewController.view.bounds];
    self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.mapView.delegate = self ;
    self.search = [[AMapSearchAPI alloc] init];
    self.search.delegate = self;
    self.mapView.showsScale=NO ;
    self.mapView.showsCompass=NO ;
    self.mapView.showsUserLocation = YES ;
    self.mapView.zoomLevel = 17 ;
//    self.mapView.allowsBackgroundLocationUpdates = YES;//iOS9以上系统必须配置
    
    //[self.mapView setUserTrackingMode: MAUserTrackingModeFollow animated:YES]; //地图跟着位置移动
    self.pathPolylines = [NSArray array];
    
    return self.mapView ;
}
RCT_EXPORT_METHOD(setMap){
    NSLog(@"setMap ...") ;
    self.mapView.showsScale=YES ;
    
}
RCT_CUSTOM_VIEW_PROPERTY(data , NSString* , MAMapView){
    NSArray *resultArray = [RCTConvert NSArray:json];  //解析
    NSDictionary *startPosition = resultArray[0];
    NSDictionary *endPosition = resultArray[1];
    NSNumber * startLongitude = [startPosition objectForKey:@"longitude"] ;
    NSNumber * startLatitude = [startPosition objectForKey:@"latitude"] ;
    NSNumber * endLongitude = [endPosition objectForKey:@"longitude"] ;
    NSNumber * endLatitude = [endPosition objectForKey:@"latitude"] ;
    struct CLLocationCoordinate2D startLocation ;
    startLocation.latitude = startLatitude.doubleValue;
    startLocation.longitude = startLongitude.doubleValue;
    struct CLLocationCoordinate2D endLocation ;
    endLocation.latitude = endLatitude.doubleValue;
    endLocation.longitude = endLongitude.doubleValue;
    /* NSNumber * longitude = [resultDic objectForKey:@"longitude"] ;
     NSNumber* latitude = [resultDic objectForKey:@"latitude"];
     NSString * name = [resultDic objectForKey:@"name"];
     self.longitude = longitude.doubleValue ;
     self.latitude = latitude.doubleValue ;
     self.name = name ;
     NSLog(@"custom prop =   longitude = %f" ,longitude.doubleValue) ;
     struct CLLocationCoordinate2D location ;
     location.latitude = latitude.doubleValue;
     location.longitude = longitude.doubleValue ;
     [self.mapView setCenterCoordinate:location] ;
     MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
     pointAnnotation.coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude);
     pointAnnotation.title = name ;
     [self.mapView addAnnotation:pointAnnotation];
     [self.mapView selectAnnotation:pointAnnotation animated:NO];*/
    //
    //构造AMapDrivingRouteSearchRequest对象,设置驾车路径规划请求参数
    //初始化检索对象
    
    AMapRidingRouteSearchRequest *request = [[AMapRidingRouteSearchRequest alloc] init];
    //设置起点,我选择了当前位置,mapView有这个属性
    request.origin = [AMapGeoPoint locationWithLatitude:startLocation.latitude longitude:startLocation.longitude];
    //设置终点,可以选择手点
    request.destination = [AMapGeoPoint locationWithLatitude:endLocation.latitude longitude:endLocation.longitude];
    //    request.strategy = 2;//距离优先
    //    request.requireExtension = YES;
    
    //发起路径搜索,发起后会执行代理方法
    //这里使用的是步行路径
    [self.search AMapRidingRouteSearch: request];
    [self.mapView setCenterCoordinate:startLocation] ;
    
}

//实现路径搜索的回调函数
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response
{
    if(response.route == nil)
    {
        return;
    }
    
    //通过AMapNavigationSearchResponse对象处理搜索结果
    NSString *route = [NSString stringWithFormat:@"Navi: %@", response.route];
    
    AMapPath *path = response.route.paths[0]; //选择一条路径
    AMapStep *step = path.steps[0]; //这个路径上的导航路段数组
    NSLog(@"%@",step.polyline);   //此路段坐标点字符串
    
    if (response.count > 0)
    {
        //移除地图原本的遮盖
        [self.mapView removeOverlays:_pathPolylines];
        _pathPolylines = nil;
        
        // 只显⽰示第⼀条 规划的路径
        _pathPolylines = [self polylinesForPath:response.route.paths[0]];
        NSLog(@"%@",response.route.paths[0]);
        //添加新的遮盖,然后会触发代理方法进行绘制
        [self.mapView addOverlays:_pathPolylines];
    }
}

//路线解析
- (NSArray *)polylinesForPath:(AMapPath *)path
{
    if (path == nil || path.steps.count == 0)
    {
        return nil;
    }
    NSMutableArray *polylines = [NSMutableArray array];
    [path.steps enumerateObjectsUsingBlock:^(AMapStep *step, NSUInteger idx, BOOL *stop) {
        NSUInteger count = 0;
        CLLocationCoordinate2D *coordinates = [self coordinatesForString:step.polyline
                                                         coordinateCount:&count
                                                              parseToken:@";"];
        
        
        MAPolyline *polyline = [MAPolyline polylineWithCoordinates:coordinates count:count];
        
        //          MAPolygon *polygon = [MAPolygon polygonWithCoordinates:coordinates count:count];
        
        [polylines addObject:polyline];
        (void)(free(coordinates)), coordinates = NULL;
    }];
    return polylines;
}

#pragma mark -- 大头针和遮盖

//自定义的经纬度和区域
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay
{
    /* 自定义定位精度对应的MACircleView. */
    if (overlay == mapView.userLocationAccuracyCircle)
    {
        MACircleRenderer *accuracyCircleRenderer = [[MACircleRenderer alloc] initWithCircle:overlay];
        
        accuracyCircleRenderer.lineWidth    = 2.f;
        accuracyCircleRenderer.strokeColor  = [UIColor lightGrayColor];
        accuracyCircleRenderer.fillColor    = [UIColor colorWithRed:1 green:0 blue:0 alpha:.3];
        
        return accuracyCircleRenderer;
    }
    
    //画路线
    if ([overlay isKindOfClass:[MAPolyline class]])
    {
        
        MAPolylineRenderer *polygonView = [[MAPolylineRenderer alloc] initWithPolyline:overlay];
        
        polygonView.lineWidth = 8.f;
        //设置填充颜色
        polygonView.fillColor = [UIColor redColor];
        //设置笔触颜色
        polygonView.strokeColor = [UIColor greenColor];
        // polygonView.lineJoinType = kMALineJoinRound;//连接类型
        polygonView.lineCapType = kMALineCapRound;
        return polygonView;
    }
    return nil;
    
}

//解析经纬度
- (CLLocationCoordinate2D *)coordinatesForString:(NSString *)string
                                 coordinateCount:(NSUInteger *)coordinateCount
                                      parseToken:(NSString *)token
{
    if (string == nil)
    {
        return NULL;
    }
    
    if (token == nil)
    {
        token = @",";
    }
    
    NSString *str = @"";
    if (![token isEqualToString:@","])
    {
        str = [string stringByReplacingOccurrencesOfString:token withString:@","];
    }
    
    else
    {
        str = [NSString stringWithString:string];
    }
    
    NSArray *components = [str componentsSeparatedByString:@","];
    NSUInteger count = [components count] / 2;
    if (coordinateCount != NULL)
    {
        *coordinateCount = count;
    }
    CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D*)malloc(count * sizeof(CLLocationCoordinate2D));
    
    for (int i = 0; i < count; i++)
    {
        NSInteger index = 2 * i;
        if (index < components.count) {
            coordinates[i].longitude = [[components objectAtIndex:index] doubleValue];
            if (index + 1 < components.count) {
                coordinates[i].latitude = [[components objectAtIndex:index + 1] doubleValue];
            } else {
                coordinates[i].latitude = 0;
            }
        }
    }
    
    return coordinates;
}

#pragma mark - MAMapViewDelegate
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MAPointAnnotation class]])
    {
        static NSString *reuseIndetifier = @"annotationReuseIndetifier";
        MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
        if (annotationView == nil)
        {
            annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation
                                                          reuseIdentifier:reuseIndetifier];
        }
        
        annotationView.image = [UIImage imageNamed:@"loc"];
        //设置中心点偏移,使得标注底部中间点成为经纬度对应点
        annotationView.centerOffset = CGPointMake(0, -18);
        annotationView.canShowCallout = YES ;
        return annotationView;
    }
    return nil;
}
- (void)mapView:(MAMapView *)mapView didDeselectAnnotationView:(MAAnnotationView *)view{
    
    MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
    pointAnnotation.coordinate = CLLocationCoordinate2DMake( self.latitude, self.longitude);
    pointAnnotation.title = self.name ;
    [self.mapView addAnnotation:pointAnnotation];
    [self.mapView selectAnnotation:pointAnnotation animated:NO];
}
@end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ahnu119

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值