React-Native包装器用于CoordinatorLayout和BottomSheetBehavior

12

我正在编写一个本地的 Android 模块,它包装了一个 BottomSheetBehavior

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

我面临的第一个问题是整个页面必须是 CoordinatorLayout 的子元素,并在其末尾添加 BottomSheetBehavior。

所以我不得不编写两个本地模块:<CoordinatorLayout /><BottomSheetBehavior />

这是 BottomSheetBehavior 包装器。

BottomSheetBehaviorManager.java

public class BottomSheetBehaviorManager extends ViewGroupManager<BottomSheetBehaviorView> {

    @Override
    public BottomSheetBehaviorView createViewInstance(ThemedReactContext context) {
        return new BottomSheetBehaviorView(context);
    }
}

底部工作表行为视图.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);
    }
}

我的React组件变成了这样。

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>
  )

它有效!

react-native-bottomsheet-behavior

但是我一直在努力使BottomSheet包裹其子视图并使用wrap_content,它不应该滑动整个屏幕,而应该只能通过包装的内容(在这种情况下是lorem ipsum文本)滑动,它可以与android组件一起使用,但不能与react组件一起使用。那么,如何使RelativeLayout包裹一个react <View style={{height: 300}} />组件?我还尝试过实现一些测量阴影节点,但效果不如预期,我不知道它们是如何工作的。

我已经将此示例添加到我的GitHub上供大家尝试。 https://github.com/cesardeazevedo/react-native-bottom-sheet-behavior

1个回答

3
经过大量调试,我终于解决了问题。我需要做两件事情,首先是重写onMeasure函数,并将子元素的高度应用到setMeasuredDimension中,这样就解决了高度问题。但是,在进行一些操作后,状态发生变化会破坏底部工作表的位置,所以我必须通过UIManager.dispatchViewManagerCommand为每个状态更改调用requestLayout来修复它,并且效果非常好。

因此,这就是解决问题的实现。

commit

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());
    }
}

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();
}

BottomSheetBehavior.js

  componentDidUpdate() {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this),
      UIManager.RCTBottomSheetBehaviorAndroid.Commands.setRequestLayout,
      [],
    )
  }

更新

我意识到在滑动时更新状态会导致布局闪烁,经过查看一些库的代码,我发现了ViewGroupManager.java文件中描述的needsCustomLayoutForChildren函数。

  /**
   * 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;
  }

我在CoordinatorLayoutManager.java中使用了fixed,并将其返回值设置为true。

以下是它的样子。

react-native-bottom-sheet-behavior


哇哇,太棒了,非常感谢您的分享,我会尝试使用BottomSheetFragment并提交PR! :) - Noitidart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接