Flutter Basics for Beginners (Parte VII)

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:





  • Link para Github





  • Aula de imagem





  • Adicionar ativos e imagens





Bom código a todos!








All Articles