Home > Software engineering >  Flutter How to stack image and total member text
Flutter How to stack image and total member text

Time:07-18

I was able to show the pictures as in the video by taking advantage of Johannes Milke's video that I left the link of. But that's not all I want. I need a structure that looks like these images but shows the total number of users. I leave the image of exactly what I want and my related codes.

What I want to achieve; Creating a structure where I can write the total number of users

There are a few packages on pub dev but not what I wanted. Thank you

Video:enter image description here

My stacked widget:

   import 'package:flutter/material.dart';

class StackedWidgets extends StatelessWidget {
  final List<Widget> items;
  final TextDirection direction;
  final double size;
  final double xShift;

  const StackedWidgets({
    Key? key,
    required this.items,
    this.direction = TextDirection.ltr,
    this.size = 100,
    this.xShift = 20,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final allItems = items
        .asMap()
        .map((index, item) {
          final left = size - xShift;

          final value = Container(
            width: size,
            height: size,
            child: item,
            margin: EdgeInsets.only(left: left * index),
          );

          return MapEntry(index, value);
        })
        .values
        .toList();

    return Stack(
      children: direction == TextDirection.ltr
          ? allItems.reversed.toList()
          : allItems,
    );
  }
}

Usage my stacked widget:

Widget buildStackedImages({
  TextDirection direction = TextDirection.ltr,
}) {
  final double size = 100;
  final double xShift = 20;
  final urlImages = [
    'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80',
    'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
    'https://images.unsplash.com/photo-1616766098956-c81f12114571?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80',
  ];

  final items = urlImages.map((urlImage) => buildImage(urlImage)).toList();

  return StackedWidgets(
    direction: direction,
    items: items,
    size: size,
    xShift: xShift,
  );
}

Widget buildImage(String urlImage) {
  final double borderSize = 5;

  return ClipOval(
    child: Container(
      padding: EdgeInsets.all(borderSize),
      color: Colors.white,
      child: ClipOval(
        child: Image.network(
          urlImage,
          fit: BoxFit.cover,
        ),
      ),
    ),
  );
}

CodePudding user response:

Add a label also to this class

   import 'package:flutter/material.dart';

class StackedWidgets extends StatelessWidget {
  final List<Widget> items;
  final TextDirection direction;
  final double size;
  final double xShift;
  final String lable;

  const StackedWidgets({
    Key? key,
    required this.items,
    this.direction = TextDirection.ltr,
    this.size = 100,
    this.xShift = 20,
    this.label = '',
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final allItems = items
        .asMap()
        .map((index, item) {
          final left = size - xShift;

          final value = Container(
            width: size,
            height: size,
            child: item,
            margin: EdgeInsets.only(left: left * index),
          );

          return MapEntry(index, value);
        })
        .values
        .toList();

    return Row(
      children: [
        Stack(
      children: direction == TextDirection.ltr
          ? allItems.reversed.toList()
          : allItems,
    ),
    Text(label),
    ]
    );
  }
}

In items pass the number widget and label too

return StackedWidgets(
    direction: direction,
    items: [...items, Container(
       width: 25,//you can also add padding if required 
        decoration: BoxDecoration(
         shape: BoxShape.circle,
         color: Colors.orange,
        ),
        child: Text(' 22'))],
    size: size,
    xShift: xShift,
   label: "users are here",
  );

CodePudding user response:

I will prefer this way,

Run on enter image description here

class InTEST extends StatefulWidget {
  const InTEST({Key? key}) : super(key: key);

  @override
  State<InTEST> createState() => _InTESTState();
}

class _InTESTState extends State<InTEST> {
  int maxRenderAvatar = 5;
  int numberOfActiveUser = 33;
  double size = 100;
  double borderSize = 5;
  Widget buildStackedImages({
    TextDirection direction = TextDirection.ltr,
  }) {
    List<String> urlImages = List.filled(
        numberOfActiveUser, //based on your list
        'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=633&q=80');

    List<Widget> items = [];

    final renderItemCount = numberOfActiveUser > maxRenderAvatar
        ? maxRenderAvatar
        : urlImages.length;
    for (int i = 0; i < renderItemCount; i  ) {
      items.add(
        Positioned(
          left: (i * size * .8),
          child: buildImage(
            urlImages[i],
          ),
        ),
      );
    }
    // add counter if  urlImages.length > maxRenderAvatar
    if (numberOfActiveUser > maxRenderAvatar) {
      items.add(
        Positioned(
          left: maxRenderAvatar * size * .8,
          child: Container(
            width: size,
            height: size,
            padding: EdgeInsets.all(borderSize),
            decoration: BoxDecoration(
              border: Border.all(color: Colors.white, width: 4),
              color: Colors.amber,
              shape: BoxShape.circle,
            ),
            alignment: Alignment.center,
            child: Text(
              "  ${urlImages.length - maxRenderAvatar}",
              style: TextStyle(
                fontSize: 23,
              ),
            ),
          ),
        ),
      );
    }

    return SizedBox(
      height: size   (borderSize * 2), //10 for borderSize
      width: MediaQuery.of(context).size.width,
      child: Stack(
        children: items,
      ),
    );
  }

  Widget buildImage(String urlImage) {
    return ClipOval(
      child: Container(
        padding: EdgeInsets.all(borderSize),
        color: Colors.white,
        child: ClipOval(
          child: Image.network(
            urlImage,
            width: size,
            height: size,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Slider(
              value: numberOfActiveUser.toDouble(),
              min: 0,
              max: 55,
              onChanged: (v) {
                numberOfActiveUser = v.toInt();
                setState(() {});
              }),
          Slider(
              value: maxRenderAvatar.toDouble(),
              min: 0,
              max: 42,
              onChanged: (v) {
                maxRenderAvatar = v.toInt();
                setState(() {});
              }),
          buildStackedImages(),
        ],
      ),
    );
  }
}
  • Related