Почему SWT Составляет композит, иногда требуют, чтобы вызов изменил размер () к расположению правильно?

Я исправил проблему, переместив функцию обратного вызова после инициализации RecyclerView.

recyclerView = itemView.findViewById(R.id.recyclerView);
ItemTouchHelper.SimpleCallback ItemTouchHelperCallbackLeft = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT, this);
new ItemTouchHelper(ItemTouchHelperCallbackLeft).attachToRecyclerView(recyclerView);
21
задан Lii 22 November 2017 в 10:58
поделиться

4 ответа

Мне кажется, что кэш макета устарел и нуждается в обновлении .

Макеты в SWT поддерживают кеширование и обычно будут кешировать предпочтительные размеры элементов управления или что угодно, что им нравится:

public abstract class Layout {
    protected abstract Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache);
    protected boolean flushCache (Control control) {...}
    protected abstract void layout (Composite composite, boolean flushCache);
}

Я относительно новичок в программировании SWT (бывший программист Swing). ), но столкнулись с похожими ситуациями, в которых макет не был должным образом обновлен. Мне обычно удавалось разрешить их, используя другие методы компоновки, которые также заставят компоновщик очистить кеш:

layout(boolean changed)

layout(boolean changed, boolean allChildren)

Надеюсь, что это поможет ...

31
ответ дан 29 November 2019 в 06:25
поделиться

Тем временем я узнал немного больше о недостатках SWT при изменении или изменении размеров частей иерархии управления во времени выполнения. ScrolledComposites и ExpandBars должен также быть обновлен явно, когда должен адаптирует их минимальные или предпочтительные размеры содержимого.

Я записал немного вспомогательного метода, который подтверждает расположение иерархии управления для управления, которое изменилось:

public static void revalidateLayout (Control control) {

    Control c = control;
    do {
        if (c instanceof ExpandBar) {
            ExpandBar expandBar = (ExpandBar) c;
            for (ExpandItem expandItem : expandBar.getItems()) {
                expandItem
                    .setHeight(expandItem.getControl().computeSize(expandBar.getSize().x, SWT.DEFAULT, true).y);
            }
        }
        c = c.getParent();

    } while (c != null && c.getParent() != null && !(c instanceof ScrolledComposite));

    if (c instanceof ScrolledComposite) {
        ScrolledComposite scrolledComposite = (ScrolledComposite) c;
        if (scrolledComposite.getExpandHorizontal() || scrolledComposite.getExpandVertical()) {
            scrolledComposite
                .setMinSize(scrolledComposite.getContent().computeSize(SWT.DEFAULT, SWT.DEFAULT, true));
        } else {
            scrolledComposite.getContent().pack(true);
        }
    }
    if (c instanceof Composite) {
        Composite composite = (Composite) c;
        composite.layout(true, true);
    }
}
20
ответ дан 29 November 2019 в 06:25
поделиться

Компоновка компоновки отвечает за размещение дочерних элементов этого композита. Поэтому, если размер композита не изменяется, но относительные позиции и размеры дочерних элементов необходимо обновить, вы вызываете layout() для композита. Однако, если необходимо обновить размер или положение самого композита, вам нужно будет вызвать layout() для его родительского композита (и так далее, пока не дойдете до оболочки).

Практическое правило. Если вы добавили или удалили элемент управления или иным образом сделали что-то, требующее ретрансляции, поднимайтесь по иерархии виджетов до тех пор, пока не найдете композицию с полосами прокрутки и вызовите layout() на ней. Причина остановки в композите с полосами прокрутки состоит в том, что его размер не изменится в ответ на изменение - полосы прокрутки «поглотят» это.

Обратите внимание, что если изменение, требующее макета, не является новым или удаленным дочерним элементом, вам следует позвонить Composite.changed(new Control[] {changedControl}) перед вызовом макета.

15
ответ дан 29 November 2019 в 06:25
поделиться

Я только что узнал о Composite.changed (Control [] children). Есть обширная статья, которую я прочитал пару лет назад:

http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html

В этой статье также упоминается вызов Composite.layout (логическое значение изменено, логическое значение все) для обновления макета: «Вызов layout () аналогичен вызову layout (true), который сообщает ColumnLayout сбросить его кэши, прежде чем устанавливать границы детей ". Это все правильно, и что я делаю с тех пор. Но это не то, что нужно, так как он в основном сводит на нет преимущества кэша макета, когда вы хотите обновить макет, потому что один или несколько элементов управления изменили требования.

Представьте, что у вас есть набор виджетов StyledText в GridLayout, и вам нужно изменить размер одного из них. Вызов computeSize () для StyledText очень дорогой. Вместо этого:

Неправильно:

parent.layout(true);

... который вызывает computeSize () для всех дочерних элементов, даже если их требования не изменились. Вы должны сделать это:

Справа:

parent.changed(new Control[] { theChangedChild });

Затем либо

rootComposite.layout(false, true);

или

parent.layout(false);

Не очень интуитивно. Параметр для layout () просто имеет неправильное имя. Вместо того, чтобы называть его «измененным», его нужно было назвать «ignoreCache» или что-то в этом роде Интуитивно понятная вещь - передать «истину», когда что-то изменилось. Вместо этого вам нужно передать «false», но сделать недействительным кеш для только что измененного элемента управления с помощью change (), прежде чем вы сделаете ...

Обратите внимание, что вызов change () также рекурсивно делает недействительной кэш-память только для родительского элемента управления в его собственном родительском элементе, что полностью имеет смысл. Поэтому, когда вы вызываете layout (), вы должны вызывать его для корневого композита (чаще всего для Shell) со значением all = true, если только вы не знаете, что размер родительского элемента измененного элемента управления будет или не может измениться в ответ.

3
ответ дан 29 November 2019 в 06:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: