Kon*_*tin 6 flutter flutter-layout
我需要制作一个底部栏“购物车”图标并显示它拥有的许多商品。问题是我无法将数字标签放置得足够高。它被它的父约束所剪裁。截图证明了这一点
\n\n\n\n按钮本身是一个 Column 小部件,其顶部有 Frare 动画“波浪”演员,其下方有一个堆栈(绿线下方)\n如果将标签向上移动,我会得到以下结果:
\n\n\n\n标签本身被剪掉,波浪不知何故消失了。\n我尝试将堆栈包装在 LimitedBox、OverflowBox、SizedBox 中,但都没有解决问题。
\n\n这是我想要的(理想情况下):
\n\n\n\n让父级保留其原始位置和大小,但显示部分超出其的子级
\n\n以下是按钮类的完整代码(计数器是在 _getCounter() 方法中创建的):
\n\nclass BottomBarButton extends StatefulWidget {\n\n BottomBarMenuItemModel itemModel;\n final double barHeight;\n\n\n BottomBarButton(this.itemModel, this.barHeight);\n\n @override\n _BottomBarButtonState createState() => _BottomBarButtonState();\n}\n\nclass _BottomBarButtonState extends State<BottomBarButton> with SingleTickerProviderStateMixin {\n\n AnimationController _scaleController;\n Animation<double> _scaleTween;\n Animation<Color> _colorTween;\n Animation<Color> _reversedColorTween;\n StreamSubscription<String> _streamSubscription;\n StreamSubscription<String> _counterSubscription;\n String _inactiveAnimation = \'idle\';\n\n @override\n void initState() {\n _streamSubscription = Dispatch().onChangeBottomBar.stream.listen((menuId) {\n if (widget.itemModel.id == menuId) {\n return;\n }\n setState(() {});\n });\n\n _scaleController = AnimationController(\n vsync: this,\n duration: const Duration(milliseconds: 250)\n );\n _scaleTween = Tween(begin: 1.0, end: 1.2).animate(\n CurvedAnimation(\n parent: _scaleController,\n curve: Curves.bounceInOut\n )\n );\n _colorTween = ColorTween(begin: pizzaBottomBarIconNormalColor, end: pizzaYellow).animate(\n CurvedAnimation(parent: _scaleController, curve: Curves.bounceInOut)\n );\n _reversedColorTween = ColorTween(begin: pizzaYellow, end: pizzaBottomBarIconNormalColor).animate(\n CurvedAnimation(parent: _scaleController, curve: Curves.bounceInOut)\n );\n DataStore().onCartDataChange.stream.listen((newCounter) {\n setState(() {});\n });\n\n super.initState();\n }\n @override\n void dispose() {\n _scaleController?.dispose();\n _streamSubscription.cancel();\n _counterSubscription.cancel();\n super.dispose();\n }\n\n Widget _getCounter() {\n if (widget.itemModel.id == Dispatch.CartMenu) {\n var itemsInCart = DataStore().cartData.length;\n if (itemsInCart > 0) {\n return AnimatedBuilder(\n animation: _scaleTween,\n builder: (c, w) {\n return Positioned(\n right: 25 / _scaleTween.value,\n top: -15 + (20 / _scaleTween.value),\n child: AnimatedBuilder(\n animation: _colorTween,\n builder: (c, w) {\n return Container(\n width: 20,\n height: 20,\n decoration: BoxDecoration(\n shape: BoxShape.circle,\n color: _reversedColorTween.value,\n ),\n child: Text(\n itemsInCart.toString(),\n textAlign: TextAlign.center,\n style: TextStyle(\n color: pizzaBottomBarColor,\n fontFamily: "OpenSans",\n fontWeight: FontWeight.w500\n ),\n ),\n );\n },\n ),\n );\n },\n );\n }\n }\n return Container();\n }\n\n @override\n Widget build(BuildContext context) {\n widget.itemModel.isActive\n ? _scaleController.forward()\n : _scaleController.reverse();\n var animationName = widget.itemModel.isActive ? \'jump_in\' : _inactiveAnimation;\n\n return Expanded(\n child: GestureDetector(\n onTap: () {\n setState(() {\n // \xd0\xbd\xd1\x83\xd0\xb6\xd0\xbd\xd0\xbe \xd1\x87\xd1\x82\xd0\xbe\xd0\xb1\xd1\x8b \xd0\xbf\xd1\x80\xd0\xb8 \xd0\xbf\xd0\xb5\xd1\x80\xd0\xb2\xd0\xbe\xd0\xbc \xd1\x80\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb5\xd1\x80\xd0\xb5 \xd0\xbd\xd0\xb5 \xd0\xb7\xd0\xb0\xd0\xbf\xd1\x83\xd1\x81\xd0\xba\xd0\xb0\xd1\x82\xd1\x8c \xd0\xb2\xd1\x81\xd0\xb5 \xd0\xb0\xd0\xbd\xd0\xb8\xd0\xbc\xd0\xb0\xd1\x86\xd0\xb8\xd0\xb8, \xd0\xb0 \xd0\xb2\xd1\x80\xd1\x83\xd0\xb1\xd0\xb8\xd1\x82\xd1\x8c \xd0\xb0\xd0\xb9\xd0\xb4\xd0\xbb\n _inactiveAnimation = \'jump_out\';\n animationName = widget.itemModel.isActive ? \'jump_in\' : _inactiveAnimation;\n Dispatch().selectMenu(widget.itemModel.id);\n// print(widget.itemModel.id);\n });\n },\n child: AbsorbPointer(\n child: Column(\n children: <Widget>[\n Stack(\n children: <Widget>[\n Container( // \xd0\xb2\xd1\x8b\xd0\xbf\xd1\x80\xd1\x8b\xd0\xb3\xd0\xb8\xd0\xb2\xd0\xb0\xd1\x8e\xd1\x89\xd0\xb0\xd1\x8f\xd1\x8f \xd0\xb2\xd0\xbe\xd0\xbb\xd0\xbd\xd0\xb0 \xd1\x81\xd0\xb2\xd0\xb5\xd1\x80\xd1\x85\xd1\x83\n // \xd0\xb0\xd0\xbd\xd0\xb8\xd0\xbc\xd0\xb0\xd1\x86\xd0\xb8\xd1\x8e \xd0\xbd\xd0\xb0\xd0\xb4\xd0\xbe \xd1\x81\xd0\xb4\xd0\xb2\xd0\xb8\xd0\xbd\xd1\x83\xd1\x82\xd1\x8c \xd0\xbd\xd0\xb0 20 \xd0\xbf\xd0\xb8\xd0\xb5\xd1\x81\xd0\xb5\xd0\xbb\xd0\xb5\xd0\xb9 \xd0\xb2\xd0\xb2\xd0\xb5\xd1\x80\xd1\x85,\n // \xd1\x87\xd1\x82\xd0\xbe\xd0\xb1\xd1\x8b \xd1\x83\xd1\x87\xd0\xb5\xd1\x81\xd1\x82\xd1\x8c \xd0\xbf\xd1\x80\xd0\xbe\xd1\x81\xd1\x82\xd1\x80\xd0\xb0\xd0\xbd\xd1\x81\xd1\x82\xd0\xb2\xd0\xbe\n // \xd0\xb4\xd0\xbb\xd1\x8f \xd0\xb2\xd1\x8b\xd0\xbf\xd1\x80\xd1\x8b\xd0\xb3\xd0\xb8\xd0\xb2\xd0\xb0\xd1\x8e\xd1\x89\xd0\xb5\xd0\xb9 \xd1\x87\xd0\xb0\xd1\x81\xd1\x82\xd0\xb8\n transform: Matrix4.translationValues(0, -20, 0),\n alignment: Alignment.bottomCenter,\n height: 20,\n width: double.infinity,\n child: FlareActor(\n "assets/anim/bottom_bar_jumpy_button.flr",\n alignment: Alignment.bottomCenter,\n fit: BoxFit.fitWidth,\n animation: animationName,\n shouldClip: false,\n )\n ),\n ScaleTransition(\n scale: _scaleTween,\n child: Container(\n // \xd0\xbd\xd0\xb5\xd0\xb0\xd0\xbd\xd0\xb8\xd0\xbc\xd0\xb8\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xbd\xd0\xb0\xd1\x8f \xd0\xb8\xd0\xba\xd0\xbe\xd0\xbd\xd0\xba\xd0\xb0\n alignment: Alignment.center,\n child: AnimatedBuilder(\n animation: _colorTween,\n builder: (context, w) {\n return Icon(\n widget.itemModel.iconData,\n size: 20,\n color: _colorTween.value,\n );\n },\n ),\n height: widget.barHeight - 22,\n ),\n ),\n _getCounter(),\n ],\n ),\n ScaleTransition(\n // \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82 \xd0\xba\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xbe\xd0\xba \xd0\xb2 \xd0\xbd\xd0\xb8\xd0\xb6\xd0\xbd\xd0\xb5\xd0\xbc \xd0\xb1\xd0\xb0\xd1\x80\xd0\xb5\n scale: _scaleTween,\n alignment: FractionalOffset.topCenter, // \xd0\xbf\xd0\xb8\xd0\xb2\xd0\xbe\xd1\x82 \xd0\xbf\xd0\xbe \xd0\xb2\xd0\xb5\xd1\x80\xd1\x85\xd0\xbd\xd0\xb5\xd0\xb9 \xd0\xba\xd1\x80\xd0\xbe\xd0\xbc\xd0\xba\xd0\xb5\n child: Transform(\n transform: Matrix4.translationValues(0, -6, 0),\n child: AnimatedBuilder(\n animation: _colorTween,\n builder: (context, w) {\n return Padding(\n padding: const EdgeInsets.only(top: 7.0),\n child: Text(widget.itemModel.title,\n maxLines: 1,\n overflow: TextOverflow.ellipsis,\n textAlign: TextAlign.start,\n style: TextStyle(\n fontFamily: \'OpenSans\',\n fontWeight: FontWeight.w500,\n fontSize: 13,\n height: 1,\n color: _colorTween.value\n ),\n ),\n );\n },\n ),\n ),\n )\n ],\n ),\n ),\n ),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
不要使用overflow,它现在已被弃用。clipBehavior代替使用。
Stack(
clipBehavior: Clip.none, // This is what you need.
children: [],
)
Run Code Online (Sandbox Code Playgroud)
一些魔法发生了。我已经为此苦苦挣扎了几个小时,但在创建这个主题后几分钟内就想出了一个解决方案。因此,使用 Transform 小部件可以很容易地解决这个问题。像这样:
Widget _getCounter() {
if (widget.itemModel.id == Dispatch.CartMenu) {
var itemsInCart = DataStore().cartData.length;
if (itemsInCart > 0) {
return AnimatedBuilder(
animation: _scaleTween,
builder: (c, w) {
return Transform(
transform: Matrix4.translationValues(
45 + (5 * _scaleTween.value),
6 - (6 * _scaleTween.value), 0
),
child: AnimatedBuilder(
animation: _colorTween,
builder: (c, w) {
return Container(
width: 20,
height: 20,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _reversedColorTween.value,
),
child: Text(
itemsInCart.toString(),
textAlign: TextAlign.center,
style: TextStyle(
color: pizzaBottomBarColor,
fontFamily: "OpenSans",
fontWeight: FontWeight.w500
),
),
);
},
),
);
},
);
}
}
return Container();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3722 次 |
| 最近记录: |