Et dybt dyk ned i sidevisning i fladder (med brugerdefinerede overgange)

Udforskning af PageView-widgetten og oprettelse af tilpassede sideovergange

Denne artikel er den syvende i serien af ​​artikler, der ser grundigt på Flutter's indbyggede widgets.

  1. ListView / ScrollPhysics
  2. Tekstfelter
  3. FloatingActionButtons
  4. Helt-widget
  5. Transform widget
  6. Trækbart / DragTarget

I denne artikel vil vi se på PageView og derefter senere lave et par tilpassede effekter til det.

BEMÆRK: ListView Deep Dive er en forløber for denne artikel. Elementerne, der er omfattet af denne artikel, gentages ikke, da de næsten er de samme. Du kan læse min ListView-artikel her

Udforskning af sidevisninger

En PageView er en widget, der genererer rullbare sider på skærmen. Dette kan enten være en fast liste over sider eller en builder-funktion, der bygger gentagne sider. PageView fungerer som en ListView i betydningen at konstruere elementer.

Typerne af PageView er:

  1. af sidevisning
  2. PageView.builder
  3. PageView.custom

PageView (standardkonstruktør)

Denne type tager en fast liste over børn (sider) og gør dem rullbare.

af sidevisning (
  børn:  [
    Beholder(
      farve: Colors.pink,
    ),
    Beholder(
      farve: Colors.cyan,
    ),
    Beholder(
      farve: Colors.deepPurple,
    ),
  ],
)

Ovenstående kode giver følgende resultat:

PageView.builder

Denne konstruktør tager en itemBuilder-funktion og et objektkonti, der ligner ListView.builder

PageView.builder (
  itemBuilder: (kontekst, position) {
    return _buildPage ();
  },
  itemCount: listItemCount, // Kan være null
)

Ligesom en ListView.builder bygger dette børn efter behov.

Hvis varenCount er indstillet til null (ikke indstillet), kan der genereres en uendelig liste over sider.

For eksempel denne kode:

PageView.builder (
  itemBuilder: (kontekst, position) {
    returbeholder (
      farve: position% 2 == 0? Colors.pink: Colors.cyan,
    );
  },
)

Giver en uendelig liste over sider med skiftende lyserøde og cyanfarver:

Bemærk: PageView.custom fungerer på samme måde som ListView.custom (diskuteret i tidligere Deep Dive), og vi vil ikke diskutere det her.

Orientering

Alle typer sidevisninger kan have vandrette eller lodrette rulle sider.

af sidevisning (
  børn:  [
    // Tilføj børn her
  ],
  rullevejledning: Axis.vertical,
)

Ovenstående kode giver os:

PageSnapping

Sidesnapning giver os mulighed for at holde siden ved mellemværdier. Dette gøres ved at slukke for attributten pageSnapping. I dette tilfælde vil siden ikke rulle til en heltalposition og opføre sig som en normal ListView.

af sidevisning (
  børn:  [
    // Tilføj børn her
  ],
  sideSnapping: falsk,
)

ScrollPhysics

En PageView kan have tilpasset rulleopførsel på samme måde som ListViews. Vi vil ikke gentage forskellige typer ScrollPhysics, da det diskuteres i ListView Deep Dive.

ScrollPhysics kan ændres ved hjælp af fysikparameteren:

af sidevisning (
  børn:  [
    // Tilføj børn her
  ],
  fysik: BouncingScrollPhysics (),
)

Kontrol af en PageView

En PageView kan programmeres styret ved at tilslutte en PageController.

// Udenfor bygningsmetode
PageController controller = PageController ();
// Inside build-metode
af sidevisning (
  controller: controller,
  børn:  [
    // Tilføj børn
  ],
)

Rullepositionen, den aktuelle side osv. Kan kontrolleres ved hjælp af controlleren.

Bemærk: Controlleren.currentPage returnerer en dobbeltværdi. For eksempel, når siden vippes, går værdien gradvist fra 1 til 2 og springer ikke med det samme til 2.

Føjelse af tilpassede overgange til PageViews

Lad os diskutere at tilføje et par tilpasset overgang til siderne ved hjælp af Transform + PageView. Denne del vil bruge Transform-widgeten meget, og jeg anbefaler at du læser en af ​​de flere artikler på widgetten.

Mine anbefalinger ville være Deep Dive, jeg skrev, og WM Leler's Transform-artikel.

Overgang 1

Opsætningen

Vi bruger først en grundlæggende PageView.builder

PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
  },
  vare Antal: 10,
)

Lad os have 10 varer lige nu.

Vi bruger en PageController og en variabel, der har værdien af ​​den aktuelle side.

Definition af PageController og variabler:

PageController controller = PageController ();
var currentPageValue = 0,0;

Opdatering af variablen, når PageView rulles.

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

Endelig konstruerer vi PageView.

Lad os nu tjekke for tre forhold:

  1. Hvis siden er den side, der stryges fra
  2. Hvis siden er den side, der skubbes til
  3. Hvis siden er en side fra skærmen
PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
    if (position == currentPageValue.floor ()) {
    } andet hvis (position == currentAnimationValue.floor () + 1) {
      
    } andet {
      
    }
  },
  vare Antal: 10,
)

Nu returnerer vi den samme side, men indpakket i en Transform-widget for at transformere vores sider, når vi skubber den.

PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
    if (position == currentPageValue.floor ()) {
      returnere transformering (
        transform: Matrix4.identity () .. rotateX (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet hvis (position == currentPageValue.floor () + 1) {
      returnere transformering (
        transform: Matrix4.identity () .. rotateX (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet {
      returbeholder (
        farve: position% 2 == 0? Colors.blue: Colors.pink,
        barn: Center (
          barn: tekst (
            "Side",
            stil: TextStyle (farve: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  vare Antal: 10,
)

Her transformerer vi siden, der bliver skudt fra, og siden, der skubbes til.

currentPageValue.floor () giver os siden til venstre og

currentPageValue.floor () giver os siden til højre

I dette eksempel roterer vi siden i X-retningen, da den swipes med en værdi af currentPageValue minus indekset i stråler. Du kan forstærke effekten ved at multiplicere denne værdi.

Vi kan justere denne transformation og justering af transform for at give os flere typer nye sideovergange.

Overgang 2

Tilsvarende kodestruktur, bare med en anden transformation:

PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
    if (position == currentPageValue.floor ()) {
      returnere Transform (
        transform: Matrix4.identity () .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet hvis (position == currentPageValue.floor () + 1) {
      returnere Transform (
        transform: Matrix4.identity () .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet {
      returbeholder (
        farve: position% 2 == 0? Colors.blue: Colors.pink,
        barn: Center (
          barn: tekst (
            "Side",
            stil: TextStyle (farve: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  vare Antal: 10,
)

Her roterer vi omkring både Y- og Z-akserne.

Overgang 3

Dette er en lignende type overgang sidste gang, men med en 3D-effekt tilføjet.

PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
    if (position == currentPageValue.floor ()) {
      returnere Transform (
        transform: Matrix4.identitet () .. sætEntry (3, 2, 0,004) .. rotereY (strømPageValue - position) .. rotereZ (strømPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet hvis (position == currentPageValue.floor () + 1) {
      returnere Transform (
        transform: Matrix4.identitet () .. sætEntry (3, 2, 0,004) .. rotereY (strømPageValue - position) .. rotereZ (strømPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet {
      returbeholder (
        farve: position% 2 == 0? Colors.blue: Colors.pink,
        barn: Center (
          barn: tekst (
            "Side",
            stil: TextStyle (farve: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  vare Antal: 10,
)

Linjen

..setEntry (3, 2, 0,004)

giver siderne en 3D-lignende effekt.

Overgang 4

PageView.builder (
  controller: controller,
  itemBuilder: (kontekst, position) {
    if (position == currentPageValue.floor ()) {
      returnere Transform (
        justering: Alignment.center,
        transform: Matrix4.identitet () .. sætindgang (3, 2, 0,001)
          ..rotateX (currentPageValue - position)
          ..rotateY (currentPageValue - position)
          ..rotateZ (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet hvis (position == currentPageValue.floor () + 1) {
      returnere Transform (
        justering: Alignment.center,
        transform: Matrix4.identitet () .. sætindgang (3, 2, 0,001)
          ..rotateX (currentPageValue - position)
          ..rotateY (currentPageValue - position)
          ..rotateZ (currentPageValue - position),
        barn: beholder (
          farve: position% 2 == 0? Colors.blue: Colors.pink,
          barn: Center (
            barn: tekst (
              "Side",
              stil: TextStyle (farve: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } andet {
      returbeholder (
        farve: position% 2 == 0? Colors.blue: Colors.pink,
        barn: Center (
          barn: tekst (
            "Side",
            stil: TextStyle (farve: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  vare Antal: 10,
)

Meget flere typer kan oprettes ved blot at ændre rotationsvinkler, akser, justeringer og oversættelser.

Demo-app ved hjælp af PageView

For at demonstrere en simpel app ved hjælp af PageView i Flutter oprettede jeg en eksempelapp til at studere ord til GRE. Denne app viser og lader brugeren gemme de hårdeste ord ved hjælp af SQLite for at gemme dem. Det har også tekst-til-tale til at udtale selve ordet.

Du kan finde denne app her: https://github.com/deven98/FlutterGREWords

Det er det for denne artikel! Jeg håber, du nød det, og lad et par klapper være, hvis du gjorde det. Følg mig for flere Flutter-artikler og kommenter for alle feedback, du måtte have om denne artikel.

Tjek også mine andre profiler og artikler:

Nogle af mine andre artikler