Een diepe duik in paginaweergave in flutter (met aangepaste overgangen)

De paginaweergave-widget verkennen en aangepaste pagina-overgangen maken

Dit artikel is het zevende in de reeks artikelen waarin de ingebouwde widgets van Flutter nader worden bekeken.

  1. ListView / ScrollPhysics
  2. TextFields
  3. FloatingActionButtons
  4. Heldenwidget
  5. Widget transformeren
  6. Draggable / DragTarget

In dit artikel zullen we PageView bekijken en er later een paar aangepaste effecten voor maken.

OPMERKING: De ListView Deep Dive is een voorloper van dit artikel. De elementen die in dat artikel worden behandeld, worden niet herhaald omdat ze bijna hetzelfde zijn. U kunt mijn ListView-artikel hier lezen

Paginaweergaven verkennen

Een PageView is een widget die schuifbare pagina's op het scherm genereert. Dit kan een vaste lijst met pagina's zijn of een builderfunctie die herhalende pagina's bouwt. PageView werkt vergelijkbaar met een ListView in de zin van het construeren van elementen.

De soorten PageView zijn:

  1. Paginaweergave
  2. PageView.builder
  3. PageView.custom

PageView (standaardconstructor)

Dit type neemt een vaste lijst met kinderen (pagina's) en maakt ze schuifbaar.

Paginaweergave(
  kinderen:  [
    Houder(
      kleur: kleuren. roze,
    )
    Houder(
      kleur: Colors.cyan,
    )
    Houder(
      kleur: Colors.deepPurple,
    )
  ],
)

De bovenstaande code geeft het volgende resultaat:

PageView.builder

Deze constructor heeft de functie itemBuilder en een itemCount vergelijkbaar met ListView.builder

PageView.builder (
  itemBuilder: (context, positie) {
    return _buildPage ();
  },
  itemCount: listItemCount, // Kan null zijn
)

Net als een ListView.builder bouwt dit kinderen op aanvraag.

Als de itemCount is ingesteld op nul (niet ingesteld), kan een oneindige lijst met pagina's worden gegenereerd.

Bijvoorbeeld deze code:

PageView.builder (
  itemBuilder: (context, positie) {
    retourcontainer (
      kleur: positie% 2 == 0? Colors.pink: Colors.cyan,
    );
  },
)

Geeft een oneindige lijst met pagina's met afwisselend roze en cyaan kleuren:

Opmerking: PageView.custom werkt op dezelfde manier als ListView.custom (besproken in eerdere Deep Dive) en we zullen het hier niet bespreken.

oriëntering

Alle soorten paginaweergaven kunnen horizontale of verticaal scrollende pagina's hebben.

Paginaweergave(
  kinderen:  [
    // Voeg hier kinderen toe
  ],
  scrollDirection: Axis.vertical,
)

De bovenstaande code geeft ons:

PageSnapping

Met pagina-uitlijning kunnen we de pagina op tussenliggende waarden houden. Dit wordt gedaan door het kenmerk pageSnapping uit te schakelen. In dit geval zal de pagina niet naar een gehele positie scrollen en zich gedragen als een normale ListView.

Paginaweergave(
  kinderen:  [
    // Voeg hier kinderen toe
  ],
  pageSnapping: false,
)

ScrollPhysics

Een PageView kan aangepast schuifgedrag hebben op dezelfde manier als ListViews. We zullen verschillende soorten ScrollPhysics niet herhalen, omdat dit wordt besproken in de ListView Deep Dive.

ScrollPhysics kan worden gewijzigd met de parameter physics:

Paginaweergave(
  kinderen:  [
    // Voeg hier kinderen toe
  ],
  natuurkunde: BouncingScrollPhysics (),
)

Een paginaweergave besturen

Een PageView kan programmatisch worden bestuurd door een PageController te koppelen.

// Buitenbouwmethode
PageController controller = PageController ();
// Inside build-methode
Paginaweergave(
  controller: controller,
  kinderen:  [
    // Voeg kinderen toe
  ],
)

De schuifpositie, huidige pagina, enz. Kunnen worden gecontroleerd met de controller.

Opmerking: De controller.currentPage retourneert een dubbele waarde. Wanneer de pagina bijvoorbeeld wordt geveegd, gaat de waarde geleidelijk van 1 naar 2 en springt niet onmiddellijk naar 2.

Aangepaste overgangen toevoegen aan PageViews

Laten we het hebben over het toevoegen van een paar aangepaste overgangen aan de pagina's met Transform + PageView. In dit deel wordt de Transform-widget uitgebreid gebruikt en ik raad aan een van de meerdere artikelen in de widget te lezen.

Mijn aanbevelingen zijn de Deep Dive die ik heb geschreven en het Transform-artikel van WM Leler.

Overgang 1

De opzet

We gebruiken eerst een eenvoudige PageView.builder

PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
  },
  itemCount: 10,
)

Laten we nu 10 items hebben.

We gebruiken een PageController en een variabele die de waarde van de huidige pagina bevat.

PageController en variabelen definiëren:

PageController controller = PageController ();
var currentPageValue = 0.0;

De variabele bijwerken wanneer de PageView wordt gescrold.

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

Ten slotte construeren we de PageView.

Laten we nu eens kijken naar drie voorwaarden:

  1. Als de pagina afkomstig is van de pagina
  2. Als de pagina de pagina is waarnaar wordt geveegd
  3. Als de pagina een pagina buiten het scherm is
PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
    if (position == currentPageValue.floor ()) {
    } anders if (position == currentAnimationValue.floor () + 1) {
      
    } anders {
      
    }
  },
  itemCount: 10,
)

Nu keren we dezelfde pagina terug, maar verpakt in een Transform-widget om onze pagina's te transformeren wanneer we deze vegen.

PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
    if (position == currentPageValue.floor ()) {
      Return Transform (
        transform: Matrix4.identity () .. rotateX (currentPageValue - positie),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders if (position == currentPageValue.floor () + 1) {
      Return Transform (
        transform: Matrix4.identity () .. rotateX (currentPageValue - positie),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders {
      retourcontainer (
        kleur: positie% 2 == 0? Colors.blue: Colors.pink,
        kind: Center (
          child: Tekst (
            "Bladzijde",
            stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
          )
        )
      );
    }
  },
  itemCount: 10,
)

Hier transformeren we de pagina waarnaar wordt geveegd en de pagina waarnaar wordt geveegd.

currentPageValue.floor () geeft ons de pagina aan de linkerkant en

currentPageValue.floor () geeft ons de pagina aan de rechterkant

In dit voorbeeld roteren we de pagina in de X-richting terwijl deze wordt geveegd met een waarde van currentPageValue minus de index in radianten. U kunt het effect versterken door deze waarde te vermenigvuldigen.

We kunnen deze transformatie en aanpassing van de transformatie aanpassen om ons meerdere soorten nieuwe pagina-overgangen te geven.

Overgang 2

Soortgelijke codestructuur, alleen met een andere transformatie:

PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
    if (position == currentPageValue.floor ()) {
      Return Transform (
        transform: Matrix4.identity () .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders if (position == currentPageValue.floor () + 1) {
      Return Transform (
        transform: Matrix4.identity () .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders {
      retourcontainer (
        kleur: positie% 2 == 0? Colors.blue: Colors.pink,
        kind: Center (
          child: Tekst (
            "Bladzijde",
            stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
          )
        )
      );
    }
  },
  itemCount: 10,
)

Hier roteren we rond zowel de Y- als de Z-as.

Overgang 3

Dit is de vorige keer een vergelijkbaar type overgang, maar met een toegevoegd 3D-effect.

PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
    if (position == currentPageValue.floor ()) {
      Return Transform (
        transform: Matrix4.identity () .. setEntry (3, 2, 0.004) .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders if (position == currentPageValue.floor () + 1) {
      Return Transform (
        transform: Matrix4.identity () .. setEntry (3, 2, 0.004) .. rotateY (currentPageValue - position) .. rotateZ (currentPageValue - position),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders {
      retourcontainer (
        kleur: positie% 2 == 0? Colors.blue: Colors.pink,
        kind: Center (
          child: Tekst (
            "Bladzijde",
            stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
          )
        )
      );
    }
  },
  itemCount: 10,
)

De lijn

..setEntry (3, 2, 0.004)

geeft de pagina's een 3D-effect.

Overgang 4

PageView.builder (
  controller: controller,
  itemBuilder: (context, positie) {
    if (position == currentPageValue.floor ()) {
      Return Transform (
        uitlijning: Alignment.center,
        transform: Matrix4.identity () .. setEntry (3, 2, 0.001)
          ..rotateX (currentPageValue - positie)
          ..rotateY (currentPageValue - positie)
          ..rotateZ (currentPageValue - positie),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders if (position == currentPageValue.floor () + 1) {
      Return Transform (
        uitlijning: Alignment.center,
        transform: Matrix4.identity () .. setEntry (3, 2, 0.001)
          ..rotateX (currentPageValue - positie)
          ..rotateY (currentPageValue - positie)
          ..rotateZ (currentPageValue - positie),
        child: Container (
          kleur: positie% 2 == 0? Colors.blue: Colors.pink,
          kind: Center (
            child: Tekst (
              "Bladzijde",
              stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
            )
          )
        )
      );
    } anders {
      retourcontainer (
        kleur: positie% 2 == 0? Colors.blue: Colors.pink,
        kind: Center (
          child: Tekst (
            "Bladzijde",
            stijl: TextStyle (kleur: Colors.white, fontSize: 22.0),
          )
        )
      );
    }
  },
  itemCount: 10,
)

Er kunnen nog veel meer typen worden gemaakt door eenvoudig rotatiehoeken, assen, uitlijningen en vertalingen te wijzigen.

Demo-app met PageView

Om een ​​eenvoudige app met PageView in Flutter te demonstreren, heb ik een voorbeeldapp gemaakt om woorden voor de GRE te bestuderen. Deze app toont en laat de gebruiker de moeilijkste woorden opslaan met behulp van SQLite om ze op te slaan. Het heeft ook Text-To-Speech voor het uitspreken van het woord zelf.

Je kunt deze app hier vinden: https://github.com/deven98/FlutterGREWords

Dat is het voor dit artikel! Ik hoop dat je ervan genoten hebt en laat een paar klappen achter als je dat deed. Volg mij voor meer Flutter-artikelen en commentaar voor eventuele feedback over dit artikel.

Bekijk ook mijn andere profielen en artikelen:

Enkele van mijn andere artikelen