Ask the assistant
0/400
Your question is processed by an AI service and kept to improve answers. Do not enter personal data.

    ReeelScroll

    This page has not been translated into English yet. The Russian original is below.

    Прокручиваемый список с поддержкой фокуса и клавиатурного управления. Поддерживает вертикальную и горизонтальную прокрутку, вложенные скроллы с делегацией навигации.

    Тип: multi-child

    ReeelScroll itemCount:3
      #config direction:horizontal spacing:20
      @Macros id:itemBuilder index:0 isFocused:false
        Text $"Элемент ${index}"

    Два режима работы

    1. Macro mode — для однотипных элементов

    Требуется itemCount + @Macros id:itemBuilder . Каждый элемент строится по одному шаблону. Идеален с #data для data-driven списков.

    ReeelScroll itemCount:5
      #config direction:horizontal spacing:24
        #padding symmetric horizontal:80
      #data
        :# title:"Фильм 1" badge:"4K"
        :# title:"Фильм 2" badge:"HDR"
        :# title:"Фильм 3" badge:"Новое"
        :# title:"Фильм 4" badge:"TOP"
        :# title:"Фильм 5" badge:"4K"
      @Macros id:itemBuilder index:0 isFocused:false
        $MovieCard title:{data[index]['title']} badge:{data[index]['badge']}
      @Macros id:selectorBuilder isFocused:false
        DecoratedBox
          #decoration
            #borderRadius circular 20
            #border fromBorderSide
              #side color:{isFocused ? $focusColor : 0x00} width:3

    2. Children mode — для разнородных элементов

    Без itemCount и @Macros id:itemBuilder . Дочерние элементы (кроме макросов) используются напрямую как items списка. itemCount определяется автоматически по количеству дочерних.

    ReeelScroll
      #config direction:vertical spacing:42
    
      // Каждый дочерний элемент — отдельный item скролла
      // Column внутри вертикального скролла — обязательно size:min
      Column crossAxisAlignment:stretch mainAxisSize:min
        $NavBar
        $HeroBanner
    
      Column crossAxisAlignment:start spacing:24 mainAxisSize:min
        $SectionHeader "Рекомендации"
        SizedBox height:288
          // Вложенный горизонтальный скролл (macro mode)
          ReeelScroll itemCount:6
            #config direction:horizontal spacing:24
            @Macros id:itemBuilder index:0 isFocused:false
              $Card title:{data[index]['title']}
    
      $PromoBanner title:"Промо" subtitle:"Текст" buttonText:"Кнопка"
    
      SizedBox height:80
    
      @Macros id:selectorBuilder isFocused:false
        SizedBox

    Параметры

    Параметр Тип Default Описание
    itemCount int children.length Количество элементов (обязателен в macro mode, опционален в children mode)
    initialIndex int 0 Начальный индекс фокуса
    autofocus bool false Автоматический захват фокуса при создании
    onIndexChanged callback — (index, isFocused){...} — вызывается при смене фокуса
    onSelect callback — (index){...} — вызывается при выборе элемента (Enter/OK)

    Конфигурация ( #config )

    ReeelScroll itemCount:10
      #config direction:horizontal spacing:20 shrinkWrap:true
        #padding symmetric horizontal:50
    Параметр Тип Default Описание
    direction vertical / horizontal vertical Направление прокрутки
    spacing double 0 Расстояние между элементами
    crossSpacing double 0 Расстояние по поперечной оси (для grid)
    shrinkWrap bool false Размер по содержимому (без бесконечной прокрутки)
    clampEdges bool true Ограничение прокрутки краями содержимого
    enableDragScroll bool true Поддержка перетаскивания мышью
    keepAliveEnabled bool false Сохранять состояние невидимых элементов
    cacheExtent double — Область предзагрузки за пределами видимой области
    scrollWheelSensitivity double 1.0 Чувствительность колёсика мыши
    defaultBehavior center / ensureVisible center Поведение позиционирования при фокусе

    Отступы

    #config direction:horizontal
      #padding symmetric horizontal:80
      // или
      #padding only left:80 top:20
      // или
      #padding all:20

    Grid-раскладка

    #config direction:vertical
      #gridDelegate fixedCount 3          // 3 колонки
      // или
      #gridDelegate maxExtent 200         // максимальная ширина элемента 200

    Анимация прокрутки

    #config
      #animationConfig curved
        curve:easeOutCubic
        duration:300ms
      // или
      #animationConfig spring
        stiffness:200.0
        damping:25.0

    Макросы-билдеры

    Все макросы-билдеры работают в обоих режимах (macro и children).

    itemBuilder (только macro mode)

    Шаблон для построения каждого элемента. Получает index и isFocused :

    @Macros id:itemBuilder index:0 isFocused:false
      Text $"Элемент ${index}, фокус: ${isFocused}"

    selectorBuilder

    Декоратор фокуса — оборачивает каждый элемент. Получает isFocused :

    @Macros id:selectorBuilder isFocused:false
      DecoratedBox
        #decoration
          #borderRadius circular 20
          #border fromBorderSide
            #side color:{isFocused ? $focusColor : 0x00} width:3

    separatorBuilder

    Разделитель между элементами. Получает index :

    @Macros id:separatorBuilder index:0
      SizedBox width:1
        ColoredBox color:$dividerColor

    underlayBuilder

    Фон под каждым элементом. Получает index :

    @Macros id:underlayBuilder index:0
      ColoredBox color:0xffc0c0c0

    #data + индексный доступ

    Data-driven подход для однотипных элементов. Данные описываются в #data через позиционные структуры ( :# ), доступ — через {data[index]['field']} :

    ReeelScroll itemCount:4
      #config direction:horizontal spacing:24
        #padding symmetric horizontal:80
      #data
        :# title:"Звёздные врата" subtitle:"Сезон 3, Серия 7" progress:0.67
        :# title:"Тёмная башня" subtitle:"Сезон 1, Серия 4" progress:0.45
        :# title:"Хроники Нарнии" subtitle:"Сезон 2, Серия 1" progress:0.12
        :# title:"Мандалорец" subtitle:"Сезон 3, Серия 2" progress:0.89
      @Macros id:itemBuilder index:0 isFocused:false
        $ContinueWatchingCard
          title:{data[index]['title']}
          subtitle:{data[index]['subtitle']}
          progress:{data[index]['progress']}

    Преимущества:

    • Данные отделены от шаблона — один макрос карточки для всех элементов
    • Компактнее, чем Switcher с N вариантами
    • Готовность к будущим генераторам (загрузка данных с сервера)

    Примеры

    Горизонтальный скролл карточек с #data

    SizedBox height:288
      ReeelScroll itemCount:6
        #config direction:horizontal spacing:24
          #padding symmetric horizontal:80
        #data
          :# badge:"Боевик"
          :# badge:"Драма"
          :# badge:"Комедия"
          :# badge:"Триллер"
          :# badge:"Фантастика"
          :# badge:"Детектив"
        @Macros id:itemBuilder index:0 isFocused:false
          $HorizontalCard badge:{data[index]['badge']}
        @Macros id:selectorBuilder isFocused:false
          DecoratedBox
            #decoration
              #borderRadius circular 24
              #border fromBorderSide
                #side color:{isFocused ? $focusColor : 0x00} width:3

    Вертикальный скролл страницы (children mode)

    ReeelScroll
      #config direction:vertical spacing:42
        #padding only top:0
    
      // Секция 1 — шапка (size:min — обязательно для Column в вертикальном скролле)
      Column crossAxisAlignment:stretch mainAxisSize:min
        $NavBar
        $HeroBanner
    
      // Секция 2 — карусель рекомендаций
      Column crossAxisAlignment:start spacing:24 mainAxisSize:min
        $SectionHeader "Рекомендации"
        SizedBox height:288
          ReeelScroll itemCount:6
            #config direction:horizontal spacing:24
              #padding symmetric horizontal:80
            #data
              :# title:"Фильм 1" badge:"4K"
              :# title:"Фильм 2" badge:"HDR"
            @Macros id:itemBuilder index:0 isFocused:false
              $MovieCard title:{data[index]['title']} badge:{data[index]['badge']}
            @Macros id:selectorBuilder isFocused:false
              DecoratedBox
                #decoration
                  #borderRadius circular 20
                  #border fromBorderSide
                    #side color:{isFocused ? $focusColor : 0x00} width:3
    
      // Секция 3 — баннер
      $PromoBanner title:"Промо" subtitle:"Текст акции" buttonText:"Подробнее"
    
      // Footer
      SizedBox height:80
    
      @Macros id:selectorBuilder isFocused:false
        SizedBox

    Смешанные типы в itemBuilder (Switcher + #data )

    Когда первый элемент структурно отличается от остальных:

    ReeelScroll itemCount:7
      #config direction:horizontal spacing:24
        #padding symmetric horizontal:80
      @Macros id:itemBuilder index:0 isFocused:false
        Switcher $index
          // Default — обычная карточка
          $VerticalCard rating:"7.0" badge:"4K"
          // Первый элемент — промо-карточка
          $PromoCard id:0 price:"12$" subtitle:"в месяц"
          $VerticalCard id:1 rating:"8.5" badge:"Новое"
          $VerticalCard id:2 rating:"7.8" badge:"4K"
          $VerticalCard id:3 rating:"9.1" badge:"TOP"

    Bad practices

    Switcher с N однотипными элементами вместо #data

    // BAD — дублирование шаблона, данные вшиты в каждый вариант
    @Macros id:itemBuilder index:0 isFocused:false
      Switcher $index
        $Card title:"Третий"
        $Card id:0 title:"Первый"
        $Card id:1 title:"Второй"
    // GOOD — данные отделены, один шаблон
    #data
      :# title:"Первый"
      :# title:"Второй"
      :# title:"Третий"
    @Macros id:itemBuilder index:0 isFocused:false
      $Card title:{data[index]['title']}

    itemBuilder + Switcher для разнородных секций

    // BAD — вынужденный Switcher с десятком вариантов
    ReeelScroll itemCount:10
      @Macros id:itemBuilder index:0 isFocused:false
        Switcher $index
          SizedBox height:80
          Column id:0
            $NavBar
          Column id:1
            $SectionHeader "Рекомендации"
          ...9 дочерних с id...
    // GOOD — children mode, каждая секция = прямой дочерний элемент
    ReeelScroll
      Column mainAxisSize:min
        $NavBar
      Column mainAxisSize:min
        $SectionHeader "Рекомендации"
        ...
      SizedBox height:80

    Best practices

    • Macro mode + #data для однотипных списков (карточки, чипсы, табы)
    • Children mode для разнородных секций (страницы с разными блоками)
    • Данные отдельно от шаблона : #data с :# -элементами + {data[index]['field']} в itemBuilder
    • selectorBuilder для визуального фокуса — бордер, тень, масштаб
    • Вложенные скроллы : внешний (vertical, children mode) + внутренние (horizontal, macro mode с #data )

    Column/Row внутри скролла — size:min

    Column и Row по умолчанию имеют size:max и пытаются занять всё доступное пространство по главной оси. Внутри ReeelScroll каждый item получает maxHeight / maxWidth , равный viewport'у. Это значит:

    • Column (главная ось — vertical) с size:max внутри вертикального скролла растянется на весь viewport
    • Row (главная ось — horizontal) с size:max внутри горизонтального скролла растянется на весь viewport

    В обоих случаях первый элемент займёт весь экран, вытеснив остальные секции.

    Правило: Column/Row как прямой item скролла по той же оси → всегда size:min .

    // BAD — секции невидимы, первый Column занимает весь viewport
    ReeelScroll
      #config direction:vertical spacing:42
      Column crossAxisAlignment:stretch
        $NavBar
        $HeroBanner
      Column crossAxisAlignment:start spacing:24
        $SectionHeader "Рекомендации"
        ...
    
    // GOOD — каждая секция занимает ровно столько, сколько нужно
    ReeelScroll
      #config direction:vertical spacing:42
      Column crossAxisAlignment:stretch mainAxisSize:min
        $NavBar
        $HeroBanner
      Column crossAxisAlignment:start spacing:24 mainAxisSize:min
        $SectionHeader "Рекомендации"
        ...

    Это не влияет на cross-axis: Column с size:max внутри горизонтального скролла безопасен (cross-axis ограничен viewport'ом).

    Ограничение размера дочерних элементов

    Если дочерний элемент скролла не имеет естественного ограничения по главной оси (Column, Row без size:min , неограниченный контейнер), оберни его в SizedBox с явным размером:

    // Горизонтальный вложенный скролл — ограничен по height (cross-axis)
    SizedBox height:288
      ReeelScroll itemCount:6
        #config direction:horizontal spacing:24
        ...
    
    // Элемент скролла без intrinsic height — ограничен SizedBox
    ReeelScroll
      #config direction:vertical
      SizedBox height:700
        Stack
          ...

    See also

    • Switcher — условный рендеринг внутри itemBuilder для смешанных типов элементов
    DOCS
    dark_mode_baseline
    RU/EN
    menu_baseline