feat: K线图添加技术指标切换(MA/EMA/BOLL/VOL/MACD),修复设置面板显示问题
This commit is contained in:
@@ -60,7 +60,10 @@ class ChartPage extends StatelessWidget {
|
||||
// 2. 时间周期选择
|
||||
_buildIntervalTabs(context, provider),
|
||||
|
||||
// 3. K线图区域
|
||||
// 3. 技术指标切换
|
||||
_buildIndicatorTabs(context, provider),
|
||||
|
||||
// 4. K线图区域
|
||||
Expanded(
|
||||
child: InteractiveChart(
|
||||
candles: candles,
|
||||
@@ -99,7 +102,7 @@ class ChartPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// 4. 底部操作栏
|
||||
// 5. 底部操作栏
|
||||
_buildBottomActions(context, provider),
|
||||
],
|
||||
);
|
||||
@@ -265,6 +268,101 @@ class ChartPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// 技术指标切换
|
||||
Widget _buildIndicatorTabs(BuildContext context, ChartProvider provider) {
|
||||
final colorScheme = context.colors;
|
||||
final indicators = [
|
||||
{'key': 'MA', 'label': 'MA', 'value': provider.indicators.showMA},
|
||||
{'key': 'EMA', 'label': 'EMA', 'value': provider.indicators.showEMA},
|
||||
{'key': 'BOLL', 'label': 'BOLL', 'value': provider.indicators.showBOLL},
|
||||
{'key': 'VOL', 'label': 'VOL', 'value': provider.indicators.showVOL},
|
||||
{'key': 'MACD', 'label': 'MACD', 'value': provider.indicators.showMACD},
|
||||
];
|
||||
|
||||
return Container(
|
||||
height: 36,
|
||||
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.sm),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surfaceContainer,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.2),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: indicators.map((item) {
|
||||
final isSelected = item['value'] as bool;
|
||||
final key = item['key'] as String;
|
||||
final label = item['label'] as String;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: AppSpacing.xs),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
switch (key) {
|
||||
case 'MA':
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showMA: !isSelected),
|
||||
);
|
||||
break;
|
||||
case 'EMA':
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showEMA: !isSelected),
|
||||
);
|
||||
break;
|
||||
case 'BOLL':
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showBOLL: !isSelected),
|
||||
);
|
||||
break;
|
||||
case 'VOL':
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showVOL: !isSelected),
|
||||
);
|
||||
break;
|
||||
case 'MACD':
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showMACD: !isSelected),
|
||||
);
|
||||
break;
|
||||
}
|
||||
},
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.md,
|
||||
vertical: AppSpacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? colorScheme.primary.withValues(alpha: 0.1)
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? colorScheme.primary
|
||||
: colorScheme.outlineVariant.withValues(alpha: 0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: AppTextStyles.labelSmall(context).copyWith(
|
||||
color: isSelected
|
||||
? colorScheme.primary
|
||||
: colorScheme.onSurfaceVariant,
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 底部操作栏
|
||||
Widget _buildBottomActions(BuildContext context, ChartProvider provider) {
|
||||
final colorScheme = context.colors;
|
||||
@@ -395,10 +493,12 @@ class ChartPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
void _showSettingsSheet(BuildContext context) {
|
||||
final provider = context.read<ChartProvider>();
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (ctx) => Consumer<ChartProvider>(
|
||||
builder: (ctx, provider, _) {
|
||||
builder: (ctx) => StatefulBuilder(
|
||||
builder: (ctx, setState) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
@@ -414,24 +514,66 @@ class ChartPage extends StatelessWidget {
|
||||
const SizedBox(height: AppSpacing.lg),
|
||||
|
||||
_buildIndicatorSwitch(
|
||||
context: ctx,
|
||||
context: context,
|
||||
label: 'MA 移动平均线 (7/14/30)',
|
||||
value: provider.indicators.showMA,
|
||||
onChanged: (v) => provider.updateIndicators(
|
||||
provider.indicators.copyWith(showMA: v),
|
||||
),
|
||||
onChanged: (v) {
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showMA: v),
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
_buildIndicatorSwitch(
|
||||
context: ctx,
|
||||
label: 'VOL 成交量',
|
||||
value: provider.indicators.showVOL,
|
||||
onChanged: (v) => provider.updateIndicators(
|
||||
provider.indicators.copyWith(showVOL: v),
|
||||
),
|
||||
context: context,
|
||||
label: 'EMA 指数移动平均',
|
||||
value: provider.indicators.showEMA,
|
||||
onChanged: (v) {
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showEMA: v),
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.lg),
|
||||
_buildIndicatorSwitch(
|
||||
context: context,
|
||||
label: 'BOLL 布林带',
|
||||
value: provider.indicators.showBOLL,
|
||||
onChanged: (v) {
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showBOLL: v),
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
_buildIndicatorSwitch(
|
||||
context: context,
|
||||
label: 'VOL 成交量',
|
||||
value: provider.indicators.showVOL,
|
||||
onChanged: (v) {
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showVOL: v),
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
_buildIndicatorSwitch(
|
||||
context: context,
|
||||
label: 'MACD',
|
||||
value: provider.indicators.showMACD,
|
||||
onChanged: (v) {
|
||||
provider.updateIndicators(
|
||||
provider.indicators.copyWith(showMACD: v),
|
||||
);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user