简体   繁体   English

如何在 Flutter 中创建这样的 UI

[英]How to create UI like this in Flutter

I'm building an App I have to build UI like below but I don't have any idea that how to create UI like this.我正在构建一个应用程序,我必须像下面这样构建 UI,但我不知道如何创建这样的 UI。 Kindly guide me through this.请指导我完成这个。

在此处输入图像描述

 var listImages = [
  "https://source.unsplash.com/random/200x200?sig=1",
  "https://source.unsplash.com/random/200x200?sig=2",
  "https://source.unsplash.com/random/200x200?sig=3",
  "https://source.unsplash.com/random/200x200?sig=4",
  "https://source.unsplash.com/random/200x200?sig=5"
];


 Padding(
        padding: const EdgeInsets.all(8.0),
        child: Stack(
          children: [
            for (int i = 0; i < (listImages.length>=4?4:listImages.length); i++)
              Transform.translate(
                offset: Offset(i == 0 ? 0.0 : i * 44, 0),
                child: Container(
                  height: 70,
                  width: 70,
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(25),
                    color: Colors.black87,
                  ),
                  clipBehavior: Clip.hardEdge,
                  child: (i+1)>=4?Text("+ ${listImages.length-3}",style:const TextStyle(color: Colors.green),):Image.network(listImages[i]),
                ),
              )
          ],
        ),
      )

Below are the methods used to prepare the layout以下是用于准备布局的方法

// this method return the layout as per your expectations, here images are the // list of items you want to use and max count are the list of max item you want // to show except the count tile.

 Widget getItems(List<String> images, int maxCount) =>
    Stack(
      children: List.generate(images.length <= maxCount ? images.length : maxCount+1, (index) {
        if(index == maxCount){
          return  Positioned(
            left: index * 60,
            child: Container(
              padding: const EdgeInsets.all(2), // Border width
              decoration: BoxDecoration(
                  border: Border.all(
                    color: Colors.grey,
                    width: 2,
                  ),
                  color: Colors.black,
                  borderRadius: BorderRadius.circular(40)),
              child: SizedBox.fromSize(
                size: const Size.fromRadius(48), // Image radius
                child: Center(
                  child: Text(
                    style: const TextStyle(
                      color: Color(0xff58D56D),
                      fontSize: 30
                    ),
                    "+${images.length-maxCount}"
                  ),
                ),
              ),
            ),
          );
        }
        else {
          return Positioned(
              left: index * 60, child: getItemWidget(images[index]));
        }
      }),
    );
  
// pass the image url you want to show.
  Widget getItemWidget(String imageUrl) =>  Stack(
    children: [
      Container(
        padding: const EdgeInsets.all(2), // Border width
        decoration: BoxDecoration(
            color: Colors.black,
            borderRadius: BorderRadius.circular(40)),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(40),

          child: SizedBox.fromSize(
            size: Size.fromRadius(48), // Image radius
            child: Image.network(
              imageUrl,
              fit: BoxFit.fill,
            ),
          ),
        ),
      ),
      Positioned(
        bottom: 0,
        left: 0,
        child: Container(
          padding: const EdgeInsets.all(2), // Border width
          decoration: const BoxDecoration(
            color: Colors.black,
            shape: BoxShape.circle,
          ),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(100),
            child: SizedBox.fromSize(
              size: Size.fromRadius(20), // Image radius
              child: Image.network(
                "https://play-lh.googleusercontent.com/STIZ_iftiehDCSynHXQaLqiL-F4kbZwasXOB2nae5pXTOpNKz8XSd7_VCF1Zgc3Z8Q",
                fit: BoxFit.contain,
              ),
            ),
          ),
        ),
      )
    ],
  );

Below code is used to show the items下面的代码用于显示项目

getItems(["https://cdn.pixabay.com/photo/2013/07/13/10/07/man-156584__340.png",
          "https://static.vecteezy.com/system/resources/thumbnails/001/993/889/small/beautiful-latin-woman-avatar-character-icon-free-vector.jpg",
          "https://static.toiimg.com/thumb/resizemode-4,msid-76729536,width-1200,height-900/76729536.jpg",
          "https://www.nj.com/resizer/zovGSasCaR41h_yUGYHXbVTQW2A=/1280x0/smart/cloudfront-us-east-1.images.arcpublishing.com/advancelocal/SJGKVE5UNVESVCW7BBOHKQCZVE.jpg",
          "https://i.kinja-img.com/gawker-media/image/upload/t_original/ijsi5fzb1nbkbhxa2gc1.png"], 3),
      )

Output: Output:

在此处输入图像描述

The point is using Stack and Positioned to positiond widgets.重点是使用StackPositioned来定位小部件。 (index to padding, maxPerson to set maximum widget to show) (填充索引,maxPerson 设置要显示的最大小部件)

https://dartpad.dev/ example https://dartpad.dev/示例

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  final colors = const [
    Colors.yellow,
    Colors.green,
    Colors.blue,
    Colors.orange,
    Colors.cyan,
    Colors.brown,
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: PersonStacker(colors: colors),
      ),
    );
  }
}

class PersonStacker extends StatelessWidget {
  final List<Color> colors;
  final int maxPerson;

  const PersonStacker({required this.colors, this.maxPerson = 3});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        ...colors
            .getRange(0, maxPerson)
            .toList()
            .asMap()
            .map((index, color) => MapEntry(index, Person(index, color: color)))
            .values
            .toList(),
        ...colors.length > maxPerson
            ? [Person(maxPerson, plus: colors.length - maxPerson)]
            : []
      ],
    );
  }
}

class Person extends StatelessWidget {
  final int index;
  final Color color;
  final Color colorBorder;
  final double size = 100;
  final double offset = 30;
  final int? plus;

  const Person(this.index,
      {this.plus, this.color = Colors.black, this.colorBorder = Colors.black});

  Widget renderChild() => plus != null
      ? Center(
          child: Text(
            "+$plus",
            style: const TextStyle(color: Colors.white, fontSize: 20),
          ),
        )
      : Container();

  @override
  Widget build(BuildContext context) {
    return Positioned(
      left: index * offset,
      child: Container(
        width: size,
        height: size,
        decoration: BoxDecoration(
          color: color,
          border: Border.all(width: 2, color: colorBorder),
          borderRadius: BorderRadius.circular(size),
        ),
        child: renderChild(),
      ),
    );
  }
}

Result结果

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM