【问题标题】:React Native: Resize custom UI componentReact Native:调整自定义 UI 组件的大小
【发布时间】:2016-10-03 16:37:26
【问题描述】:

我已经构建了一个非常简单的原生 Android UI 组件,我想在点击我的 react native 项目中的按钮时更新其子视图的大小。更准确地说,当单击此按钮时,我会向我的SimpleViewManager 发送一个命令,而SimpleViewManager 又会调用我的自定义视图的resizeLayout()

我可以验证resizeLayout() 是否被正确调用,但布局没有调整大小直到我旋转手机。显然,更改设备的方向会触发我的自定义视图的draw(),但我明确调用的invalidate() 也是如此。

其他布局更改(例如更改背景颜色而不是调整其大小)也可以正常工作。

我的自定义组件如下所示:

public class CustomComponent extends RelativeLayout {
    public CustomComponent(Context context) {
        super(context);
        init();
    }

    public CustomComponent(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomComponent(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.simple_layout, this);
    }

    public void resizeLayout(){
        LinearLayout childLayout = (LinearLayout) findViewById(R.id.child_layout);
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) childLayout.getLayoutParams();
        layoutParams.height = 50;
        layoutParams.width= 50;
        childLayout.setLayoutParams(layoutParams);

        invalidate();
    }
}

simple_layout.xml 看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/child_layout"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#ffee11"/>
</RelativeLayout>

任何帮助将不胜感激。

【问题讨论】:

    标签: android react-native


    【解决方案1】:

    经过几天的搜索,我终于在 this React Native 的 repo 中的旧报告问题中找到了答案。

    此解决方案与ReactPicker.javaReactToolbar.java 中使用的解决方案相同。我必须将以下代码放入我的 CustomComponent 中,之后甚至不需要调用 requestLayout()invalidate()。更新布局的 LayoutParams 后,更改就会立即传播。

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

    【讨论】:

    • 谢谢。帮助我解决了自定义添加的使用 java 视图未在层次结构中更新的问题。 (只需将您的自定义视图放在具有上述方法覆盖的容器中)
    • 哦,实际上,对于我来说,显然还有一步:添加上述容器视图(我继承自RelativeLayout)后,调用container.layout(0, 0, width, height);
    • 这对我帮助很大,我们的库被卡在 width:0, height:0 因为显然 ReactNative 应用程序中的 requestLayout 不是很有用。添加赏金。
    • 这对我很有帮助!谢谢!
    • 我不敢相信在 2019 年,React Native 仍然没有在他们的文档中提到这个问题。我在这上面浪费了几个小时。
    【解决方案2】:

    尝试运行

    requestLayout();
    

    而不是无效。

    这篇文章也有一些关于视图生命周期的好信息。

    Usage of forceLayout(), requestLayout() and invalidate()

    我还建议将视图 xml 中的根元素更改为

    <merge>
    

    这样,您的 CustomComponent 类就没有 RelativeLayout 作为其直接子级,除非您要这样做。

    【讨论】:

    • 您好,感谢您的回答。使用&lt;merge&gt; 实际上是个好主意。但是,我已经尝试在我的 CustomComponent 和 childLayout 中调用所有上述方法。该代码在 Android 项目中运行良好。当我将它与 React Native 结合使用时会出现问题。
    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 2019-11-05
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多