Commit 7d7ca2ec authored by Qiu Xiang's avatar Qiu Xiang

添加 Marker 自定义 view 的支持

parent baa392b8
package cn.qiuxiang.react.amap3d; package cn.qiuxiang.react.amap3d;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.facebook.react.ReactPackage; import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class AMap3DPackage implements ReactPackage { public class AMap3DPackage implements ReactPackage {
@Override @Override
...@@ -26,6 +26,7 @@ public class AMap3DPackage implements ReactPackage { ...@@ -26,6 +26,7 @@ public class AMap3DPackage implements ReactPackage {
return Arrays.<ViewManager>asList( return Arrays.<ViewManager>asList(
new AMapViewManager(), new AMapViewManager(),
new AMapMarkerManager(), new AMapMarkerManager(),
new AMapOverlayManager(),
new AMapInfoWindowManager()); new AMapInfoWindowManager());
} }
} }
package cn.qiuxiang.react.amap3d; package cn.qiuxiang.react.amap3d;
import android.widget.LinearLayout; import android.view.ViewGroup;
import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
...@@ -21,21 +21,14 @@ class AMapInfoWindowManager extends ViewGroupManager<AMapInfoWindow> { ...@@ -21,21 +21,14 @@ class AMapInfoWindowManager extends ViewGroupManager<AMapInfoWindow> {
@Override @Override
public LayoutShadowNode createShadowNodeInstance() { public LayoutShadowNode createShadowNodeInstance() {
// we use a custom shadow node that emits the width/height of the view
// after layout with the updateExtraData method. Without this, we can't generate
// a bitmap of the appropriate width/height of the rendered view.
return new SizeReportingShadowNode(); return new SizeReportingShadowNode();
} }
@Override @Override
public void updateExtraData(AMapInfoWindow infoWindow, Object extraData) { public void updateExtraData(AMapInfoWindow infoWindow, Object extraData) {
// This method is called from the shadow node with the width/height of the rendered
// marker view.
//
// noinspection unchecked // noinspection unchecked
HashMap<String, Float> data = (HashMap<String, Float>) extraData; HashMap<String, Float> data = (HashMap<String, Float>) extraData;
infoWindow.setLayoutParams(new LinearLayout.LayoutParams( infoWindow.setLayoutParams(new ViewGroup.LayoutParams(
Math.round(data.get("width")), Math.round(data.get("height")))); Math.round(data.get("width")), Math.round(data.get("height"))));
} }
} }
package cn.qiuxiang.react.amap3d; package cn.qiuxiang.react.amap3d;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.View;
import com.amap.api.maps.AMap; import com.amap.api.maps.AMap;
import com.amap.api.maps.model.BitmapDescriptor; import com.amap.api.maps.model.BitmapDescriptor;
...@@ -53,6 +56,7 @@ public class AMapMarker extends ReactViewGroup { ...@@ -53,6 +56,7 @@ public class AMapMarker extends ReactViewGroup {
private float opacity = 1; private float opacity = 1;
private boolean draggable = false; private boolean draggable = false;
private boolean selected; private boolean selected;
private boolean showsInfoWindow = false;
private BitmapDescriptor bitmapDescriptor; private BitmapDescriptor bitmapDescriptor;
private RCTEventEmitter eventEmitter; private RCTEventEmitter eventEmitter;
private DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber = private DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber =
...@@ -104,6 +108,7 @@ public class AMapMarker extends ReactViewGroup { ...@@ -104,6 +108,7 @@ public class AMapMarker extends ReactViewGroup {
.draggable(draggable) .draggable(draggable)
.position(position) .position(position)
.title(title) .title(title)
.infoWindowEnable(showsInfoWindow)
.snippet(snippet); .snippet(snippet);
} }
...@@ -185,7 +190,31 @@ public class AMapMarker extends ReactViewGroup { ...@@ -185,7 +190,31 @@ public class AMapMarker extends ReactViewGroup {
infoWindow = view; infoWindow = view;
} }
public void setInfoWindowLayout(int width, int height) { public void setIconView(final AMapOverlay overlay) {
infoWindow.setLayoutParams(new ReactViewGroup.LayoutParams(width, height)); overlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
updateIcon(overlay);
}
});
overlay.setOnUpdateListener(new AMapOverlay.OnUpdateListener() {
@Override
public void onUpdate() {
updateIcon(overlay);
}
});
}
private void updateIcon(AMapOverlay overlay) {
Bitmap bitmap = Bitmap.createBitmap(
overlay.getWidth(),
overlay.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
overlay.draw(canvas);
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap);
if (marker != null) {
marker.setIcon(bitmapDescriptor);
}
} }
} }
...@@ -27,8 +27,8 @@ class AMapMarkerManager extends ViewGroupManager<AMapMarker> { ...@@ -27,8 +27,8 @@ class AMapMarkerManager extends ViewGroupManager<AMapMarker> {
public void addView(AMapMarker marker, View view, int index) { public void addView(AMapMarker marker, View view, int index) {
if (view instanceof AMapInfoWindow) { if (view instanceof AMapInfoWindow) {
marker.setInfoWindow((ReactViewGroup) view); marker.setInfoWindow((ReactViewGroup) view);
} else { } else if (view instanceof AMapOverlay) {
super.addView(marker, view, index); marker.setIconView((AMapOverlay) view);
} }
} }
......
package cn.qiuxiang.react.amap3d;
import android.content.Context;
import com.facebook.react.views.view.ReactViewGroup;
public class AMapOverlay extends ReactViewGroup {
private OnUpdateListener onUpdateListener;
public AMapOverlay(Context context) {
super(context);
}
public void setOnUpdateListener(OnUpdateListener listener) {
onUpdateListener = listener;
}
public void update() {
if (onUpdateListener != null) {
onUpdateListener.onUpdate();
}
}
interface OnUpdateListener {
void onUpdate();
}
}
package cn.qiuxiang.react.amap3d;
import android.view.ViewGroup;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import java.util.HashMap;
import java.util.Map;
class AMapOverlayManager extends ViewGroupManager<AMapOverlay> {
private static final int UPDATE = 1;
@Override
public String getName() {
return "AMapOverlay";
}
@Override
protected AMapOverlay createViewInstance(ThemedReactContext reactContext) {
return new AMapOverlay(reactContext);
}
@Override
public Map<String, Integer> getCommandsMap() {
return MapBuilder.of("update", UPDATE);
}
@Override
public void receiveCommand(AMapOverlay overlay, int commandId, ReadableArray args) {
switch (commandId) {
case UPDATE:
overlay.update();
break;
}
}
@Override
public LayoutShadowNode createShadowNodeInstance() {
return new SizeReportingShadowNode();
}
@Override
public void updateExtraData(AMapOverlay overlay, Object extraData) {
// noinspection unchecked
HashMap<String, Float> data = (HashMap<String, Float>) extraData;
overlay.setLayoutParams(new ViewGroup.LayoutParams(
Math.round(data.get("width")), Math.round(data.get("height"))));
}
}
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
package cn.qiuxiang.react.amap3d; package cn.qiuxiang.react.amap3d;
import android.util.Log;
import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.uimanager.UIViewOperationQueue;
......
...@@ -2,6 +2,7 @@ import React, {PropTypes, Component} from 'react' ...@@ -2,6 +2,7 @@ import React, {PropTypes, Component} from 'react'
import {requireNativeComponent, View} from 'react-native' import {requireNativeComponent, View} from 'react-native'
import Marker from './Marker' import Marker from './Marker'
import InfoWindow from './InfoWindow' import InfoWindow from './InfoWindow'
import Overlay from './Overlay'
const CoordinatePropType = PropTypes.shape({ const CoordinatePropType = PropTypes.shape({
latitude: PropTypes.number.isRequired, latitude: PropTypes.number.isRequired,
...@@ -143,10 +144,11 @@ class MapView extends Component { ...@@ -143,10 +144,11 @@ class MapView extends Component {
} }
static Marker = Marker static Marker = Marker
static Overlay = Overlay
static InfoWindow = InfoWindow static InfoWindow = InfoWindow
} }
AMapView = requireNativeComponent('AMapView', MapView) AMapView = requireNativeComponent('AMapView', MapView)
export default MapView export default MapView
export {MapView, Marker, InfoWindow} export {MapView, Marker, InfoWindow, Overlay}
...@@ -94,8 +94,8 @@ class Marker extends Component { ...@@ -94,8 +94,8 @@ class Marker extends Component {
} }
if (typeof props.icon === 'function') { if (typeof props.icon === 'function') {
delete props.icon
customMarker = props.icon() customMarker = props.icon()
delete props.icon
} }
return <AMapMarker {...props}> return <AMapMarker {...props}>
......
import React, {PropTypes, Component} from 'react'
import {
View,
UIManager,
NativeModules,
findNodeHandle,
requireNativeComponent,
} from 'react-native'
class Overlay extends Component {
static propTypes = {
...View.propTypes,
}
componentDidUpdate() {
setTimeout(() => {
UIManager.dispatchViewManagerCommand(
findNodeHandle(this),
UIManager.AMapOverlay.Commands.update,
null,
)
}, 0)
}
render() {
return <AMapOverlay {...this.props}/>
}
}
AMapOverlay = requireNativeComponent('AMapOverlay', Overlay)
export default Overlay
import React, {Component} from 'react' import React, {Component} from 'react'
import {StyleSheet, Alert, Text, View} from 'react-native' import {StyleSheet, Alert, Text, View} from 'react-native'
import {MapView, Marker, InfoWindow} from 'react-native-amap3d' import {MapView, Marker, InfoWindow, Overlay} from 'react-native-amap3d'
export default class MarkerComponent extends Component { export default class MarkerComponent extends Component {
static navigationOptions = { static navigationOptions = {
title: '添加标记', title: '添加标记',
} }
state = {
time: new Date(),
}
componentDidMount() {
this.mounted = true
setInterval(() => {
if (this.mounted) {
this.setState({time: new Date()})
}
}, 1000)
}
componentWillUnmount() {
this.mounted = false
}
render() { render() {
return <MapView style={StyleSheet.absoluteFill}> return <MapView style={StyleSheet.absoluteFill}>
<Marker <Marker
...@@ -30,7 +47,7 @@ export default class MarkerComponent extends Component { ...@@ -30,7 +47,7 @@ export default class MarkerComponent extends Component {
longitude: 116.297972, longitude: 116.297972,
}}> }}>
<InfoWindow style={styles.customInfoWindow}> <InfoWindow style={styles.customInfoWindow}>
<Text>一个自定义的信息窗口</Text> <Text>一个自定义 View 的信息窗口</Text>
</InfoWindow> </InfoWindow>
</Marker> </Marker>
<Marker <Marker
...@@ -42,7 +59,10 @@ export default class MarkerComponent extends Component { ...@@ -42,7 +59,10 @@ export default class MarkerComponent extends Component {
}} }}
/> />
<Marker <Marker
title='自定义 View 图标' title='自定义 View Marker'
icon={() => <Overlay style={styles.customMarker}>
<Text style={styles.markerText}>{this.state.time.toLocaleTimeString()}</Text>
</Overlay>}
coordinate={{ coordinate={{
latitude: 39.706901, latitude: 39.706901,
longitude: 116.397972, longitude: 116.397972,
...@@ -54,12 +74,18 @@ export default class MarkerComponent extends Component { ...@@ -54,12 +74,18 @@ export default class MarkerComponent extends Component {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
customInfoWindow: { customInfoWindow: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff', backgroundColor: '#fff',
width: 100, width: 128,
padding: 10, padding: 10,
borderRadius: 10,
elevation: 4, elevation: 4,
}, },
customMarker: {
width: 70,
backgroundColor: '#009688',
alignItems: 'center',
padding: 5,
},
markerText: {
color: '#fff',
},
}) })
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