reckfellENGINE

Контейнеры: распределение места и прокрутка

Полная раскладка C#: Expand/Fill, предел ширины, пропорции и переход к концу списка.

На этой странице

Выберите владельца раскладки

КонтейнерДля чего
HBoxContainer / VBoxContainerСтрока / колонка
GridContainerТаблица с заданным числом колонок
FlowContainer и его вариантыПеренос элементов на следующую строку/колонку
MarginContainerОтступы вокруг содержимого
PanelContainerФон темы и место под содержимое
CenterContainer / AspectRatioContainerЦентрирование / сохранение пропорций
ScrollContainerПрокручиваемая видимая область
TabContainer / SplitContainerВкладки / разделяемые панели

Контейнер сортирует подходящих прямых дочерних Control. Промежуточная обычная Entity разрывает это отношение. Вкладывайте контейнеры, чтобы получить иерархию строк и колонок. Не добавляйте элементы поверх друг друга прямо в PanelContainer, если им нужна последовательная раскладка: поместите внутрь VBox/HBox.

В обычной раскладке участвуют непосредственные дочерние Control, которые видимы и не имеют TopLevel. Если элемент выпал из ряда, проверьте эти условия прежде, чем менять anchors. TopLevel выводит Control из обычной сортировки контейнера; это не способ закрепить его Position внутри строки.

Запустить пример

Добавьте UiSampleStyle.cs. Прикрепите ContainersDemo.cs к корню Control, соберите и запустите F6. Верхняя строка показывает распределение A/B/C, ниже — двадцать кнопок в прокрутке. Перейдите по списку клавишей Tab: FollowFocus подводит выбранный элемент в видимую область. Метод RevealLast можно вызвать из вашей кнопки перехода к концу.

ContainersDemo.cs
C#
using Reckfell;

public partial class ContainersDemo : Control
{
    public HBoxContainer Row { get; private set; } = null!;
    public PanelContainer A { get; private set; } = null!;
    public PanelContainer B { get; private set; } = null!;
    public PanelContainer C { get; private set; } = null!;
    public ScrollContainer Scroll { get; private set; } = null!;
    public Button Last { get; private set; } = null!;

    public override void _Ready()
    {
        UiSampleStyle.Prepare(this);
        var margin = new MarginContainer(); AddChild(margin);
        margin.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect, margin: 16);
        var column = new VBoxContainer(); margin.AddChild(column);
        column.AddChild(new Label { Text = UiSampleStyle.Text("Контейнеры и прокрутка", "Containers and scrolling") });
        Row = new HBoxContainer(); column.AddChild(Row);
        A = Item("A", 64); B = Item("B", 64); C = Item("C", 64);
        A.CustomMaximumSize = new Vector2(140, -1);
        A.SizeFlagsHorizontal = SizeFlags.ExpandFill; B.SizeFlagsHorizontal = SizeFlags.ExpandFill;
        B.SizeFlagsStretchRatio = 2; C.SizeFlagsHorizontal = SizeFlags.Fill;
        Row.AddChild(A); Row.AddChild(B); Row.AddChild(C);
        Scroll = new ScrollContainer
        {
            SizeFlagsVertical = SizeFlags.ExpandFill, FollowFocus = true,
            HorizontalScrollMode = ScrollContainer.ScrollMode.Disabled
        };
        column.AddChild(Scroll);
        var list = new VBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill }; Scroll.AddChild(list);
        for (int i = 1; i <= 20; i++)
        {
            Last = new Button { Text = UiSampleStyle.Text("Пункт ", "Item ") + i, CustomMinimumSize = new Vector2(0, 40) };
            list.AddChild(Last);
        }
    }

    private static PanelContainer Item(string text, float width)
    {
        var panel = new PanelContainer { CustomMinimumSize = new Vector2(width, 60) };
        panel.AddChild(new Label { Text = text, HorizontalAlignment = HorizontalAlignment.Center });
        return panel;
    }

    public void RevealLast()
    {
        Last.GrabFocus();
        Callable.From(() => Scroll.EnsureControlVisible(Last)).CallDeferred();
    }
}

Fill и Expand решают разные задачи

ФлагРезультат
FillЗаполнить выделенный контейнером прямоугольник
ExpandУчаствовать в распределении дополнительного места
ExpandFillПолучить дополнительное место и заполнить его
ShrinkBegin / Center / EndИспользовать меньший размер с указанным выравниванием
MaximizeДополнительный приоритет/использование максимума в поддерживающем контейнере; не синоним FullRect

У A и B включён ExpandFill, но A ограничена 140. Освободившееся место получает B; C не расширяется. SizeFlagsStretchRatio — относительный вес, не точный процент итоговой ширины: минимумы, максимумы и промежутки участвуют в расчёте. В BoxContainer Maximize усиливает приоритет растяжения у Expand; минимумы других элементов и maximum всё равно учитываются. Смысл флагов проверяйте для конкретного контейнера.

Прокрутка без разрастания окна

ScrollContainer получает доступную высоту через ExpandFill. Внутри — одна колонка с двадцатью элементами; её минимум по высоте больше видимой области. Горизонтальная прокрутка отключена, колонка заполняет доступную ширину. Если положить в список Control с несжимаемым текстом шире окна, отключение полосы не исправит содержимое: разрешите перенос или измените структуру.

EnsureControlVisible() требует потомка этого ScrollContainer и актуальных прямоугольников. После динамического изменения дерева дождитесь сортировки контейнеров. RevealLast откладывает обращение; не считайте Size сразу после AddChild окончательным результатом раскладки. FollowFocus удобен для клавиатуры, но не задаёт весь маршрут фокуса.

Диагностика

ПроблемаПричина / решение
Position сам возвращаетсяИм управляет родительский контейнер
Прямой дочерний элемент не раскладываетсяЭто должен быть видимый Control без TopLevel; после изменения дождитесь сортировки
Fill не растягивает строкуFill заполняет выделенную долю; распределение свободного места включает Expand
Два элемента не делят место 1:2Учитываются минимумы, максимумы и остальные участники
Скрытый элемент оставляет местоПроверьте, какой именно Control скрыт, и дождитесь сортировки
Прокрутки нет, а окно растётСлишком большой минимум у ScrollContainer или неверные SizeFlags его родителей
Переход к пункту не работает сразуРаскладка ещё не пересчитана либо объект не потомок ScrollContainer
Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.