[英]How to create UI like this in Flutter
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.重点是使用
Stack
和Positioned
来定位小部件。 (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.