前几天在QQ群里看到有人问类似这种头像堆叠的效果在Flutter里面怎么实现?
想了一想,在Flutter里面好像可以用Stack和Positioned来实现。
最后效果如下
问题1:Stack靠右不好处理,现在是用 Row 嵌套2个 Expanded(黄色背景和红色背景),然后根据显示头像的数量来计算这2个Expanded的 flex。
问题2:动态调整Stack里面头像的数量。第一行,靠左显示可以很好的解决。第二行,靠右显示,因为Stack被Expanded包围,如果用函数返回一个 List<Widget>给Stack的children,Flutter会报错。
PS: 问题1,2的解决。使用SizedBox
Container(
height: 40,
alignment: Alignment.topRight,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(
width: _getImageStackWidth(8),
height: double.infinity,
child: Stack(
children: _getStackItems(8),
),
),
Icon(Icons.arrow_forward),
],
)),
最后上代码
import 'package:flutter/material.dart';
class ImageStackPage extends StatelessWidget {
final double sizeW = 50.0;
final double offsetW = 20.0;
int _getSpaceStackFlex(BuildContext context, int imageNumber) {
int maxNum = (MediaQuery.of(context).size.width - 16).toInt();
int num = (offsetW * (imageNumber - 1) + sizeW).toInt();
return maxNum - num + 1;
}
int _getImageStackFlex(BuildContext context, int imageNumber) {
int num = (offsetW * (imageNumber - 1) + sizeW).toInt();
return num;
}
double _getImageStackWidth(int imageNumber) {
return offsetW * (imageNumber - 1) + sizeW;
}
List<Widget> _getStackItems(int count) {
List<Widget> _list = new List<Widget>();
for (var i = 0; i < count; i++) {
double off = 20.0 * i;
_list.add(Positioned(
left: off,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head02.png"),
width: sizeW,
height: sizeW,
),
),
));
}
return _list;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('头像堆叠'),
),
body: Container(
child: Column(
children: <Widget>[
Container(
height: 40,
alignment: Alignment.topRight,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(
width: _getImageStackWidth(8),
height: double.infinity,
child: Stack(
children: _getStackItems(8),
),
),
Icon(Icons.arrow_forward),
],
)),
Container(
height: 40,
child: Container(
color: Colors.teal,
child: Stack(
children: _getStackItems(8),
),
)),
Container(
color: Colors.grey,
child: new Row(
children: <Widget>[
Expanded(
flex: _getSpaceStackFlex(context, 8),
child: Container(
color: Colors.yellow,
height: 40,
),
),
Expanded(
flex: _getImageStackFlex(context, 8),
child: Container(
color: Colors.red,
child: Stack(
alignment: AlignmentDirectional.bottomEnd,
children: <Widget>[
CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
Positioned(
right: 20,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head02.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 40,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 60,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 80,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 100,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 120,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
),
Positioned(
right: 140,
child: CircleAvatar(
child: Image(
image: AssetImage("images/head01.png"),
width: sizeW,
height: sizeW,
),
),
)
],
),
),
),
Icon(Icons.arrow_forward),
],
)),
],
),
),
);
}
}