init projet
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/pokemon.dart';
|
||||
import '../components/pokemon_type.dart';
|
||||
|
||||
// Vue détail d'un Pokémon. Elle est appelée par la route "/pokemon-detail". Elle prend en paramètre un Pokémon.
|
||||
// Elle affiche l'image du Pokémon, son nom, son numéro et ses types. Elle permet également de passer en mode shiny.
|
||||
// Elle hérite de la classe StatefulWidget car elle a besoin de gérer un état (le mode shiny).
|
||||
class PokemonDetailPage extends StatefulWidget {
|
||||
const PokemonDetailPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PokemonDetailPage> createState() => _PokemonDetailPageState();
|
||||
}
|
||||
|
||||
// La classe _PokemonDetailPageState hérite de la classe State. Elle permet de gérer l'état de la page.
|
||||
// Elle contient une variable _isShiny qui permet de savoir si le mode shiny est activé ou non.
|
||||
class _PokemonDetailPageState extends State<PokemonDetailPage> {
|
||||
// Variable qui permet de savoir si le mode shiny est activé ou non
|
||||
bool _isShiny = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// On récupère le Pokémon passé en paramètre de la route
|
||||
final Pokemon pokemon = ModalRoute.of(context)!.settings.arguments as Pokemon;
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Le GestureDetector va permettre de détecter un tap sur l'image du Pokémon
|
||||
GestureDetector(
|
||||
// L'image du Pokémon est une image en ligne. On utilise donc Image.network
|
||||
// On utilise la variable _isShiny pour savoir si on affiche l'image normale ou l'image shiny
|
||||
child: Image.network(_isShiny ? pokemon.shinyImageUrl : pokemon.imageUrl, width: 200),
|
||||
onTap:() {
|
||||
// Lorsqu'on tap sur l'image, on change la valeur de la variable _isShiny
|
||||
// Cela va permettre de changer l'image affichée
|
||||
// On utilise la méthode setState pour dire à Flutter que la valeur de la variable a changé
|
||||
setState(() {
|
||||
_isShiny = !_isShiny;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: pokemon.formatedName, // formatedName est une propriété calculée du modèle Pokemon
|
||||
style: const TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: " #${pokemon.id.toString().padLeft(4, "0")}",
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
PokemonTypeWidget(pokemon.type1),
|
||||
pokemon.type2 != null ? PokemonTypeWidget(pokemon.type2!) : Container(),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/pokemon.dart';
|
||||
import '../components/pokemon_tile.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb; // Platform is not supported on web
|
||||
|
||||
// Page de la liste des pokémons. Elle est appelée par la route "/". Elle affiche la liste des 151 premiers pokémons.
|
||||
// Elle hérite de la classe StatefulWidget car elle a besoin de gérer un état (la liste des pokémons).
|
||||
class PokemonListPage extends StatefulWidget {
|
||||
const PokemonListPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PokemonListPage> createState() => _PokemonListPageState();
|
||||
}
|
||||
|
||||
class _PokemonListPageState extends State<PokemonListPage> {
|
||||
|
||||
Widget _buildPokemonTile(BuildContext context, int index) {
|
||||
// On utilise un FutureBuilder pour afficher un pokémon à partir de son ID. L'index commençant à 0, on ajoute 1 pour le numéro du pokémon.
|
||||
// Le FutureBuilder va permettre d'afficher un widget en fonction de l'état du Future
|
||||
// Le FutureBuilder prend en paramètre un Future (ici Pokemon.fromID(index + 1))
|
||||
// Il prend aussi en paramètre une fonction qui va permettre de construire le widget en fonction de l'état du Future : builder: (context, snapshot) {}
|
||||
return FutureBuilder(
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
// Si le Future a réussi à récupérer les données, on affiche le widget PokemonTile
|
||||
if (snapshot.data == null) {
|
||||
return Text('Error while fetching pokemon #${index + 1}');
|
||||
}
|
||||
return PokemonTile(snapshot.data as Pokemon);
|
||||
} else if (snapshot.hasError) {
|
||||
// Si le Future a échoué à récupérer les données, on affiche un message d'erreur
|
||||
print(snapshot.error);
|
||||
return const Text('Erreur : ');
|
||||
} else {
|
||||
// Si le Future n'a pas encore récupéré les données, on affiche un widget de chargement
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: const CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
future: Pokemon.fromID(index + 1),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Liste des pokémons'),
|
||||
),
|
||||
body: Center(
|
||||
child: GridView.builder(
|
||||
// Le GridView permet d'afficher une liste de widgets sous forme de grille
|
||||
// On utilise le constructeur GridView.builder pour construire la grille
|
||||
// Le GridView.builder prend en paramètre un itemCount qui correspond au nombre d'éléments à afficher
|
||||
// Il prend aussi en paramètre un itemBuilder qui va permettre de construire chaque élément de la grille
|
||||
// Le GridView.builder prend aussi en paramètre un gridDelegate qui va permettre de définir le nombre de colonnes de la grille
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: kIsWeb ? 4 : 2, // On affiche 4 colonnes sur le web et 2 colonnes sur mobile
|
||||
),
|
||||
itemCount: 151, // On pourrait en mettre plus mais on va se limiter aux 151 premiers pokémons
|
||||
itemBuilder: _buildPokemonTile,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user