Commit 1a607f69 authored by Qiu Xiang's avatar Qiu Xiang

实现自定义信息窗口

parent 0164651f
...@@ -44,6 +44,7 @@ public class AMapMarker extends ReactViewGroup { ...@@ -44,6 +44,7 @@ public class AMapMarker extends ReactViewGroup {
COLORS.put("HUE_YELLOW", BitmapDescriptorFactory.HUE_YELLOW); COLORS.put("HUE_YELLOW", BitmapDescriptorFactory.HUE_YELLOW);
} }
private ReactViewGroup infoWindow;
private Marker marker; private Marker marker;
private LatLng position; private LatLng position;
private String title = ""; private String title = "";
...@@ -175,4 +176,16 @@ public class AMapMarker extends ReactViewGroup { ...@@ -175,4 +176,16 @@ public class AMapMarker extends ReactViewGroup {
} }
} }
} }
public ReactViewGroup getInfoWindow() {
return infoWindow;
}
public void setInfoWindow(ReactViewGroup view) {
infoWindow = view;
}
public void setInfoWindowLayout(int width, int height) {
infoWindow.setLayoutParams(new ReactViewGroup.LayoutParams(width, height));
}
} }
package cn.qiuxiang.react.amap3d; package cn.qiuxiang.react.amap3d;
import android.view.View;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder; import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
class AMapMarkerManager extends SimpleViewManager<AMapMarker> { class AMapMarkerManager extends ViewGroupManager<AMapMarker> {
@Override @Override
public String getName() { public String getName() {
return "AMapMarker"; return "AMapMarker";
...@@ -20,6 +23,11 @@ class AMapMarkerManager extends SimpleViewManager<AMapMarker> { ...@@ -20,6 +23,11 @@ class AMapMarkerManager extends SimpleViewManager<AMapMarker> {
return new AMapMarker(reactContext); return new AMapMarker(reactContext);
} }
@Override
public void addView(AMapMarker marker, View view, int index) {
marker.setInfoWindow((ReactViewGroup) view);
}
@Override @Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() { public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
...@@ -70,4 +78,17 @@ class AMapMarkerManager extends SimpleViewManager<AMapMarker> { ...@@ -70,4 +78,17 @@ class AMapMarkerManager extends SimpleViewManager<AMapMarker> {
public void setImage(AMapMarker marker, String image) { public void setImage(AMapMarker marker, String image) {
marker.setImage(image); marker.setImage(image);
} }
// 对于 infoWindow,必须手动设置 layoutParams 才能正确显示,
// 但我在 Android 端没有找到监听 infoWindow onLayout 的方法,
// 我的解决办法是在 js 端监听 onLayout,并反馈到这里。
//
// PS.
// react-native-maps 的解决方法是 LayoutShadowNode,详见:
// https://github.com/airbnb/react-native-maps/blob/master/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java
// 这里暂做保留。
@ReactProp(name = "infoWindowLayout")
public void setInfoWindowLayout(AMapMarker marker, ReadableMap layout) {
marker.setInfoWindowLayout(layout.getInt("width"), layout.getInt("height"));
}
} }
...@@ -2,6 +2,7 @@ package cn.qiuxiang.react.amap3d; ...@@ -2,6 +2,7 @@ package cn.qiuxiang.react.amap3d;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.location.Location; import android.location.Location;
import android.view.View;
import com.amap.api.maps.AMap; import com.amap.api.maps.AMap;
import com.amap.api.maps.MapView; import com.amap.api.maps.MapView;
...@@ -109,6 +110,18 @@ public class AMapView extends MapView { ...@@ -109,6 +110,18 @@ public class AMapView extends MapView {
markers.get(marker.getId()).sendEvent("onInfoWindowClick", Arguments.createMap()); markers.get(marker.getId()).sendEvent("onInfoWindowClick", Arguments.createMap());
} }
}); });
map.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
return markers.get(marker.getId()).getInfoWindow();
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
} }
public void addMarker(AMapMarker marker) { public void addMarker(AMapMarker marker) {
......
import React, {PropTypes, Component} from 'react' import React, {PropTypes, Component} from 'react'
import {requireNativeComponent, View} from 'react-native' import {requireNativeComponent, View, PixelRatio} from 'react-native'
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource' import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'
import {CoordinatePropType} from './PropTypes' import {CoordinatePropType} from './PropTypes'
...@@ -60,10 +60,12 @@ class Marker extends Component { ...@@ -60,10 +60,12 @@ class Marker extends Component {
onDragStart: React.PropTypes.func, onDragStart: React.PropTypes.func,
onDrag: React.PropTypes.func, onDrag: React.PropTypes.func,
onDragEnd: React.PropTypes.func, onDragEnd: React.PropTypes.func,
onCalloutPress: React.PropTypes.func, onInfoWindowPress: React.PropTypes.func,
} }
_eventHandler(name) { state = {}
_handle(name) {
return event => { return event => {
if (this.props[name]) { if (this.props[name]) {
this.props[name](event) this.props[name](event)
...@@ -71,21 +73,42 @@ class Marker extends Component { ...@@ -71,21 +73,42 @@ class Marker extends Component {
} }
} }
_handleLayout(calloutLayout) {
this.setState({infoWindowLayout: {
width: PixelRatio.getPixelSizeForLayoutSize(calloutLayout.width),
height: PixelRatio.getPixelSizeForLayoutSize(calloutLayout.height),
}})
}
render() { render() {
const props = { const props = {
...this.props, ...this.props,
onMarkerClick: this._eventHandler('onPress'), infoWindowLayout: this.state.infoWindowLayout,
onMarkerDragStart: this._eventHandler('onDragStart'), onMarkerClick: this._handle('onPress'),
onMarkerDrag: this._eventHandler('onDrag'), onMarkerDragStart: this._handle('onDragStart'),
onMarkerDragEnd: this._eventHandler('onDragEnd'), onMarkerDrag: this._handle('onDrag'),
onMarkerDragEnd: this._handle('onDragEnd'),
} }
if (typeof props.image === 'number') { if (typeof props.image === 'number') {
props.image = resolveAssetSource(this.props.image).uri props.image = resolveAssetSource(this.props.image).uri
} }
if (props.children) {
props.children = <View
{...props.children.props}
onLayout={event => this._handleLayout(event.nativeEvent.layout)}
collapsable={false}/>
}
return <AMapMarker {...props}/> return <AMapMarker {...props}/>
} }
} }
AMapMarker = requireNativeComponent('AMapMarker', Marker) AMapMarker = requireNativeComponent('AMapMarker', Marker, {
nativeOnly: {
infoWindowLayout: true,
},
})
export default Marker export default Marker
import React, {Component} from 'react' import React, {Component} from 'react'
import {StyleSheet, Alert} from 'react-native' import {StyleSheet, Alert, Text, View} from 'react-native'
import {MapView, Marker} from 'react-native-amap3d' import {MapView, Marker} from 'react-native-amap3d'
export default class MarkerComponent extends Component { export default class MarkerComponent extends Component {
...@@ -12,23 +12,27 @@ export default class MarkerComponent extends Component { ...@@ -12,23 +12,27 @@ export default class MarkerComponent extends Component {
<Marker <Marker
title='一个可拖拽的 Marker' title='一个可拖拽的 Marker'
draggable draggable
selected
onDragEnd={({nativeEvent}) => onDragEnd={({nativeEvent}) =>
Alert.alert(`新坐标:${nativeEvent.latitude}, ${nativeEvent.longitude}`)} Alert.alert(`新坐标:${nativeEvent.latitude}, ${nativeEvent.longitude}`)}
onCalloutPress={() => Alert.alert('Callout Press')} onInfoWindowPress={() => Alert.alert('信息窗口点击事件')}
coordinate={{ coordinate={{
latitude: 39.806901, latitude: 39.806901,
longitude: 116.397972, longitude: 116.397972,
}} }}
/> />
<Marker <Marker
selected
image='HUE_RED' image='HUE_RED'
title='一个红色的 Marker' title='一个红色的 Marker'
infoWindowWidth={100}
coordinate={{ coordinate={{
latitude: 39.806901, latitude: 39.806901,
longitude: 116.297972, longitude: 116.297972,
}} }}>
/> <View style={styles.customInfoWindow}>
<Text>一个自定义的信息窗口</Text>
</View>
</Marker>
<Marker <Marker
image={require('../images/marker.png')} image={require('../images/marker.png')}
title='自定义图片' title='自定义图片'
...@@ -40,3 +44,15 @@ export default class MarkerComponent extends Component { ...@@ -40,3 +44,15 @@ export default class MarkerComponent extends Component {
</MapView> </MapView>
} }
} }
const styles = StyleSheet.create({
customInfoWindow: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
width: 100,
padding: 10,
borderRadius: 10,
elevation: 4,
},
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment