Дълбоко гмуркане в PageView в трептене (с персонализирани преходи)

Проучване на джаджа PageView и създаване на персонализирани преходи на страници

Тази статия е седмата в поредицата статии, които разглеждат задълбочено вградените джаджи на Flutter.

  1. ListView / ScrollPhysics
  2. TextFields
  3. FloatingActionButtons
  4. Hero Widget
  5. Трансформация джаджа
  6. С възможност за преместване / DragTarget

В тази статия ще разгледаме PageView, след което по-късно ще направим няколко персонализирани ефекта за него.

ЗАБЕЛЕЖКА: ListView Deep Dive е предвестник на тази статия. Елементите, обхванати в тази статия, няма да бъдат повторени, тъй като са почти еднакви. Можете да прочетете статията ми ListView тук

Проучване на PageViews на страницата

PageView е джаджа, която генерира превъртащи се страници на екрана. Това може да бъде фиксиран списък от страници или функция за съставяне, която изгражда повтарящи се страници. PageView действа подобно на ListView по смисъла на конструирането на елементи.

Видовете PageView са:

  1. показване на страници
  2. PageView.builder
  3. PageView.custom

PageView (конструктор по подразбиране)

Този тип взема фиксиран списък на деца (страници) и ги прави превъртащи се.

показване на страници (
  деца: <Джаджа> [
    Контейнер(
      цвят: Colors.pink,
    ),
    Контейнер(
      цвят: Colors.cyan,
    ),
    Контейнер(
      цвят: Colors.deepPurple,
    ),
  ],
)

Горният код дава следния резултат:

PageView.builder

Този конструктор има функция itemBuilder и itemCount, подобен на ListView.builder

PageView.builder (
  itemBuilder: (контекст, позиция) {
    return _buildPage ();
  }
  itemCount: listItemCount, // Може да бъде нула
)

Подобно на ListView.builder, това изгражда децата при поискване.

Ако itemCount е зададен на нула (не е зададен), може да се генерира безкраен списък от страници.

Например този код:

PageView.builder (
  itemBuilder: (контекст, позиция) {
    връщане контейнер (
      цвят: позиция% 2 == 0? Colors.pink: Colors.cyan,
    );
  }
)

Дава безкраен списък от страници с редуващи се розови и сини цветове:

Забележка: PageView.custom работи по същия начин като ListView.custom (обсъден по-рано Deep Dive) и няма да го обсъждаме тук.

ориентация

Всички видове изгледи на страници могат да имат хоризонтални или вертикално превъртащи се страници.

показване на страници (
  деца: <Джаджа> [
    // Добавете деца тук
  ],
  scrollDirection: Axis.vertical,
)

Горният код ни дава:

PageSnapping

Щракването на страницата ни позволява да поддържаме страницата на междинни стойности. Това става чрез изключване на атрибута pageSnapping. В този случай страницата няма да се превърта до цяло число и ще се държи като нормален ListView.

показване на страници (
  деца: <Джаджа> [
    // Добавете деца тук
  ],
  pageSnapping: false,
)

ScrollPhysics

PageView може да има персонализирано поведение на превъртане по същия начин като ListViews. Няма да повтаряме различни видове ScrollPhysics, тъй като това е обсъдено в ListView Deep Dive.

ScrollPhysics може да бъде променен с помощта на параметъра физика:

показване на страници (
  деца: <Джаджа> [
    // Добавете деца тук
  ],
  физика: BouncingScrollPhysics (),
)

Контрол на изглед на страница

PageView може да бъде контролиран програмно чрез прикачване на PageController.

// Външен метод за изграждане
PageController контролер = PageController ();
// Метод за вътрешно изграждане
показване на страници (
  контролер: контролер,
  деца: <Джаджа> [
    // Добавяне на деца
  ],
)

Позицията на превъртане, текущата страница и т.н. може да се провери с помощта на контролера.

Забележка: controller.currentPage връща двойна стойност. Например, когато страницата се прекарва, стойността преминава от 1 на 2 постепенно и не мигновено прескача до 2.

Добавяне на персонализирани преходи към PageViews

Нека обсъдим как да добавим няколко персонализирани прехода към страниците с помощта на Transform + PageView. Тази част ще използва широко джаджата Transform и препоръчвам да прочетете една от множеството статии на приспособлението.

Моите препоръки биха били Deep Dive, който написах и статията на WM Leler за Трансформация.

Преход 1

Конфигурацията

Първо използваме основен PageView.builder

PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
  }
  itemCount: 10,
)

За сега имаме 10 елемента

Използваме PageController и променлива, която държи стойността на currentPage.

Дефиниране на PageController и променливи:

PageController контролер = PageController ();
var currentPageValue = 0.0;

Актуализиране на променливата, когато PageView се превърта.

controller.addListener (() {
  setState (() {
    currentPageValue = controller.page;
  });
});

Накрая конструираме PageView.

Сега, нека проверим за три условия:

  1. Ако страницата е страницата, от която се прекарва пръст
  2. Ако страницата е страницата, към която се прекарва пръст
  3. Ако страницата е страница извън екрана
PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
    ако (позиция == currentPageValue.floor ()) {
    } else if (позиция == currentAnimationValue.floor () + 1) {
      
    } else {
      
    }
  }
  itemCount: 10,
)

Сега връщаме същата страница, но увита в джаджа Transform, за да трансформираме страниците си, когато я прекараме.

PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
    ако (позиция == currentPageValue.floor ()) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. завъртанеX (текущаPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else if (позиция == currentPageValue.floor () + 1) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. завъртанеX (текущаPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else {
      връщане контейнер (
        цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
        дете: Център (
          дете: текст (
            "Страница",
            стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
          ),
        ),
      );
    }
  }
  itemCount: 10,
)

Тук преобразуваме страницата, която се прекарва с пръст, и страницата, към която се прекарва.

currentPageValue.floor () ни дава страницата вляво и

currentPageValue.floor () ни дава страницата вдясно

В този пример завъртаме страницата по посока X, тъй като тя е прекарана от стойност на currentPageValue минус индекса в радианти. Можете да усилите ефекта, като умножите тази стойност.

Можем да променим това преобразуване и подравняване на трансформацията, за да ни даде множество видове преходи на нови страници.

Преход 2

Подобна структура на кода, само с различна трансформация:

PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
    ако (позиция == currentPageValue.floor ()) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. завъртанеY (текущаPageValue - позиция) .. завъртанеZ (текущаPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else if (позиция == currentPageValue.floor () + 1) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. завъртанеY (текущаPageValue - позиция) .. завъртанеZ (текущаPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else {
      връщане контейнер (
        цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
        дете: Център (
          дете: текст (
            "Страница",
            стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
          ),
        ),
      );
    }
  }
  itemCount: 10,
)

Тук ние се въртим около Y и Z оси.

Преход 3

Това е подобен тип преход миналия път, но с добавен 3-D ефект.

PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
    ако (позиция == currentPageValue.floor ()) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. setEntry (3, 2, 0.004) .. завъртанеY (currentPageValue - позиция) .. завъртанеZ (currentPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else if (позиция == currentPageValue.floor () + 1) {
      връщане Преобразуване (
        трансформация: Matrix4.identity () .. setEntry (3, 2, 0.004) .. завъртанеY (currentPageValue - позиция) .. завъртанеZ (currentPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else {
      връщане контейнер (
        цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
        дете: Център (
          дете: текст (
            "Страница",
            стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
          ),
        ),
      );
    }
  }
  itemCount: 10,
)

Линията

..setEntry (3, 2, 0.004)

дава на страниците 3-D подобен ефект.

Преход 4

PageView.builder (
  контролер: контролер,
  itemBuilder: (контекст, позиция) {
    ако (позиция == currentPageValue.floor ()) {
      връщане Преобразуване (
        подравняване: Alignment.center,
        трансформация: Matrix4.identity () .. setEntry (3, 2, 0.001)
          ..rotateX (currentPageValue - позиция)
          ..rotateY (currentPageValue - позиция)
          ..rotateZ (currentPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else if (позиция == currentPageValue.floor () + 1) {
      връщане Преобразуване (
        подравняване: Alignment.center,
        трансформация: Matrix4.identity () .. setEntry (3, 2, 0.001)
          ..rotateX (currentPageValue - позиция)
          ..rotateY (currentPageValue - позиция)
          ..rotateZ (currentPageValue - позиция),
        дете: контейнер (
          цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
          дете: Център (
            дете: текст (
              "Страница",
              стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
            ),
          ),
        ),
      );
    } else {
      връщане контейнер (
        цвят: позиция% 2 == 0? Colors.blue: Colors.pink,
        дете: Център (
          дете: текст (
            "Страница",
            стил: TextStyle (цвят: Colors.white, размер на шрифта: 22.0),
          ),
        ),
      );
    }
  }
  itemCount: 10,
)

Много повече видове могат да бъдат създадени чрез просто промяна на ъглите на завъртане, оси, подравняване и преводи.

Демо приложение с PageView

За да демонстрирам просто приложение с помощта на PageView във Flutter, създадох примерно приложение за изучаване на думи за GRE. Това приложение показва и позволява на потребителя да запазва най-трудните думи, използвайки SQLite, за да ги запише. Той също така има Text-To-Speech за произнасяне на самата дума.

Можете да намерите това приложение тук: https://github.com/deven98/FlutterGREWords

Това е за тази статия! Надявам се, че ви е харесало, и оставете няколко хлопки, ако сте го направили. Следвайте ме за още статии на Flutter и коментирайте всякаква обратна връзка, която може да имате относно тази статия.

Чувствайте се свободни да разгледате и другите ми профили и статии:

Някои от другите ми статии