Saltar al contenido

Ajuste la altura del niño de GridView de acuerdo con el contenido dinámico en flutter

Siéntete en la libertad de compartir nuestra página y códigos con otro, ayúdanos a hacer crecer nuestra comunidad.

Solución:

Editar: Agregué el constructor StaggeredTile.fit en el 0.2.0. Con eso, debería poder crear su aplicación ;-).

Tamaños de mosaicos dinámicos

Primer comentario:
Por ahora, con StaggeredGridView, el diseño y la representación de los niños son completamente independientes. Entonces, como dijo @rmtmckenzie, tendrá que obtener el tamaño de la imagen para crear sus mosaicos. Entonces puedes usar StaggeredTile.count constructor con un valor doble para el mainAxisCellCount parámetro: new StaggeredTile.count(x, x*h/w) (donde h es la altura de tu imagen y w su ancho. Para que el mosaico tenga la misma relación de aspecto que su imagen.

Lo que desea lograr necesitará más trabajo porque desea tener un área debajo de la imagen con algo de información. Para eso, creo que tendrá que calcular el ancho real de su mosaico antes de crearlo y usar el StaggeredTile.extent constructor.

Entiendo que esto no es ideal y actualmente estoy trabajando en una nueva forma de crear el diseño. Espero que te ayude a construir escenarios como el tuyo.

Primero déjame contarte cómo terminé aquí:

En mi aplicación, quería una vista de cuadrícula para mostrar mis tarjetas publicitarias y todos los datos que provienen de la base de datos del servidor y las imágenes provienen del servidor y las imágenes tienen diferentes tamaños. solía FutureBuilder para mapear esos datos a GridView. Primero intenté usar:

double cardWidth = MediaQuery.of(context).size.width / 3.3;
double cardHeight = MediaQuery.of(context).size.height / 3.6;
//....
GridView.count(
  childAspectRatio: cardWidth / cardHeight,
  //..

Como puede ver, no será dinámico para todas las tarjetas. Vine aquí como tú e intenté usar todas las respuestas, esas son geniales y tienes que abordar un poco para entender cómo, pero cualquiera de esas respuestas resolvió completamente mi problema.

Utilizando @RomainRastel respuesta y gracias a su StaggeredGridView paquete. Tuve que usar StaggeredGridView.count como mi constructor para mapear todas las cartas y para el staggeredTiles propiedad tuve que volver a mapear todas las tarjetas y agregar para cada StaggeredTile.fit(2).

Estoy seguro de que todavía no lo entendiste, así que probemos con un ejemplo simple para que no tengas que ir a otro lugar para encontrar una respuesta:

Primero agregue dependencia a pubspec.yaml, ahora la versión es 0.2.5. Puede consultar el último aquí.

dependencies:
 flutter_staggered_grid_view: ^0.2.5

Si está obteniendo datos de Internet o si va a copiar y pegar este ejemplo, también debe agregar esta dependencia: http: ^0.12.0.

import 'package:flutter/material.dart';

//this is what you need to have for flexible grid
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

//below two imports for fetching data from somewhere on the internet
import 'dart:convert';
import 'package:http/http.dart' as http;

//boilerplate that you use everywhere
class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: "Flexible GridView",
      home: HomePage(),
    );
  


//here is the flexible grid in FutureBuilder that map each and every item and add to a gridview with ad card
class HomePage extends StatelessWidget 
  //this is should be somewhere else but to keep things simple for you,
  Future fetchAds() async 
    //the link you want to data from, goes inside get
    final response = await http
        .get('https://blasanka.github.io/watch-ads/lib/data/ads.json');

    if (response.statusCode == 200) return json.decode(response.body);
    return [];
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Dynamic height GridView Demo"),
      ),
      body: FutureBuilder(
          future: fetchAds(),
          builder: (BuildContext context, AsyncSnapshot snapshot) 
            if (snapshot.hasData) 
              return new Padding(
                padding: const EdgeInsets.all(4.0),
                //this is what you actually need
                child: new StaggeredGridView.count(
                  crossAxisCount: 4, // I only need two card horizontally
                  padding: const EdgeInsets.all(2.0),
                  children: snapshot.data.map((item) 
                    //Do you need to go somewhere when you tap on this card, wrap using InkWell and add your route
                    return new AdCard(item);
                  ).toList(),

                  //Here is the place that we are getting flexible/ dynamic card for various images
                  staggeredTiles: snapshot.data
                      .map((_) => StaggeredTile.fit(2))
                      .toList(),
                  mainAxisSpacing: 3.0,
                  crossAxisSpacing: 4.0, // add some space
                ),
              );
             else 
              return Center(
                  child:
                      new CircularProgressIndicator()); // If there are no data show this
            
          ),
    );
  


//This is actually not need to be a StatefulWidget but in case, I have it
class AdCard extends StatefulWidget 
  AdCard(this.ad);

  final ad;

  _AdCardState createState() => _AdCardState();


class _AdCardState extends State 
  //to keep things readable
  var _ad;
  String _imageUrl;
  String _title;
  String _price;
  String _location;

  void initState() 
    setState(() 
      _ad = widget.ad;
      //if values are not null only we need to show them
      _imageUrl = (_ad['imageUrl'] != '')
          ? _ad['imageUrl']
          : 'https://uae.microless.com/cdn/no_image.jpg';
      _title = (_ad['title'] != '') ? _ad['title'] : '';
      _price = (_ad['price'] != '') ? _ad['price'] : '';
      _location = (_ad['location'] != '') ? _ad['location'] : '';
    );

    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Card(
      semanticContainer: false,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(4.0)),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Image.network(_imageUrl),
          Text(_title),
          Text('$ $_price'),
          Text(_location),
        ],
      ),
    );
  

Si tiene algún problema, aquí hay un ejemplo completo en un repositorio de git.

Ejemplo de vista de cuadrícula flexible de Flutter

¡Buena suerte!

Aquí hay dos cosas:

  1. Hay un paquete existente para hacer tal diseño.

  2. Para hacer el las imágenes se ven bien usar BoxFit.cover sobre el DecorationImage widget.

Hay toneladas de ejemplos en el repositorio de paquetes aquí.

Acabo de usar uno de los ejemplos y lo modifiqué para incluir imágenes:

ingrese la descripción de la imagen aquí

class GridViewExample extends StatefulWidget 
  @override
  _GridViewExampleState createState() => new _GridViewExampleState();


class _GridViewExampleState extends State 
  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      body: new Padding(
        padding: const EdgeInsets.all(8.0),
        child: new StaggeredGridView.countBuilder(
  crossAxisCount: 4,
  itemCount: 8,
  itemBuilder: (BuildContext context, int index) => new Container(
        decoration: new BoxDecoration(
          image: new DecorationImage(
            image: new NetworkImage("https://i.imgur.com/EVTkpZL.jpg"),
            fit: BoxFit.cover
          )
        )

        ),

  staggeredTileBuilder: (int index) =>
      new StaggeredTile.count(2, index.isEven ? 2 : 1),
  mainAxisSpacing: 4.0,
  crossAxisSpacing: 4.0,
),),

    );
  

Puntuaciones y reseñas

Al final de la post puedes encontrar las crónicas de otros creadores, tú igualmente eres capaz dejar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *