> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/ru/ui/scroll-and-grid.md).

# Прокрутка и сетка

***

Прокручиваемые области и сетки позволяют легко создавать инвентари, списки, меню и карточные раскладки. В этом руководстве показаны правильные шаблоны для обоих вариантов, включая компоновку, ID и полосы прокрутки.

{% hint style="info" %}
Следуйте основам UI: начинайте с прямоугольников экрана, используйте cut для компоновки и всегда используйте `defer` для пар push/pop.
{% endhint %}

### Прокручиваемые области

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

```go
draw_scrollable_list :: proc(items: []string) {
    rect := UI.get_safe_screen_rect().inset(50);

    // Сначала зарезервируйте место для полосы прокрутки
    scroll_bar_area := rect.cut_right(8).inset(2);

    settings: Scroll_View_Settings;
    settings.vertical = true;
    settings.horizontal = false;
    settings.clip_padding = {10, 10, 10, 10};

    sv := UI.push_scroll_view(rect, "my_scroll_view", settings); {
        defer UI.pop_scroll_view();

        content := sv.content_rect;
        ts := UI.default_text_settings();
        ts.size = 24;

        for i: 0..<items.count {
            item_rect := content.cut_top(40);
            UI.text(item_rect, ts, items[i]);
        }
    }

    scroll_bar_rect := sv.compute_scroll_bar_rect(scroll_bar_area);

    UI.quad(scroll_bar_area, core_globals.white_sprite, {0.025, 0.025, 0.025, 1});
    UI.quad(scroll_bar_rect, core_globals.white_sprite, {0.1, 0.1, 0.1, 1});
}
```

**Важно:** Если полоса прокрутки находится внутри содержимого прокручиваемой области, это нарушит границы и поведение прокрутки. Всегда сначала вырезайте область для полосы прокрутки.

### Сетка

Используйте `Grid_Layout` для элементов одинакового размера, таких как ячейки инвентаря или сетки значков. Сетки начинаются в левом верхнем углу, продвигаются вправо, затем переходят на следующую строку.

```go
draw_inventory_grid :: proc(items: []string) {
    rect := UI.get_safe_screen_rect().inset(40);

    bs := UI.default_button_settings();
    ts := UI.default_text_settings();

    // 4 столбца x 6 строк в зависимости от количества элементов, 8 пунктов отступа
    grid := UI.make_grid_layout(rect, 4, 6, .ELEMENT_COUNT, 8);

    for i: 0..<items.count {
        UI.push_id("slot_%", {i});
        defer UI.pop_id();

        slot_rect := grid.next();
        if UI.button(slot_rect, bs, ts, items[i]).clicked {
            log_info("выбран элемент %", {i});
        }
    }
}
```

Если вы предпочитаете плитки фиксированного размера, используйте `.ELEMENT_SIZE` вместо `.ELEMENT_COUNT`:

```go
grid := UI.make_grid_layout(rect, 100, 100, .ELEMENT_SIZE, 8);
```

Метод `next()` обновляет состояние сетки:

```go
slot_rect := grid.next();
grid.index; // 0, 1, 2, ...
grid.cur_x; // столбец
grid.cur_y; // строка
```

### Прокручиваемые сетки

`Grid_Layout` автоматически расширяют прокручиваемые области, когда используются внутри них. Этот шаблон идеален для больших инвентарей:

```go
draw_scrollable_grid :: proc(items: []string) {
    rect := UI.get_safe_screen_rect().inset(50);
    scroll_bar_area := rect.cut_right(8).inset(2);

    settings: Scroll_View_Settings;
    settings.vertical = true;
    settings.horizontal = false;
    settings.clip_padding = {10, 10, 10, 10};

    sv := UI.push_scroll_view(rect, "inventory_scroll", settings); {
        defer UI.pop_scroll_view();

        grid := UI.make_grid_layout(sv.content_rect, 4, 6, .ELEMENT_COUNT, 8);
        bs := UI.default_button_settings();
        ts := UI.default_text_settings();

        for i: 0..<items.count {
            UI.push_id("slot_%", {i});
            defer UI.pop_id();

            slot_rect := grid.next();
            if UI.button(slot_rect, bs, ts, items[i].name).clicked {
                select_item(i);
            }
        }
    }

    scroll_bar_rect := sv.compute_scroll_bar_rect(scroll_bar_area);
    UI.quad(scroll_bar_area, core_globals.white_sprite, {0.025, 0.025, 0.025, 1});
    UI.quad(scroll_bar_rect, core_globals.white_sprite, {0.1, 0.1, 0.1, 1});
}
```

### Рекомендации

* Используйте `UI.push_id()` для повторяющихся элементов внутри списков или сеток.
* Сначала вырежьте область для полосы прокрутки, прежде чем создавать прокручиваемую область.
* Начинайте с `UI.get_safe_screen_rect()` и выводите всю компоновку из него.
* Сведите к минимуму взаимодействия, зависящие только от наведения (ориентация на mobile-first).
