La plupart des applications mobiles contiennent diverses images.
Mais qu'en est-il sans eux ? Les images rendent l'interface utilisateur plus riche et plus claire.
Flutter a un support intégré pour les images. La classe la plus couramment utilisée est Image, que nous examinerons dans cet article.
Eh bien, allons-y !
Notre plan
Partie 1 - introduction au développement, première annexe, notion d'état ;
Partie 2 - fichier pubspec.yaml et utilisation de flutter sur la ligne de commande ;
Partie 3 - BottomNavigationBar et Navigator ;
Partie 4 - MVC. Nous utiliserons ce modèle particulier comme l'un des plus simples ;
Partie 5 - paquet http. Création de la classe Repository, premières demandes, listing des posts ;
Partie 6 - travailler avec des formulaires, des zones de texte et créer un article.
Partie 7 (article en cours) - travailler avec des images, afficher des images sous forme de grille, recevoir des images du réseau, ajouter les vôtres à l'application ;
Partie 8 - créer votre propre thème, ajouter des polices et des animations personnalisées ;
Partie 9 - un peu sur les tests ;
Ajouter des images au projet
Tout d'abord, essayons d'ajouter nos propres images au projet.
Attention : les images ajoutées à votre projet augmentent la taille de l'application, alors n'en faites pas trop !
Pour ajouter des images, nous devons créer un nouveau répertoire images
à la racine du projet :
images
pubspec.yaml:
# dependencies: flutter: sdk: flutter # ... # dev_dependencies: # ... # assets flutter: # , MaterialApp # Material Design uses-material-design: true # images # / , # images assets: - images/
. Github':
AlbumListPage
:
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
class AlbumListPage extends StatefulWidget {
@override
_AlbumListPageState createState() => _AlbumListPageState();
}
class _AlbumListPageState extends State<AlbumListPage> {
//
final fileImages = [
"applejack.png",
"fluttershy.png",
"rarity.png",
"starlight_glimmer.png",
"twillight_sparkle.png"
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Album List Page"),
),
body: _buildContent()
);
}
//
Widget _buildContent() {
// flutter_staggered_grid_view
// StaggeredGridView
return StaggeredGridView.countBuilder(
//
itemCount: fileImages.length,
// crossAxisCount
//
crossAxisCount: 8,
//
mainAxisSpacing: 10,
//
crossAxisSpacing: 10,
staggeredTileBuilder: (index) {
// 4 ( )
// 2 ( )
return StaggeredTile.count(4, index % 2 == 0 ? 4 : 8);
},
//
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.pinkAccent, width: 1)
),
// Image.asset
// pubspec.yaml
// asset Image
child: Image.asset("images/${fileImages[index]}"),
);
},
);
}
}
.
! .
REST API .
, AlbumListPage. , , .
.
Photo
:
// Post
class Photo {
final int _id;
final String _title;
final String _url;
Photo.fromJson(Map<String, dynamic> json) :
_id = json["id"],
_title = json["title"],
_url = json["url"];
}
class PhotoList {
final List<Photo> photos = [];
PhotoList.fromJson(List<dynamic> jsonItems) {
for (var jsonItem in jsonItems) {
photos.add(Photo.fromJson(jsonItem));
}
}
}
abstract class PhotoResult {}
class PhotoResultSuccess extends PhotoResult {
final PhotoList photoList;
PhotoResultSuccess(this.photoList);
}
//
class PhotoResultFailure extends PhotoResult {
final String error;
PhotoResultFailure(this.error);
}
//
class PhotoResultLoading extends PhotoResult {
PhotoResultLoading();
}
Repository
:
Future<PhotoList> fetchPhotos() async {
// URL,
//
final url = Uri.parse("$SERVER/photos");
// GET
final response = await http.get(url);
//
if (response.statusCode == 200) {
//
// json.decode
return PhotoList.fromJson(json.decode(response.body));
} else {
//
throw Exception("failed request");
}
}
AlbumController
:
// AlbumController PostController
class AlbumController extends ControllerMVC {
final Repository repo = Repository();
//
PhotoResult currentState = PhotoResultLoading();
void init() async {
try {
//
final photoList = await repo.fetchPhotos();
//
setState(() => currentState = PhotoResultSuccess(photoList));
} catch (error) {
//
setState(() => currentState = PhotoResultFailure(" "));
}
}
}
AlbumListPage
:
class AlbumListPage extends StatefulWidget {
@override
_AlbumListPageState createState() => _AlbumListPageState();
}
class _AlbumListPageState extends StateMVC {
//
// late
late AlbumController _controller;
_AlbumListPageState() : super(AlbumController()){
_controller = controller as AlbumController;
}
@override
void initState() {
super.initState();
// JSONPlaceholder
_controller.init();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Album List Page"),
),
body: _buildContent()
);
}
Widget _buildContent() {
//
final state = _controller.currentState;
if (state is PhotoResultLoading) {
//
return Center(
child: CircularProgressIndicator(),
);
} else if (state is PhotoResultFailure) {
//
return Center(
child: Text(
state.error,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline4!.copyWith(color: Colors.red)
),
);
} else {
final images = (state as PhotoResultSuccess).photoList.photos;
// StaggeredGridView
//
return StaggeredGridView.countBuilder(
//
itemCount: images.length,
// crossAxisCount
//
crossAxisCount: 8,
//
mainAxisSpacing: 10,
//
crossAxisSpacing: 10,
staggeredTileBuilder: (index) {
// 4 ( )
// 2 ( )
return StaggeredTile.count(4, index % 2 == 0 ? 4 : 8);
},
//
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.pinkAccent, width: 1)
),
// Image.network
//
child: Image.network(
images[index].url,
//
width: double.infinity,
height: double.infinity,
//
fit: BoxFit.cover,
//
// Loading...
loadingBuilder: (context, widget, imageChunkEvent) {
if (imageChunkEvent == null) {
return widget;
}
return Center(child: Text("Loading..."));
},
//
// Error!
errorBuilder: (context, obj, stacktrace) => Center(child: Text("Error!")),
),
);
},
);
}
}
}
.
!
, Flutter .
Image.network
n'est pas une panacée et il est donc préférable d'utiliser des bibliothèques spéciales avec plus de fonctionnalités dans les projets de combat.
L'une de ces bibliothèques prometteuses est cached_network_image
Il s'agit d'une bibliothèque assez simple qui prend en charge tous les problèmes et complexités techniques.
Liens utiles:
Bon code à tous !