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

添加 Marker 自定义 view 的支持

parent baa392b8
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.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
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 {
@Override
......@@ -26,6 +26,7 @@ public class AMap3DPackage implements ReactPackage {
return Arrays.<ViewManager>asList(
new AMapViewManager(),
new AMapMarkerManager(),
new AMapOverlayManager(),
new AMapInfoWindowManager());
}
}
package cn.qiuxiang.react.amap3d;
import android.widget.LinearLayout;
import android.view.ViewGroup;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ThemedReactContext;
......@@ -21,21 +21,14 @@ class AMapInfoWindowManager extends ViewGroupManager<AMapInfoWindow> {
@Override
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();
}
@Override
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
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"))));
}
}
package cn.qiuxiang.react.amap3d;
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.model.BitmapDescriptor;
......@@ -53,6 +56,7 @@ public class AMapMarker extends ReactViewGroup {
private float opacity = 1;
private boolean draggable = false;
private boolean selected;
private boolean showsInfoWindow = false;
private BitmapDescriptor bitmapDescriptor;
private RCTEventEmitter eventEmitter;
private DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber =
......@@ -104,6 +108,7 @@ public class AMapMarker extends ReactViewGroup {
.draggable(draggable)
.position(position)
.title(title)
.infoWindowEnable(showsInfoWindow)
.snippet(snippet);
}
......@@ -185,7 +190,31 @@ public class AMapMarker extends ReactViewGroup {
infoWindow = view;
}
public void setInfoWindowLayout(int width, int height) {
infoWindow.setLayoutParams(new ReactViewGroup.LayoutParams(width, height));
public void setIconView(final AMapOverlay overlay) {
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> {
public void addView(AMapMarker marker, View view, int index) {
if (view instanceof AMapInfoWindow) {
marker.setInfoWindow((ReactViewGroup) view);
} else {
super.addView(marker, view, index);
} else if (view instanceof AMapOverlay) {
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 @@
package cn.qiuxiang.react.amap3d;
import android.util.Log;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.UIViewOperationQueue;
......
......@@ -2,6 +2,7 @@ import React, {PropTypes, Component} from 'react'
import {requireNativeComponent, View} from 'react-native'
import Marker from './Marker'
import InfoWindow from './InfoWindow'
import Overlay from './Overlay'
const CoordinatePropType = PropTypes.shape({
latitude: PropTypes.number.isRequired,
......@@ -143,10 +144,11 @@ class MapView extends Component {
}
static Marker = Marker
static Overlay = Overlay
static InfoWindow = InfoWindow
}
AMapView = requireNativeComponent('AMapView', MapView)
export default MapView
export {MapView, Marker, InfoWindow}
export {MapView, Marker, InfoWindow, Overlay}
......@@ -94,8 +94,8 @@ class Marker extends Component {
}
if (typeof props.icon === 'function') {
delete props.icon
customMarker = props.icon()
delete props.icon
}
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 {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 {
static navigationOptions = {
title: '添加标记',
}
state = {
time: new Date(),
}
componentDidMount() {
this.mounted = true
setInterval(() => {
if (this.mounted) {
this.setState({time: new Date()})
}
}, 1000)
}
componentWillUnmount() {
this.mounted = false
}
render() {
return <MapView style={StyleSheet.absoluteFill}>
<Marker
......@@ -30,7 +47,7 @@ export default class MarkerComponent extends Component {
longitude: 116.297972,
}}>
<InfoWindow style={styles.customInfoWindow}>
<Text>一个自定义的信息窗口</Text>
<Text>一个自定义 View 的信息窗口</Text>
</InfoWindow>
</Marker>
<Marker
......@@ -42,7 +59,10 @@ export default class MarkerComponent extends Component {
}}
/>
<Marker
title='自定义 View 图标'
title='自定义 View Marker'
icon={() => <Overlay style={styles.customMarker}>
<Text style={styles.markerText}>{this.state.time.toLocaleTimeString()}</Text>
</Overlay>}
coordinate={{
latitude: 39.706901,
longitude: 116.397972,
......@@ -54,12 +74,18 @@ export default class MarkerComponent extends Component {
const styles = StyleSheet.create({
customInfoWindow: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
width: 100,
width: 128,
padding: 10,
borderRadius: 10,
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