Conceptos básicos de Flutter para principiantes (Parte VII)

La mayoría de las aplicaciones móviles contienen varias imágenes.





Pero, ¿y sin ellos? Las imágenes hacen que la interfaz de usuario sea más rica y clara.





Flutter tiene soporte incorporado para imágenes. La clase más utilizada es Imagen, que veremos en este artículo.





¡Bueno, vamos!





Nuestro plan
  • Parte 1  - introducción al desarrollo, primer apéndice, concepto de estado;





  • Parte 2  : archivo pubspec.yaml y uso de flutter en la línea de comandos;





  • Parte 3  - BottomNavigationBar y Navigator;





  • Parte 4  - MVC. Usaremos este patrón en particular como uno de los más simples;





  • Parte 5  - paquete http. Creación de la clase Repository, primeras solicitudes, listado de publicaciones;





  • Parte 6 : trabajar con formularios, cuadros de texto y crear una publicación.





  • Parte 7 (artículo actual): trabajar con imágenes, mostrar imágenes en forma de cuadrícula, recibir imágenes de la red, agregar las suyas a la aplicación;





  • Parte 8: creación de su propio tema, agregando fuentes y animaciones personalizadas;





  • Parte 9: un poco sobre las pruebas;





Agregar imágenes al proyecto

Primero, intentemos agregar nuestras propias imágenes al proyecto.





Tenga cuidado: las imágenes agregadas a su proyecto aumentan el tamaño de la aplicación, ¡así que no se exceda!





Para agregar imágenes, necesitamos crear un nuevo directorio images



en la raíz del proyecto:





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



no es una panacea y por lo tanto es mejor utilizar bibliotecas especiales con más funcionalidad en proyectos de combate.





Una de estas bibliotecas prometedoras es cached_network_image





Esta es una biblioteca bastante simple que se ocupa de todos los problemas técnicos y complejidades.





Enlaces útiles:





  • Enlace a Github





  • Clase de imagen





  • Agregar activos e imágenes





¡Buen código para todos!








All Articles