CoordinatorLayout和BottomSheetBehavior的react-native包装器

FXC*_*nha 12 android react-native bottom-sheet react-native-android

我一直在编写一个包含BottomSheetBehavior的原生android模块.

一个非常简单的BottomSheetBehavior可以像这样实现 https://gist.github.com/cesardeazevedo/a4dc4ed12df33fe1877fc6cea42475ae

我面对的第一件事,整个页面必须是CoordinatorLayout的子节点和底部的BottomSheetBehavior.

所以我不得不写2个原生模块,<CoordinatorLayout /><BottomSheetBehavior />.

这是bottomSheetBehavior包装器.

BottomSheetBehaviorManager.java

public class BottomSheetBehaviorManager extends ViewGroupManager<BottomSheetBehaviorView> {

    @Override
    public BottomSheetBehaviorView createViewInstance(ThemedReactContext context) {
        return new BottomSheetBehaviorView(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

BottomSheetBehaviorView.java

public class BottomSheetBehaviorView extends RelativeLayout {

    public BottomSheetBehaviorView(Context context) {
        super(context);

        int width  = ViewGroup.LayoutParams.WRAP_CONTENT;
        int height = ViewGroup.LayoutParams.WRAP_CONTENT;
        // int height = 1000; // fixed a height works, it only slide up half of the screen

        CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(width, height);
        params.setBehavior(new BottomSheetBehavior());
        this.setLayoutParams(params);

        BottomSheetBehavior<BottomSheetBehaviorView> bottomSheetBehavior = BottomSheetBehavior.from(this);
        bottomSheetBehavior.setHideable(false);
        bottomSheetBehavior.setPeekHeight(200);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的反应成分变得像这样.

index.android.js

  return () {
    <CoordinatorLayout style={{flex: 1}}>
      <View><!--app--></View>
      <BottomSheetBehavior>
        <View style={{height: 300}}> <!--height doesnt work-->
          <Text>BottomSheetBehavior !</Text>
        </View>
      </BottomSheetBehavior>
    </CoordinatorLayout>
  )
Run Code Online (Sandbox Code Playgroud)

它的工作原理!

反应母语-bottomsheet行为

但我一直在努力让BottomSheet包装他们的孩子wrap_content,它不应该滑动整个屏幕,它应该只滑过包装的内容(在这种情况下是一个lorem ipsum文本),它适用于Android组件,但它不使用反应组件.那么,如何制作一个RelativeLayout包装反应<View style={{height: 300}} />组件?我也试图实现一些测量shadownode,但没有按预期工作,我不知道它们是如何工作的.

我在我的github上添加了这个例子,每个人都想尝试一下. https://github.com/cesardeazevedo/react-native-bottom-sheet-behavior

FXC*_*nha 3

经过大量调试,终于我明白了,我必须做两件事,首先是重写 onMeasure 函数并将子高度应用到setMeasuredDimension,显然解决了高度问题,但是玩了一下之后, state 破坏了 BottomSheet 的位置,因此我必须通过 UIManager.dispatchViewManagerCommand 为每个状态更改调用 requestLayout,并且效果很好。

所以,这就是修复的实现。

犯罪

BottomSheetBehaviorView.js

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    View child = this.getChildAt(0);

    if (child != null) {
        setMeasuredDimension(widthMeasureSpec, child.getHeight());
    }
}
Run Code Online (Sandbox Code Playgroud)

BottomSheetBehaviorManager.js

@Override
public Map<String, Integer> getCommandsMap() {
    return MapBuilder.of("setRequestLayout", COMMAND_SET_REQUEST_LAYOUT);
}

@Override
public void receiveCommand(BottomSheetBehaviorView view, int commandType, @Nullable ReadableArray args) {
    if (commandType == COMMAND_SET_REQUEST_LAYOUT) {
        setRequestLayout(view);
    }
}

private void setRequestLayout(BottomSheetBehaviorView view) {
    view.requestLayout();
}
Run Code Online (Sandbox Code Playgroud)

BottomSheetBehavior.js

  componentDidUpdate() {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this),
      UIManager.RCTBottomSheetBehaviorAndroid.Commands.setRequestLayout,
      [],
    )
  }
Run Code Online (Sandbox Code Playgroud)

更新

我意识到滑动时更新状态会闪烁所有布局,在查看了一些库代码后,我发现了 needCustomLayoutForChildren 函数,该函数在 ViewGroupManager.java 上进行了描述

  /**
   * Returns whether this View type needs to handle laying out its own children instead of
   * deferring to the standard css-layout algorithm.
   * Returns true for the layout to *not* be automatically invoked. Instead onLayout will be
   * invoked as normal and it is the View instance's responsibility to properly call layout on its
   * children.
   * Returns false for the default behavior of automatically laying out children without going
   * through the ViewGroup's onLayout method. In that case, onLayout for this View type must *not*
   * call layout on its children.
   */
  public boolean needsCustomLayoutForChildren() {
    return false;
  }
Run Code Online (Sandbox Code Playgroud)

所以我修复了在 CoordinatorLayoutManager.java 上返回 true

这是它的样子。

反应本机底部工作表行为