Flutter自定义带弯边形状实现及Stack组件非Positioned定位问题
实现方案
1. LTE/ZTL标识向内弯边效果实现
该向内凹的边角为视觉模拟效果,你可以采用两种方案实现:
- 简易方案:在白色标签的左右两侧各放置1个尺寸为17*17的小容器,颜色和底部深蓝色背景
0xff0C2242保持一致,将容器靠近标签的一侧设置为17的圆角,叠加在标签与深蓝色背景的衔接位置,即可模拟出向内凹陷的弯边效果 - 精准方案:使用
CustomPaint组件自定义绘制标签的外形路径,可完全自定义每一段边角的弧度和位置,适配性更强
2. Stack布局除Positioned外的子组件定位方式
- 用
Align组件:通过alignment属性指定子组件在Stack中的相对位置,支持枚举值(如Alignment.bottomCenter)和坐标值(如Alignment(0.3, -0.2)),还可配合widthFactor、heightFactor参数调整组件占位尺寸 - 用
FractionallySizedBox:结合alignment属性,通过宽高占父容器的比例来同时调整组件尺寸和定位,适配不同屏幕尺寸更方便 - 用
PositionedDirectional:功能与Positioned完全一致,会自动适配LTR/RTL文本布局方向,适合多语言国际化场景使用
可实现效果的参考代码
import 'package:flutter/material.dart'; class NavHome extends StatelessWidget { const NavHome({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final baseBgColor = const Color(0xff0C2242); return Scaffold( backgroundColor: Colors.grey.shade100, body: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ SizedBox( height: MediaQuery.of(context).size.height * 0.023, ), Stack( alignment: Alignment.topCenter, children: [ Container( height: MediaQuery.of(context).size.height * 0.35, width: MediaQuery.of(context).size.width * 0.90, decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 3, offset: const Offset(0, 0), ), ], color: baseBgColor, borderRadius: BorderRadius.circular(17))), Container( height: MediaQuery.of(context).size.height * 0.27, width: MediaQuery.of(context).size.width * 0.90, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(17))), // 底部白色凸起标签 Positioned( top: MediaQuery.of(context).size.height * 0.27, left: MediaQuery.of(context).size.width * 0.3, child: Stack( children: [ Container( height: MediaQuery.of(context).size.height * 0.08, width: MediaQuery.of(context).size.width * 0.30, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(17), bottomRight: Radius.circular(17))), child: const Center(child: Text("LTE / ZTL", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),)), ), // 左侧向内凹角 Positioned( top: 0, left: -17, child: Container( width: 17, height: 17, decoration: BoxDecoration( color: baseBgColor, borderRadius: const BorderRadius.only(topRight: Radius.circular(17)), ), ), ), // 右侧向内凹角 Positioned( top: 0, right: -17, child: Container( width: 17, height: 17, decoration: BoxDecoration( color: baseBgColor, borderRadius: const BorderRadius.only(topLeft: Radius.circular(17)), ), ), ) ], ), ) ], ) ], ), ); } }
内容的提问来源于stack exchange,提问作者Alan Bosco
相关产品推荐
相关产品推荐

