无法在android中调整原生模块中的线性布局子项

sba*_*aar 12 android scroll android-layout react-native android-layoutparams

完整代码在这里

在java中正确行为的视频和不正确的反应原生在这里

我修改了一个线性布局,通过调整左边的孩子的大小来响应触摸,而右边的孩子占据了剩余的空间,模拟了一个可以使用以下代码"打开"或"关闭"的水平滚动

    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) leftView.getLayoutParams();
    //Log.d("ll","width " + newWidth);
    lp.width=newWidth;
    leftView.setLayoutParams(lp);
Run Code Online (Sandbox Code Playgroud)

在本机反应中,touch仍然调用此方法并记录预期值,但不更新子项的大小.它更新的唯一时间是我将可见性切换为已消失然后再次可见.从java调用invalidate/requestLayout或从js调用forceUpdate没有任何效果.

我需要调用一些其他代码来使视图无效并重绘吗?我需要提供一些提示,以便该组件滚动或响应触摸吗?

Gio*_*gos 6

我有同样的问题,我在这个旧的报道问题上找到了答案本地回购.

在自定义布局中添加以下代码,之后甚至无需调用requestLayout()或invalidate().更新布局的LayoutParams后,会立即传播更改.此解决方案与ReactPicker.javaReactToolbar.java中使用的解决方案相同.

@Override
public void requestLayout() {
    super.requestLayout();

    // The spinner relies on a measure + layout pass happening after it calls requestLayout().
    // Without this, the widget never actually changes the selection and doesn't call the
    // appropriate listeners. Since we override onLayout in our ViewGroups, a layout pass never
    // happens after a call to requestLayout, so we simulate one here.
    post(measureAndLayout);
}

private final Runnable measureAndLayout = new Runnable() {
    @Override
    public void run() {
        measure(
                MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
        layout(getLeft(), getTop(), getRight(), getBottom());
    }
};
Run Code Online (Sandbox Code Playgroud)


sba*_*aar 1

在大多数情况下,RN android 确实不会更新子布局或可见性或适配器更改。通过在需要更新时将钩子插入自定义视图,这将使 invalidate/requestLayout 然后调用此代码,大部分情况下会恢复正常行为。仍然存在一些情况,测量不像正常情况那样发生,我必须发布延迟的可运行对象,然后导致这种无效。处理节点的父节点可能并不是在所有情况下都严格必要,但对于某些情况来说是必要的。

在视图管理器中

Method markNewLayout, getShadowNode;

public ViewManager(){
    super();
    if (markNewLayout == null) {
        try {
            markNewLayout = CSSNode.class.getDeclaredMethod("markHasNewLayout");
            markNewLayout.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    try{
    if (getShadowNode==null){
        getShadowNode = UIImplementation.class.getDeclaredMethod("resolveShadowNode",int.class);
        getShadowNode.setAccessible(true);
    }
    } catch (Exception e) {
    e.printStackTrace();
}
public class MyShadowNode extends LayoutShadowNode {
@Override
public void markUpdated(){
    super.markUpdated();
    if (hasNewLayout()) markLayoutSeen();
    dirty();
}
@Override
public boolean isDirty(){
    return true;
}




 @Override
    protected CustomView createViewInstance(final ThemedReactContext reactContext) {

 view.setRnUpdateListener(new CustomView.RNUpdateListener() {
            MyShadowNode node;
            @Override
            public void needsUpdate() {
                view.requestLayout();


                Runnable r = new Runnable() {
                    @Override
                    public void run() {

                        if (node ==null){
                            try {
                                node = (MyShadowNode) getShadowNode.invoke(uiImplementation, view.getId());
                            }
                            catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                            if (node != null) {
                                if (node.hasNewLayout()) node.markLayoutSeen();
                                ReactShadowNode parent = node.getParent();
                                while (parent != null) {
                                    if (parent.hasNewLayout()) {
                                        try {
                                            markNewLayout.invoke(parent,view.getId());
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                        parent.markLayoutSeen();
                                    }
                                    parent = parent.getParent();
                                }
                                node.markUpdated();
                            }
                            Log.d(getName(), "markUpdated");
                    }

                };
                reactContext.runOnNativeModulesQueueThread(r);
            }
        });


    }
Run Code Online (Sandbox Code Playgroud)