react-native-component / react-native-smart-amap

react-native 高德地图SDK 插件
MIT License
176 stars 54 forks source link

react-native-smart-amap

A AMap Library for React Native apps.

npm npm npm npm

react-native 高德地图SDK 插件, 支持ios与android, 关于使用高德地图SDK, 申请应用key等详细信息请点击这里

Mac下Android Studio中获取SHA1和MD5请点击这里

预览

react-native-smart-amap-preview-ios

安装

npm install react-native-smart-amap --save

Notice

这个版本仅支持react-native 0.40及以上, 如果你想使用旧版本,使用npm install react-native-smart-amap@untilRN0.40 --save

安装 (iOS)


...
#import <AMapFoundationKit/AMapFoundationKit.h> //引入高德地图核心包
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

  [AMapServices sharedServices].apiKey = @"请填写您的key"; //设置高德地图SDK服务key
  ...
}
...

安装 (Android)

...
include ':react-native-smart-amap'
project(':react-native-smart-amap').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-smart-amap/android')
...
dependencies {
    ...
    // From node_modules
    compile project(':react-native-smart-amap')
}
...
import com.reactnativecomponent.amaplocation.RCTAMapPackage;    //import package
...
/**
 * A list of packages used by the app. If the app uses additional views
 * or modules besides the default ones, add more packages here.
 */
@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new RCTAMapPackage()  //register Module
    );
}
...

...
 <!--*************************高德地图-定位所需要权限*************************-->
    <!-- Normal Permissions 不需要运行时注册 -->
    <!--获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />

    <!-- 请求网络 -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- 不是SDK需要的权限,是示例中的后台唤醒定位需要的权限 -->
    <!--<uses-permission android:name="android.permission.WAKE_LOCK" />-->

    <!-- 需要运行时注册的权限 -->
    <!--用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!--用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!--用于提高GPS定位速度-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <!--写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--读取缓存数据-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <!--用于读取手机当前的状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <!-- 更改设置 -->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--*************************高德地图-定位所需要权限*************************-->
...

...
    <!--高德地图SDK key设置-->
    <meta-data
        android:name="com.amap.api.v2.apikey"
        android:value="请填写您的key"/>
    <!--高德地图APS服务设置-->
    <service android:name="com.amap.api.location.APSService" >
    </service>
...

完整示例

点击这里 ReactNativeComponentDemos

使用简介

Install the package from npm with npm install react-native-smart-amap --save. Then, require it from your app's JavaScript files with import Barcode from 'react-native-smart-amap'.

import React, {
    Component,
} from 'react'
import {
    StyleSheet,
    View,
    Text,
    Image,
    NativeAppEventEmitter,
    TouchableHighlight,
    ListView,
    Dimensions,
    Alert,
    Platform,
} from 'react-native'

import AMapLocation from 'react-native-smart-amap-location'
import AMap from 'react-native-smart-amap'
import Button from 'react-native-smart-button'
import AppEventListenerEnhance from 'react-native-smart-app-event-listener-enhance'
import PullToRefreshListView from 'react-native-smart-pull-to-refresh-listview'
import TimerEnhance from 'react-native-smart-timer-enhance'
import AMapALoneNearByList from './amp-alone-nearby-list'
import ListViewActivityIndicator from './ListViewActivityIndicator'

const {width: deviceWidth, height: deviceHeight} = Dimensions.get('window')

class AMapDemo extends Component {

    constructor(props) {
        super(props);

        this._amap = null
        this._page = 0
        this._coordinate = this.props.navigator.navigationContext._currentRoute.coordinate
        console.log(`this._coordinate -> `)
        console.log(this._coordinate)
        this._keywords = '商务住宅|学校'
        this._onDidMoveByUserTimer = null
    }

    componentDidMount() {
        this.addAppEventListener(
            NativeAppEventEmitter.addListener('amap.location.onLocationResult', this._onLocationResult),
            NativeAppEventEmitter.addListener('amap.onPOISearchDone', this._onPOISearchDone)
            //NativeAppEventEmitter.addListener('amap.onPOISearchFailed', this._onPOISearchFailed)
        )
    }

    render () {
        //console.log(`amap-alone render...`)
        return (
                <View style={{marginTop: (Platform.OS == 'ios' ? 20 + 44 : 56), flex: 1, }}>
                    <View style={{position: 'relative', height: (deviceHeight - (Platform.OS == 'ios' ? 64 : 56)) - 50 * 5,}}>
                        <AMap
                        ref={ component => this._amap = component }
                        style={{flex: 1, }}
                        options={{
                            frame: {
                                width: deviceWidth,
                                height: (deviceHeight - 64) - 50 * 5
                            },
                            showsUserLocation: false,
                            userTrackingMode: Platform.OS == 'ios' ? AMap.constants.userTrackingMode.none : null,
                            centerCoordinate: {
                                latitude: this._coordinate.latitude,
                                longitude: this._coordinate.longitude,
                            },
                            zoomLevel: 18.1,
                            centerMarker: Platform.OS == 'ios' ? 'icon_location' : 'poi_marker',
                        }}
                        onLayout={this._onLayout}
                        onDidMoveByUser={this._onDidMoveByUser}
                        />
                        <Button
                            touchableType={Button.constants.touchableTypes.highlight}
                            underlayColor={'#ccc'}
                            style={{padding: 5, position: 'absolute', left: 10, bottom: 20, backgroundColor: '#fff', justifyContent: 'center', borderRadius: 3, borderWidth: StyleSheet.hairlineWidth, borderColor: '#ffffff', justifyContent: 'center', }}
                            onPress={ () => {
                                AMapLocation.init(null)
                                AMapLocation.getLocation()
                                //this._activityIndicator.setState({ visible: true,})
                            }}>
                            <Image source={{uri: Platform.OS == 'ios' ? 'gpsStat1' : 'gps_stat1'}} style={{width: 28, height: 28,}}/>
                        </Button>
                   </View>
                    <View style={{flex: 1, position: 'relative',}}>
                        <AMapALoneNearByList
                            ref={ (component) => this._amapALoneNearByList = component }
                            onRefresh={this._onRefresh}
                            onLoadMore={this._onLoadMore}
                        />
                        <ListViewActivityIndicator
                            ref={ (component) => this._activityIndicator = component }
                            style={{marginRight: 10, position:'absolute', left: (deviceWidth - 20) / 2, top: (50 * 5 - 20) / 2, }}
                            color={'#a9a9a9'}/>
                    </View>
                </View>
        )
    }

    _onDidMoveByUser = (e) => {
        //console.log(`_onDidMoveByUser....`)
        if(this._onDidMoveByUserTimer) {
            this.clearTimeout(this._onDidMoveByUserTimer)
            this._onDidMoveByUserTimer = null
        }
        let { longitude, latitude, } = e.nativeEvent.data.centerCoordinate
        this._onDidMoveByUserTimer = this.setTimeout( ()=> {
            let {refresh_none, refresh_idle, load_more_none, load_more_idle, loaded_all,} = PullToRefreshListView.constants.viewState
            if((this._amapALoneNearByList._pullToRefreshListView._refreshState == refresh_none || this._amapALoneNearByList._pullToRefreshListView._refreshState == refresh_idle)
                && (this._amapALoneNearByList._pullToRefreshListView._loadMoreState == load_more_none
                || this._amapALoneNearByList._pullToRefreshListView._loadMoreState == load_more_idle
                || this._amapALoneNearByList._pullToRefreshListView._loadMoreState == loaded_all)) {
                console.log(`beginRefresh(true)....`)
                this._coordinate = {
                    longitude,
                    latitude,
                }
                this._activityIndicator.setState({ visible: true,})
                this._amapALoneNearByList._pullToRefreshListView._scrollView.scrollTo({ y: 0, animated: false, })
                this._amapALoneNearByList._pullToRefreshListView.beginRefresh(true)
                //this._amapALoneNearByList._pullToRefreshListView.beginRefresh()
                this._beginRefresh = true
            }
        }, 300)
    }

    _onLocationResult = (result) => {
        if(result.error) {
            console.log(`map-错误代码: ${result.error.code}, map-错误信息: ${result.error.localizedDescription}`)
        }
        else {
            if(result.formattedAddress) {
                console.log(`map-格式化地址 = ${result.formattedAddress}`)
            }
            else {
                console.log(`map-纬度 = ${result.coordinate.latitude}, map-经度 = ${result.coordinate.longitude}`)
                this._coordinate = {
                    latitude: result.coordinate.latitude,
                    longitude: result.coordinate.longitude,
                }
                this._amap.setOptions({
                    zoomLevel: 18.1,
                })
                this._amap.setCenterCoordinate(this._coordinate)
            }
        }
    }

    //_onPOISearchFailed = (e) => {
    //    //console.log(`_onPOISearchFailed...`)
    //    //console.log(e)
    //    //console.log(e.error)
    //    this._page--;
    //}

    _onPOISearchDone = (result) => {
        console.log(`_onPOISearchDone...`)

        if(Platform.OS == 'ios') {
            this._endSearch(result)
        }
        else {
            this.setTimeout( () => {
                this._endSearch(result)
            }, 255)
        }
    }

    _endSearch = (result) => {
        let { searchResultList, error } = result

        console.log(result.error)

        if(error) {
            if(this._page == 1) {
                this._page--
                this._amapALoneNearByList._pullToRefreshListView.endRefresh(this._beginRefresh)
                //this._amapALoneNearByList._pullToRefreshListView.endRefresh()
                this._beginRefresh = false
                this._activityIndicator.setState({ visible: false,})
            }
            else {
                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(false)
            }
            return
        }

        console.log(`this._page = ${this._page}`)

        //onRefresh
        if(this._page == 1) {
            this._amapALoneNearByList.setState({
                dataList: searchResultList,
                dataSource: this._amapALoneNearByList._dataSource.cloneWithRows(searchResultList),
            })
            this._amapALoneNearByList._pullToRefreshListView.endRefresh(this._beginRefresh)
            //this._amapALoneNearByList._pullToRefreshListView.endRefresh()
            this._beginRefresh = false
            this._activityIndicator.setState({ visible: false,})
        }
        //onLoadMore
        else {
            let newDataList = this._amapALoneNearByList.state.dataList.concat(searchResultList)
            this._amapALoneNearByList.setState({
                dataList: newDataList,
                dataSource: this._amapALoneNearByList._dataSource.cloneWithRows(newDataList),
            })
            let loadedAll
            if(searchResultList.length == 100) {
                loadedAll = true
                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(loadedAll)
            }
            else {
                loadedAll = false
                this._amapALoneNearByList._pullToRefreshListView.endLoadMore(loadedAll)
            }
        }
    }

    _searchNearBy = (searchParams)=> {
        this._amap.searchPoiByCenterCoordinate(searchParams)
    }

    _onRefresh = () => {
        console.log(`outer _onRefresh...`)
        this._searchNearBy({
            page: (this._page = 1),
            coordinate: this._coordinate,
            keywords: this._keywords,
        })
    }

    _onLoadMore = () => {
        console.log(`outer _onLoadMore...`)
        this._searchNearBy({
            page: ++this._page,
            coordinate: this._coordinate,
            keywords: this._keywords,
        })
    }

}

export default TimerEnhance(AppEventListenerEnhance(AMapDemo))

属性

Prop Type Optional Default Description
options object No 地图参数对象
options.frame object No ios设置地图宽(width), 高(height), 类型是number
options.showTraffic bool Yes ios设置是否显示路况, 默认不显示
options.showsUserLocation bool Yes ios设置是否显示用户位置,默认显示
options.userTrackingMode bool Yes ios设置追踪用户位置更新的模式,默认不追踪
options.zoomLevel number Yes 指定缩放级别, 默认为最大级别
options.centerCoordinate object Yes 根据经度(latitude)纬度(longitude)指定地图的中心点, 类型是number
options.centerMarker string Yes 设置中心点自定义图标的项目资源名称, 如为空则不显示中心点图标

方法

事件监听