Подтвердить что ты не робот

Невозможно изменить размер дочерних элементов линейного макета в встроенном модуле android

Полный код здесь

Видео с правильным поведением в java и неправильным в ответе на родной здесь

Я изменил линейный макет, чтобы реагировать на касание, изменяя размер левого дочернего элемента, пока правый ребенок занимает остальную часть пространства, имитируя горизонтальную прокрутку, которая может быть "открыта" или "закрыта", используя следующий код

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

В ответе native touch все еще вызывает этот метод и регистрирует ожидаемые значения, но размер детей не обновляется. Единственный раз, когда он обновляется, - это когда я снова переключаю видимость, а затем снова вижу. Вызов invalidate/requestLayout в представлении из java или forceUpdate из js не имеет никакого эффекта.

Есть ли какой-нибудь другой код, который мне нужно вызвать, чтобы аннулировать и перерисовать вид? Есть ли подсказка, которую мне нужно дать, чтобы отреагировать, что этот компонент прокручивается или реагирует на касание?

4b9b3361

Ответ 1

RN android действительно не обновляет макеты детей или видимость или изменения адаптера в большинстве условий. Вставляя крючки в пользовательский вид, когда требуется обновление, которое приведет к недействительности /requestLayout, вызовите этот код, в основном, восстанавливается нормальное поведение. Есть еще некоторые случаи, когда измерение происходит не так, как обычно, и я должен опубликовать Runedable Runnables, которые затем вызывают это недействительность. Работа с родителями node может быть не обязательно необходима во всех случаях, но это для некоторых.

В Менеджере просмотра

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


    }

Ответ 2

У меня была та же проблема, и я нашел ответ на эту давнюю проблему, связанную с реагированием на native repo.

Добавьте следующий код в свой собственный макет, и после этого нет необходимости даже вызывать requestLayout() или invalidate(). Изменения распространяются, как только вы обновляете свой макет LayoutParams. Это решение такое же, как те, что использовались в ReactPicker.java и ReactToolbar.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());
    }
};

Ответ 3

Попробуйте удалить содержимое макета по одному. Может быть, один из этих детей обернул контент. Вы можете использовать для него иерархический просмотрщик и uiautomatorviewer Также подумайте о весах. Если возможно, разместите данные иерархического просмотра.

Ответ 4

LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) leftView.getLayoutParams();
lp.width=newWidth;
leftView.setLayoutParams(lp);
leftView.requestLayout(); 

Выше код решит вашу проблему.