Commit baa392b8 authored by Qiu Xiang's avatar Qiu Xiang
Browse files

使用 shadowNode 处理 infoWindow 的 layout

parent e0734213
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ public class AMap3DPackage implements ReactPackage {
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
                new AMapViewManager(),
                new AMapMarkerManager());
                new AMapMarkerManager(),
                new AMapInfoWindowManager());
    }
}
+11 −0
Original line number Diff line number Diff line
package cn.qiuxiang.react.amap3d;

import android.content.Context;

import com.facebook.react.views.view.ReactViewGroup;

public class AMapInfoWindow extends ReactViewGroup {
    public AMapInfoWindow(Context context) {
        super(context);
    }
}
+41 −0
Original line number Diff line number Diff line
package cn.qiuxiang.react.amap3d;

import android.widget.LinearLayout;

import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;

import java.util.HashMap;

class AMapInfoWindowManager extends ViewGroupManager<AMapInfoWindow> {
    @Override
    public String getName() {
        return "AMapInfoWindow";
    }

    @Override
    protected AMapInfoWindow createViewInstance(ThemedReactContext reactContext) {
        return new AMapInfoWindow(reactContext);
    }

    @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(
                Math.round(data.get("width")), Math.round(data.get("height"))));
    }
}
+5 −14
Original line number Diff line number Diff line
@@ -25,7 +25,11 @@ class AMapMarkerManager extends ViewGroupManager<AMapMarker> {

    @Override
    public void addView(AMapMarker marker, View view, int index) {
        if (view instanceof AMapInfoWindow) {
            marker.setInfoWindow((ReactViewGroup) view);
        } else {
            super.addView(marker, view, index);
        }
    }

    @Override
@@ -78,17 +82,4 @@ class AMapMarkerManager extends ViewGroupManager<AMapMarker> {
    public void setIcon(AMapMarker marker, String icon) {
        marker.setIcon(icon);
    }

    // 对于 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"));
    }
}
+33 −0
Original line number Diff line number Diff line
/*
  Copyright (c) 2015-present, Facebook, Inc.
  All rights reserved.
  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

package cn.qiuxiang.react.amap3d;

import android.util.Log;

import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.UIViewOperationQueue;

import java.util.HashMap;
import java.util.Map;

// Custom LayoutShadowNode implementation used in conjunction with the AirMapManager
// which sends the width/height of the view after layout occurs.
class SizeReportingShadowNode extends LayoutShadowNode {

    @Override
    public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) {
        super.onCollectExtraUpdates(uiViewOperationQueue);

        Map<String, Float> data = new HashMap<>();
        data.put("width", getLayoutWidth());
        data.put("height", getLayoutHeight());

        uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data);
    }
}
Loading