You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除FlChart图表中的侧边标题?

Flutter中FlChart移除侧边标题问题

我用FlChart展示股票数据,已经注释了LineChartData里的titlesData属性,但图表四周还是有默认的侧边标题,怎么彻底移除?(忽略图表样式问题)

代码:

import 'dart:convert';
//import 'package:intl/intl.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:futura_api/api.dart';

class LineChartSample2 extends StatefulWidget {
  final String symbol;

  const LineChartSample2({Key? key, required this.symbol}) : super(key: key);

  @override
  State<LineChartSample2> createState() => _LineChartSample2State();
}

class _LineChartSample2State extends State<LineChartSample2> {
  late Future<StockData?> stockDataFuture;
  late LineChartData stockChartData;

  bool showAvg = false;

  final StocksApi _stocksApi =
      StocksApi(ApiClient(basePath: 'http://192.168.178.33'));

  List<Color> gradientColors = [
    Colors.deepPurple[200] as Color,
    Colors.deepPurple[800] as Color,
  ];

  final int _divider = 25;
  final int _leftLabelsCount = 6;

  final List<FlSpot> _values = [];
  double _minX = 0;
  double _maxX = 0;
  double _minY = 0;
  double _maxY = 0;
  double _leftTitlesInterval = 0;

  @override
  void initState() {
    // todo add websocket connection
    stockDataFuture = fetchData(widget.symbol);
    super.initState();
  }

  Future<StockData?> fetchData(String symbol) async {
    try {
      if (kDebugMode) {
        return Future<StockData?>.delayed(const Duration(seconds: 0), () async {
          Map<String, dynamic> jsonData = jsonDecode(
              await DefaultAssetBundle.of(context)
                  .loadString("lib/assets/fonts/stock_data.json"));
          return StockData.fromJson(jsonData);
        });
      }
      return await _stocksApi.apiStocksGet(symbol: symbol, interval: "1d");
    } catch (e) {
      return null; // Return an empty string or handle the error as needed
    }
  }

  void parseStockData(Map<String, StockDto>? data) {
    double minY = double.maxFinite;
    double maxY = double.minPositive;

    data?.forEach(
      (key, value) {
        if (minY > (value.close ?? 0)) minY = value.close ?? 0;
        if (maxY < (value.close ?? 0)) maxY = value.close ?? 0;
        _values.add(FlSpot(getXValueFromDateString(key), value.close ?? 0));
      },
    );

    _minX = _values.first.x;
    _maxX = _values.last.x;
    _minY = (minY / _divider).floorToDouble() * _divider;
    _maxY = (maxY / _divider).ceilToDouble() * _divider;
    _leftTitlesInterval =
        ((_maxY - _minY) / (_leftLabelsCount - 1)).floorToDouble();
  }

  LineChartData _mainData() {
    return LineChartData(
      // titlesData: FlTitlesData(
      //     bottomTitles: _bottomTitles(), leftTitles: _leftTitles()),
      gridData: _gridData(),
      minX: _minX,
      maxX: _maxX,
      minY: _minY,
      maxY: _maxY,
      lineBarsData: [
        _lineBarData(),
      ],
    );
  }

  LineChartBarData _lineBarData() {
    return LineChartBarData(
      spots: _values,
      gradient: LinearGradient(
        colors: gradientColors,
      ),
      isCurved: true,
      barWidth: 2,
      isStrokeCapRound: true,
      dotData: const FlDotData(
        show: false,
      ),
      belowBarData: BarAreaData(
        show: true,
        gradient: LinearGradient(
          colors:
              gradientColors.map((color) => color.withOpacity(0.3)).toList(),
        ),
      ),
      // Other properties...
    );
  }

  Widget buildChart(LineChartData data) {
    stockChartData = data;
    return AspectRatio(
      aspectRatio: 1.70,
      child: Padding(
        padding:
            const EdgeInsets.only(right: 18, left: 12, top: 24, bottom: 12),
        child: _values.isEmpty ? const Placeholder() : LineChart(_mainData()),
      ),
    );
  }

  double getXValueFromDateString(String dateString) {
    DateTime dateTime = DateTime.parse(dateString);
    return dateTime.millisecondsSinceEpoch.toDouble();
  }

  LineChartData avgData() {
    // Implement this method based on your requirement for average data display
    return stockChartData; // Return the same data for simplicity in this example
  }

  // AxisTitles _bottomTitles() {
  //   return AxisTitles(
  //       sideTitles: SideTitles(
  //     showTitles: true,
  //     getTitlesWidget: (value, meta) {
  //       final DateTime date =
  //           DateTime.fromMillisecondsSinceEpoch(value.toInt());
  //       return SideTitleWidget(
  //           axisSide: AxisSide.bottom,
  //           child: Text(
  //             DateFormat.MMM().format(date),
  //             style: const TextStyle(color: Colors.white, fontSize: 12),
  //           ));
  //     },
  //     interval: (_maxX - _minX) / 6,
  //   ));
  // }

  // AxisTitles _leftTitles() {
  //   return AxisTitles(
  //       sideTitles: SideTitles(
  //           showTitles: true,
  //           interval: _leftTitlesInterval,
  //           getTitlesWidget: (value, meta) {
  //             return SideTitleWidget(
  //               axisSide: AxisSide.left,
  //               space: 4,
  //               child: Text(
  //                 NumberFormat.compactCurrency(symbol: '€').format(value),
  //                 style: const TextStyle(color: Colors.white, fontSize: 12),
  //               ),
  //             );
  //           }));
  // }

  FlGridData _gridData() {
    return FlGridData(
      show: true,
      drawVerticalLine: false,
      getDrawingHorizontalLine: (value) {
        return const FlLine(color: Colors.white, strokeWidth: 1);
      },
      checkToShowHorizontalLine: (value) {
        return (value - _minY) % _leftTitlesInterval == 0;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<StockData?>(
      future: stockDataFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          return Center(child: Text('Error: ${snapshot.error}'));
        } else if (snapshot.hasData) {
          parseStockData(snapshot.data!.timeSeries);
          return buildChart(_mainData());
        } else {
          return const Center(child: Text('No data available'));
        }
      },
    );
  }
}

图表截图:
图表截图

我已经尝试注释TitlesData属性,但并未解决问题。


解决方法

注释掉titlesData没用是因为FlChart默认会启用所有方向的标题。要彻底移除,得显式设置titlesData并关闭所有标题:

修改_mainData()方法里的LineChartData,加上以下配置:

titlesData: const FlTitlesData(
  show: false, // 一键关闭所有方向的标题
),

或者你也可以精细控制单个方向的显示状态:

titlesData: const FlTitlesData(
  bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
  leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
  rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
  topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
),

这样就能完全去掉图表四周的侧边标题了。

内容的提问来源于stack exchange,提问作者Jonasaas1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:59:51