A maioria dos aplicativos móveis contém várias imagens.
Mas e sem eles? As imagens tornam a interface do usuário mais rica e clara.
Flutter possui suporte integrado para imagens. A classe mais comumente usada é Imagem, que veremos neste artigo.
Bem, vamos!
Nosso plano
Parte 1 - introdução ao desenvolvimento, primeiro apêndice, conceito de estado;
Parte 2 - arquivo pubspec.yaml e usando flutter na linha de comando;
Parte 3 - BottomNavigationBar e Navigator;
Parte 4 - MVC. Usaremos esse padrão específico como um dos mais simples;
Parte 5 - pacote http. Criação da classe Repositório, primeiras solicitações, listagem de postagens;
Parte 6 - trabalhando com formulários, caixas de texto e criando uma postagem.
Parte 7 (artigo atual) - trabalhar com fotos, exibir fotos em forma de grade, receber fotos da rede, adicionar as suas ao aplicativo;
Parte 8 - criando seu próprio tema, adicionando fontes e animações personalizadas;
Parte 9 - um pouco sobre testes;
Adicionando fotos ao projeto
Primeiro, vamos tentar adicionar nossas próprias fotos ao projeto.
Cuidado: as imagens adicionadas ao seu projeto aumentam o tamanho do aplicativo, portanto, não exagere!
Para adicionar imagens, precisamos criar um novo diretório images
na raiz do projeto:
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ão é uma panacéia e, portanto, é melhor usar bibliotecas especiais com mais funcionalidade em projetos de combate.
Uma dessas bibliotecas promissoras é cached_network_image
Esta é uma biblioteca bastante simples que cuida de todos os problemas técnicos e complexidades.
Links Úteis:
Bom código a todos!