Home > Back-end >  Flutter wrong size of image in list view
Flutter wrong size of image in list view

Time:12-01

I have created a list view with images in flutter. it works but the images is wrong size. It looks like this:

enter image description here

But what I want is this:

enter image description here

This is the code I am using:

SizedBox(
                      height: 300,
                      child: ListView.builder(
                        shrinkWrap: true,
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (BuildContext ctx, int index) {
                          return SizedBox(
                              width: MediaQuery.of(context).size.width * 0.5,
                              child: Card(
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(10),
                                  child: Image.file(
                                    File(_imageFileListM[index].path),
                                    fit: BoxFit.fitWidth,
                                  ),
                                ),
                                margin: const EdgeInsets.all(10),
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(20.0),
                                ),
                              ));
                        },
                        itemCount: _imageFileListM.length,
                      ))

What am I doing wrong?

CodePudding user response:

try this:

SizedBox(
          height: 300,
          child: ListView.builder(
            shrinkWrap: true,
            scrollDirection: Axis.horizontal,
            itemBuilder: (BuildContext ctx, int index) {
              return SizedBox(
                  width: MediaQuery.of(context).size.width * 0.5,
                  child: Card(
                    elevation: 0,
                    color: Colors.transparent,
                    surfaceTintColor: Colors.transparent,
                    child: Align(
                      alignment: Alignment.center,
                      child: Container(
                        clipBehavior: Clip.antiAlias,
                        decoration: BoxDecoration(
                          color: Colors.transparent,
                          borderRadius: BorderRadius.circular(10),
                        ),
                        child: Image.file(
                          File(_imageFileListM[index].path),
                          fit: BoxFit.contain,
                        ),
                      ),
                    ),
                    margin: const EdgeInsets.all(10),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20.0),
                    ),
                  ));
            },
            itemCount: _imageFileListM.length,
          )),

enter image description here

CodePudding user response:

use container widget Box decoration property like this may help you

Container( height: 200.h, width: double.infinity, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("Enter your path") ), color: baseColor2, borderRadius: BorderRadius.only( bottomLeft:Radius.circular(20.r), bottomRight:Radius.circular(20.r))),

),

CodePudding user response:

Just wrap your list element with FittedBox like this:

SizedBox(
  height: 300,
  child: ListView.builder(
    shrinkWrap: true,
    scrollDirection: Axis.horizontal,
    itemBuilder: (BuildContext ctx, int index) {
      return SizedBox(
          width: MediaQuery.of(context).size.width * 0.5,
          child: FittedBox(
            child: Card(
              child: ClipRRect(
                borderRadius: BorderRadius.circular(20),
                child: Image.file(
                  File(_imageFileListM[index].path),
                  fit: BoxFit.fitWidth,
                ),
              ),
              margin: const EdgeInsets.all(10),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20.0),
              ),
            ),
          ));
    },
    itemCount: _imageFileListM.length,
  )))

CodePudding user response:

A simple way to achieve this is to use Stack and position.

Stack allows widgets to overlap each other. Positioned allows you to render its child at a specific location within the stack.

The stack is pretty much like a column but the widgets are rendered on top of each other therefore you need to specify how they should render.

This would be your main Image Widget:

  1. The image is wrapped in an expanded-sized box to cover the whole space.

  2. positioned is set to bottom 0 will stick the widget to the bottom. left and right are specified to be 0 so the widget also expands horizontally.

class ImageWidget extends StatelessWidget {
  final String url;
  const ImageWidget({super.key, required this.url});

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(16),
      child: Stack(
        children: [
          SizedBox.expand(
            child: Image.network(
              url,
              fit: BoxFit.contain,
            ),
          ),
          const Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: ImageChildWidget(),
          ),
        ],
      ),
    );
  }
}

This would be the bottom part. you can replace this with anything you'd like.

class ImageChildWidget extends StatelessWidget {
  const ImageChildWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return const ColoredBox(
      color: Color.fromARGB(155, 0, 0, 0),
      child: Padding(
        padding: EdgeInsets.all(8),
        child: Text(
          'Some Long Text',
          style: TextStyle(
            color: Colors.white,
            fontSize: 16,
          ),
        ),
      ),
    );
  }
}

You also have a grid view, it's easy with gridDelegate

  • crossAxisCount: 2, says that you want 2 elements per row
  • mainAxisSpacing: 16, says that you want a padding of 16 vertically
  • crossAxisSpacing: 16, says that you want a padding of 16 horizontally
class GridExample extends StatefulWidget {
  const GridExample({super.key});

  @override
  State<GridExample> createState() => GridExampleState();
}

class GridExampleState extends State<GridExample> {
  // Generate a random list of images
  List<String> urls = List.generate(
    10,
    (_) {
      int random = Random().nextInt(500)   250; // 250-500
      return 'https://picsum.photos/$random/$random';
    },
  );

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      key: widget.key,
      itemCount: urls.length,
      padding: const EdgeInsets.all(16),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        mainAxisSpacing: 16,
        crossAxisSpacing: 16,
      ),
      itemBuilder: (context, index) {
        return ImageWidget(
          key: ValueKey(urls[index]),
          url: urls[index],
        );
      },
    );
  }
}

Full code sample.

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: GridExample(
            key: ValueKey('grid'),
          ),
        ),
      ),
    );
  }
}

class GridExample extends StatefulWidget {
  const GridExample({super.key});

  @override
  State<GridExample> createState() => GridExampleState();
}

class GridExampleState extends State<GridExample> {
  // Generate a random list of images
  List<String> urls = List.generate(
    10,
    (_) {
      int random = Random().nextInt(500)   250; // 250-500
      return 'https://picsum.photos/$random/$random';
    },
  );

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      key: widget.key,
      itemCount: urls.length,
      padding: const EdgeInsets.all(16),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        mainAxisSpacing: 16,
        crossAxisSpacing: 16,
      ),
      itemBuilder: (context, index) {
        return ImageWidget(
          key: ValueKey(urls[index]),
          url: urls[index],
        );
      },
    );
  }
}

class ImageWidget extends StatelessWidget {
  final String url;
  const ImageWidget({super.key, required this.url});

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(16),
      child: Stack(
        children: [
          SizedBox.expand(
            child: Image.network(
              url,
              fit: BoxFit.contain,
            ),
          ),
          const Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: ImageChildWidget(),
          ),
        ],
      ),
    );
  }
}

class ImageChildWidget extends StatelessWidget {
  const ImageChildWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return const ColoredBox(
      color: Color.fromARGB(155, 0, 0, 0),
      child: Padding(
        padding: EdgeInsets.all(8),
        child: Text(
          'Some Long Text',
          style: TextStyle(
            color: Colors.white,
            fontSize: 16,
          ),
        ),
      ),
    );
  }
}

End result:

enter image description here

  • Related