更新
This commit is contained in:
112
lib/pages/sleep_report/chart/StatusBarWithIndicator.dart
Normal file
112
lib/pages/sleep_report/chart/StatusBarWithIndicator.dart
Normal file
@@ -0,0 +1,112 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:vbvs_app/common/util/FitTool.dart';
|
||||
|
||||
class StatusBarWithIndicator extends StatelessWidget {
|
||||
final int selectKey;
|
||||
final List<Map<String, dynamic>> showLabel;
|
||||
final IconData icon;
|
||||
final double gap; // 每段之间的间距
|
||||
|
||||
const StatusBarWithIndicator({
|
||||
super.key,
|
||||
required this.selectKey,
|
||||
required this.showLabel,
|
||||
this.icon = Icons.favorite,
|
||||
this.gap = 8.0, // 默认 8.rpx 间距
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
final totalWidth = constraints.maxWidth;
|
||||
final itemCount = showLabel.length;
|
||||
|
||||
// 每条线的宽度 = (总宽度 - 总间隔)/ 项数
|
||||
final totalGap = (itemCount - 1) * gap.rpx;
|
||||
final itemWidth = (totalWidth - totalGap) / itemCount;
|
||||
|
||||
// 找到选中项的 index
|
||||
final selectedIndex = showLabel.indexWhere((e) => e['key'] == selectKey);
|
||||
final iconLeft = selectedIndex >= 0
|
||||
? selectedIndex * (itemWidth + gap.rpx) + itemWidth / 2
|
||||
: 0.0;
|
||||
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
if (selectedIndex >= 0)
|
||||
Positioned(
|
||||
left: iconLeft,
|
||||
top: -20.rpx,
|
||||
child: Transform.translate(
|
||||
offset: Offset(-22.5.rpx, 0), // 图片宽度 45.rpx,居中偏移
|
||||
child: Container(
|
||||
width: 45.rpx,
|
||||
height: 76.rpx,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/img/tip_arrow.gif'),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 50.rpx),
|
||||
child: Column(
|
||||
children: [
|
||||
// 条形段(带间距)
|
||||
Row(
|
||||
children: showLabel.asMap().entries.map((entry) {
|
||||
int index = entry.key;
|
||||
var item = entry.value;
|
||||
|
||||
return Container(
|
||||
width: itemWidth,
|
||||
height: 15.rpx,
|
||||
margin: EdgeInsets.only(
|
||||
left: index == 0 ? 0 : gap.rpx,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: item['color'],
|
||||
borderRadius: BorderRadius.circular(0.rpx),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
SizedBox(height: 12.rpx),
|
||||
// 名称文字
|
||||
Row(
|
||||
children: showLabel.asMap().entries.map((entry) {
|
||||
int index = entry.key;
|
||||
var item = entry.value;
|
||||
|
||||
return Container(
|
||||
width: itemWidth,
|
||||
margin: EdgeInsets.only(
|
||||
left: index == 0 ? 0 : gap.rpx,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
item['name'],
|
||||
style: TextStyle(
|
||||
fontSize: 24.rpx,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user