【问题标题】:Button click at the same page keeps triggering CustomPaint's paint flutter同一页面的按钮点击不断触发CustomPaint的油漆颤动
【发布时间】:2019-08-26 08:05:06
【问题描述】:

我创建了一个用于绘制图形的 CustomPaint。我需要一个滑块来处理要显示的数据数量。我在构建 CustomPaint 小部件的同一页面上放置了一个滑块和一个按钮,单击按钮或滑块上的幻灯片将触发 CustomPaint 的paint & shouldRepaint 方法,即使按钮和滑块的 onPressed 和onChanged 为空

我基于 https://github.com/MSzalek-Mobile/weight_tracker 构建我的小部件,

他使用 Redux 进行状态管理,而我更喜欢使用 Provider。我的结构几乎和他的一样——在显示它的页面上用消费者包装我的小部件,但无济于事。

图表小部件

import 'package:flowy/models/data_entry.dart';
import 'package:flowy/models/XDataPositionOnGraph.dart';
import 'package:flowy/models/YDataPositionOnGraph.dart';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;

class GraphWidget extends CustomPainter {
  double leftOffsetStart;
  double topOffsetEnd;
  double drawingWidth;
  double drawingHeight;




  ///Sorts Max Min Value and Difference
  ///Y Axis max min : (double) dataValue
  ///X Axis max min : (DateTime) dataTime
  void sortMaxAndMinValue(List<DataEntry> dataEntry) {
    yMax = dataEntry[0].dataValue;
    yMin = dataEntry[0].dataValue;
    xMax = dataEntry[0].dataTime;
    xMin = dataEntry[0].dataTime;
    for (int i = 0; i < dataEntry.length; i++) {
      if (yMax <= dataEntry[i].dataValue) {
        yMax = dataEntry[i].dataValue;

        //print('yMax now is $yMax');
      } else if (yMin >= dataEntry[i].dataValue) {
        yMin = dataEntry[i].dataValue;

        //print('yMmin now is $yMin');
      }
    }
//
    for (int i = 0; i < dataEntry.length; i++) {
      if ((dataEntry[i].dataTime).isAfter(xMax)) {
        xMax = dataEntry[i].dataTime;
        //print('dataEntryValue is ${dataEntry[i].dataTime} xMax now is $xMax');
      }

      if ((dataEntry[i].dataTime).isBefore(xMin)) {
        xMin = dataEntry[i].dataTime;
        //print('dataEntryValue is ${dataEntry[i].dataTime} xMin now is $xMin');
      }
    }

    //print('xMax is $xMax');
    //print('xMin is $xMin');

    yDifference = yDifferenceBetweenMaxAndMin(yMax, yMin);
    xDifference = xDifferenceBetweenMaxAndMin(xMax, xMin);
    //print('xDifference is ${xDifference.inDays}');
    //print('yDifference is $yDifference');

    holder = dataEntry[2].dataTime.millisecondsSinceEpoch;
    int holder1 = dataEntry[3].dataTime.millisecondsSinceEpoch;
    DateTime.fromMillisecondsSinceEpoch(holder).toUtc();

    int diffHolder = holder - holder1;
    print(
        'dataEntryList ${dataEntry[2].dataTime} convert to epoch:  ${dataEntry[2].dataTime.millisecondsSinceEpoch}');
    print(
        'dataEntryList ${dataEntry[3].dataTime} convert to epoch:  ${dataEntry[3].dataTime.millisecondsSinceEpoch}');

    Duration nonEpoch = dataEntry[2].dataTime.difference(dataEntry[3].dataTime);
    print(
        'holder ${DateTime.fromMillisecondsSinceEpoch(diffHolder).toUtc().day}');
    print('nonEpoch = ${nonEpoch.inDays}');

//    //print('xDifference is ${DateTime.fromMicrosecondsSinceEpoch(xDifference)}');
  }

  ///Draw Horizontal lines and labels
  ///change Offset(singleWidth) to change line offset
  ///Plots Data
  void drawHorizontalLinesAndLabels(List<DataEntry> dataEntryList, Size size,
      Canvas canvas, xDifference, yDifference, yMax, yMin, xMax, xMin) {
    double singleHeight = size.height / 11;
    double singleWidth = size.width / 6;

    var paint = Paint();
    paint.color = Colors.grey[200];
    paint.strokeWidth = 3;

    List<double> yAxisNewList =
    stepDifferenceYAxis(dataEntryList, yDifference, yMax, yMin);
    List<DateTime> xAxisNewList =
    stepDifferenceXAxis(size, dataEntryList, xDifference, xMax, xMin);

    drawYAxisLabel(yAxisNewList, size, canvas);

    for (int i = 1; i < 12; i++) {
      if (i.isOdd) {
        //drawing label and line if odd
//      //print('i is $i');

        canvas.drawLine(
          Offset(singleWidth, singleHeight * i),
          Offset(size.width, singleHeight * i),
          paint,
        );
      }
    }

    drawXAxisLabelFixed(xAxisNewList, size, canvas, xDifference);

    plotData(dataEntryList, canvas, size, yDifference, xDifference, singleWidth,
        singleHeight, yMax);
  }



  ///Draw X Axis Label Fixed
  ///Fixes 10 labels
  ///stepWidth is defined by plotSize/ 10
  ///size.width - (stepWidth): Drawing from the right side
  /// [0] is latest, xAxisIntLabelList.length oldest
  ///
  /// Because the first label might have a difference value difference, hence,
  /// xMinDifference is calculated to find the deviation on the canvas from it
  void drawXAxisLabelFixed(List<DateTime> xAxisIntLabelList, Size size,
      Canvas canvas, Duration difference) {
    double singleHeight = size.height / 11;
    double singleWidth = size.width / 6;

    Size plotSize;

    plotSize = Size(size.width - singleWidth, size.height + singleHeight * 0.2);

    ui.Paragraph paragraph;

    print(
        'difference between [9][8] and [8][7] xData ${xAxisIntLabelList[9].difference(xAxisIntLabelList[8]) == xAxisIntLabelList[8].difference(xAxisIntLabelList[7])}');

    double stepWidth = plotSize.width / 10;

    print(
        'singlewidth is $singleWidth original size is $size plotsize is $plotSize \n stepwidth is $stepWidth datalength is ${xAxisIntLabelList.length} ');

    for (int j = 0; j < 10; j++) {
      paragraph = _buildXAxisLabel(xAxisIntLabelList,
          Size(stepWidth, size.height), canvas, difference, j);

      canvas.drawParagraph(
          paragraph,
          Offset(size.width - size.width * 0.02 - (stepWidth * j),
              plotSize.height));
      xDataLabelsPosition.add(XDataPositionOnGraph(
          xAxisIntLabelList[j], size.width - (stepWidth * j)));
    }

    //In DateTime
//    print(' xData Position =  ${xDataLabelsPosition[9].position}');

    xLineDifference = (xDataLabelsPosition[0].position -
        xDataLabelsPosition[1].position) /
        ((xDataLabelsPosition[0].value.difference(xDataLabelsPosition[1].value))
            .inMinutes);

    xMinLineDifference = (xDataLabelsPosition[9].position -
        xDataLabelsPosition[8].position) /
        ((xDataLabelsPosition[9].value.difference(xDataLabelsPosition[8].value))
            .inMinutes);

    print(
        'xLineDifference is $xLineDifference ,\n xMinLineDifference $xMinLineDifference \n difference in minutes is ${(xDataLabelsPosition[0].value.difference(xDataLabelsPosition[1].value)).inMinutes} ');
  }


  ///Builds XAxisLabel with DateTime List calc from stepDifferenceXAxis
  ui.Paragraph _buildXAxisLabel(List<DateTime> xAxisIntLabelList, Size size,
      Canvas canvas, difference, j) {
    //print('xAxisIntLabelList is $xAxisIntLabelList');
    //difference is duration
    print(xAxisIntLabelList[0]);

    double leftOffsetStart = size.width;
    ui.ParagraphBuilder builder;

    builder = ui.ParagraphBuilder(
      new ui.ParagraphStyle(
        fontSize: 10.0,
        textAlign: TextAlign.start,
      ),
    );

    builder
      ..pushStyle(new ui.TextStyle(color: Colors.black))
      ..addText(xAxisIntLabelList[j].minute.toString());

    final ui.Paragraph paragraph = builder.build()
      ..layout(new ui.ParagraphConstraints(width: leftOffsetStart));
    return paragraph;
  }

  ///XAxis Step Difference
  ///Difference divide by 5 for 5 labels
  ///Return a new List<int> with max = max-xDiff;
  ///Build according to data.length : Build 6
  List<DateTime> stepDifferenceXAxis(Size size, List<DataEntry> dataEntryList,
      Duration xDifference, DateTime max, DateTime min) {
//    dataEntryList.add(_buildCurrentWaitingData());

//    max = DateTime.now();
//    Duration difference = max.difference(min);

    print(
        'xDIff in stepDiffXAxis is ${xDifference.inMinutes}, diff is ${xDifference.inMinutes}');
    xDifferenceAddedDateTimeNow = int.parse((xDifference.inMinutes.toString()));

    double stepValue = xDifference.inMinutes / 10;
    print('stepValue is ${stepValue}');


    //print('\n/////////////////'      'xMax is $max and xDiff is $xDiff dataEntryList.length ${dataEntryList.length}'      '\n//////////////////////');

    List<DateTime> newList = [];

    for (int i = 0; i < 9; i++) {
      newList.add(max);
      xDateTime.add(max);
      print('i is $i max is $max ${dataEntryList[0].dataTime} ');

      max = max.subtract(Duration(minutes: stepValue.ceil()));

      print('xAxisCummulative is ${max}  maxDay is ${dataEntryList.length}');
    }

    if (min.isBefore(newList[8])) {
      newList.add(min);
    } else {
      newList.add(max.subtract(Duration(minutes: stepValue.ceil())));
    }

    print('newList is $newList');
    return newList;
  }

  /// Draw YAxis label,
  /// Build 6 Paragraphs(1,3,5,7,9,11) with _buildXAxisLabel()
  /// Draw Paragraphs at XLine
  /// Collect Data Value and Y Position of the lines
  /// Calculate difference of the lines and find out relative position of each value
  void drawYAxisLabel(List<double> yAxisIntList, Size size, Canvas canvas) {
    double singleHeight = size.height / 11;
    double singleWidth = size.width / 6;

    ui.Paragraph paragraph1 = _buildYAxisLabel(yAxisIntList, size, canvas, 0);
    ui.Paragraph paragraph3 = _buildYAxisLabel(yAxisIntList, size, canvas, 1);
    ui.Paragraph paragraph5 = _buildYAxisLabel(yAxisIntList, size, canvas, 2);
    ui.Paragraph paragraph7 = _buildYAxisLabel(yAxisIntList, size, canvas, 3);
    ui.Paragraph paragraph9 = _buildYAxisLabel(yAxisIntList, size, canvas, 4);
    ui.Paragraph paragraph11 = _buildYAxisLabel(yAxisIntList, size, canvas, 5);

    canvas.drawParagraph(
        paragraph1, Offset(singleWidth - 20, singleHeight * 1));

    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[0], singleHeight * 1))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[0], singleHeight * 1));
    }
    canvas.drawParagraph(
        paragraph3, Offset(singleWidth - 20, singleHeight * 3));
    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[1], singleHeight * 3))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[1], singleHeight * 3));
    }
    canvas.drawParagraph(
        paragraph5, Offset(singleWidth - 20, singleHeight * 5));
    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[2], singleHeight * 5))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[2], singleHeight * 5));
    }
    canvas.drawParagraph(
        paragraph7, Offset(singleWidth - 20, singleHeight * 7));
    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[3], singleHeight * 7))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[3], singleHeight * 7));
    }
    canvas.drawParagraph(
        paragraph9, Offset(singleWidth - 20, singleHeight * 9));
    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[4], singleHeight * 9))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[4], singleHeight * 9));
    }
    canvas.drawParagraph(
        paragraph11, Offset(singleWidth - 20, singleHeight * 11));
    if (!yDataLabelsPosition
        .contains(YDataPositionOnGraph(yAxisIntList[5], singleHeight * 11))) {
      yDataLabelsPosition
          .add(YDataPositionOnGraph(yAxisIntList[5], singleHeight * 11));
    }
    yLineDifference =
        (yDataLabelsPosition[1].position - yDataLabelsPosition[0].position) /
            (yDataLabelsPosition[0].value - yDataLabelsPosition[1].value);

    print('yLineDifference is $yLineDifference');
  }

  ///Build YAxisLabel Paragraph
  ui.Paragraph _buildYAxisLabel(
      List<double> yLineLabelList, Size size, Canvas canvas, j) {
    double leftOffsetStart = size.width * 0.11;
    ui.ParagraphBuilder builder;

    builder = ui.ParagraphBuilder(
      new ui.ParagraphStyle(
        fontSize: 10.0,
        textAlign: TextAlign.start,
      ),
    );

    builder
      ..pushStyle(new ui.TextStyle(color: Colors.black))
      ..addText(yLineLabelList[j].toString());

    final ui.Paragraph paragraph = builder.build()
      ..layout(new ui.ParagraphConstraints(width: leftOffsetStart));
    return paragraph;
  }



  ///YAxis Step Difference
  ///Difference divide by 5 for 5 labels
  ///Return a new List<int> for Labelling with max = max-xLineDiff;
  List<double> stepDifferenceYAxis(List<DataEntry> dataEntryList,
      double yDifference, double max, double min) {
    double stepDiff = yDifference / 5;

    print('ydifference is $yDifference');
    List<double> newList = [];

    for (int i = 0; i <= 6; i++) {
      //print('max is $max');
      print(
          'max ceil is ${max.ceil()} max round is ${max.round()} max floor is ${max.floor()}');
      newList.add(double.parse(max.floor().toStringAsFixed(2)));

      max = max - stepDiff;
    }

    //print('instantiate newlist[0] as max ${newList[0]}');

    return newList;
  }

  ///Get Difference between Max And Min
  double yDifferenceBetweenMaxAndMin(max, min) {
    return max - min;
  }

  Duration xDifferenceBetweenMaxAndMin(DateTime max, DateTime min) {
    return max.difference(min);
  }

  ///Build Current Data point
  DataEntry _buildCurrentWaitingData() {
    return DataEntry(null, DateTime.now());
  }

//TODO Work on representing X region with step
  ///Plot Data
  /// Put all x and y values in a list of their own type
  /// Define dataPlotSize
  /// Calls checkDataAndPlot()
  /// DrawLine for all plots
  void plotData(
      List<DataEntry> dataEntryList,
      Canvas canvas,
      Size size,
      double yDifference,
      Duration xDifference,
      singleWidth,
      singleHeight,
      max) {
    //dataPlotSize is the Data Plotting region

    for (int j = 0; j < yDataLabelsPosition.length; j++) {
      if (!yLabelsInDouble.contains(yDataLabelsPosition[j].value)) {
        yLabelsInDouble.add(yDataLabelsPosition[j].value);
      }
    }

    for (int j = 0; j < xDataLabelsPosition.length; j++) {
      if (!xLabelInDateTime.contains(xDataLabelsPosition[j].value)) {
        xLabelInDateTime.add(xDataLabelsPosition[j].value);
      }
    }

    print('xlabels in int $xLabelInDateTime');
    print('xlabels[0] = ${xDataLabelsPosition[0].position}');

    Size dataPlotSize =
    Size(size.width - singleWidth, size.height - singleHeight);

    var paint = Paint();
    paint.color = Colors.blueGrey[500];
    paint.strokeWidth = 3;

    print('yDiff is $yDifference');
    //dataPlotSizeheight / difference, meaning representing each step by its plotting height

    double singlePlotHeight = dataPlotSize.height / yDifference;
    double stepWidth = dataPlotSize.width / dataEntryList.length;

    print(
        'singlePlotHeight is $singlePlotHeight  size is $size dataPlotSize is $dataPlotSize singleHeight is $singleHeight');

    print('max is $max');
    print(
        'data value is ${dataEntryList[2].dataValue} , max - datavalue is ${max - dataEntryList[2].dataValue}');
    print('xDiffAddedDTNow $xDifferenceAddedDateTimeNow');

    for (int i = 0; i < dataEntryList.length; i++) {
      print('\n////////////////\nPLOTTING GRAPH\n////////////////\n');

      print('dataEntry Value is ${dataEntryList[i].dataValue}');

      checkDataPositionAndPlot(dataEntryList, canvas, i);
      print('all YData ${yDataPosition.length} ');

    }

    print('ydataposition ${yDataPosition.length}');
    print('xdataposition ${xDataPosition.length}');
    print('xlabelsposition ${xDataLabelsPosition.length}');

    for (int i = 0; i < yDataPosition.length - 1; i++) {
      canvas.drawLine(
          Offset(xDataPosition[i].position, yDataPosition[i].position),
          Offset(xDataPosition[i + 1].position, yDataPosition[i + 1].position),
          paint);
    }
  }

  /// CheckDataPositionAndPlot
  /// 1. Check if dataEntry should be plotted on line (exists in yLabelsInDouble)
  ///     a. If exists, forEach dataLabelPosition that is == to dataEntry
  ///        add data to yDataPosition with the position
  ///     b. Else, check if dataEntry is null, --> do nothing
  ///     c. Else, dataEntry should not be plotted on line,
  ///        for loop to check dataEntry falls in which region by subtracting
  ///        dataEntry with the label value, If negative, then take the previous
  ///        line and find the difference in value and position then add to yDataPosition
  /// 2. Note : a. first label value on  X Axis is assigned directly depending on whether it is < the
  ///              consecutive label value
  ///           b. Checks if falls between the first label [9] and second label [8]
  ///           c. Use xLineDifference and xMinLineDifference accordingly
  void checkDataPositionAndPlot(
      List<DataEntry> dataEntryList, Canvas canvas, i) {
    print('yDatalabel Length ${yDataLabelsPosition.length}');

    if (yLabelsInDouble.contains(dataEntryList[i].dataValue)) {
      print(' ${dataEntryList[i].dataValue} y is online');

      yDataLabelsPosition.forEach((f) {
        print("${f.value} is fvalue ");

        if (f.value == dataEntryList[i].dataValue) {
          print("${f.value} value added ");
          yDataPosition.add(YDataPositionOnGraph(f.value, f.position));
        }
      });
    } else {
      if (dataEntryList[i].dataValue == null) {
      } else {
        print('!!!! ${dataEntryList[i].dataValue}not online !!!!');
        double sign;

        for (int j = yLabelsInDouble.length - 1; j >= 0; j--) {
          sign = 0;
          sign = dataEntryList[i].dataValue - yDataLabelsPosition[j - 1].value;

//          print('iteration $j ydatalabel ${yDataLabelsPosition[j].value}');
          if (sign.isNegative) {
            double deviation =
                dataEntryList[i].dataValue - yDataLabelsPosition[j].value;
            print(
                ' datavalue =  ${dataEntryList[i].dataValue}, ydatalabel [j]${yDataLabelsPosition[j].value}  deviation ${deviation}');

            yDataPosition.add(YDataPositionOnGraph(dataEntryList[i].dataValue,
                yDataLabelsPosition[j].position - deviation * yLineDifference));

            print('not on graph added ');
            break;
          }
        }
      }
    }

    print(
        'xlabel in int [0] ${xLabelInDateTime.length} dataTime[0] ${dataEntryList[i].dataTime.day}');

///////////////////////////////////////////////////////////////////////////////////////////////////

    if (xLabelInDateTime.contains(dataEntryList[i].dataTime)) {
      print(' ${dataEntryList[i].dataTime} x is online');

      xDataLabelsPosition.forEach((f) {
        print("${f.value} is fvalue ");

        if (f.value == dataEntryList[i].dataTime) {
          print("${f.value} X value added ");
          xDataPosition.add(XDataPositionOnGraph(f.value, f.position));
        }
      });
    } else {
      if (dataEntryList[i].dataValue == null) {
      } else {
        print('datalabelpost length ${xDataLabelsPosition.length}');
        print('dataentry length ${dataEntryList.length}');
        print('xlabelint  ${xLabelInDateTime[0]}');
        print('!!!! ${dataEntryList[i].dataTime.minute}not online !!!!');

        for (int j = xLabelInDateTime.length - 1; j >= 0; j--) {
//
//

          print('X,iteration $j xdatalabel ${xDataLabelsPosition[j].value}');
          if (dataEntryList[i].dataTime.isAfter(xDataLabelsPosition[j].value) &&
              dataEntryList[i]
                  .dataTime
                  .isBefore(xDataLabelsPosition[j - 1].value)) {
            int deviation = dataEntryList[i]
                .dataTime
                .difference(xDataLabelsPosition[j].value)
                .inMinutes;
            print(
                ' datavalue =  ${dataEntryList[i].dataTime.day}, xdatalabel [j]${xDataLabelsPosition[j].value}  deviation ${deviation}');

            if (j == xLabelInDateTime.length - 1) {
              xDataPosition.add(XDataPositionOnGraph(
                  dataEntryList[i].dataTime,
                  xDataLabelsPosition[j].position +
                      deviation * xMinLineDifference));
            } else {
              xDataPosition.add(XDataPositionOnGraph(
                  dataEntryList[i].dataTime,
                  xDataLabelsPosition[j].position +
                      deviation * xLineDifference));

              print('not on graph added ');
              break;
            }
          }
        }

        print('Y Not on graph');
      }
    }
  }

  /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///
  /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///
  /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///      /// /// /// /// /// /// /// ///

  List<XDataPositionOnGraph> xDataLabelsPosition = [];
  List<YDataPositionOnGraph> yDataLabelsPosition = [];
  List<DateTime> xDateTime = [];

  double yMax =0 , yMin=0, yDifference=0;
  DateTime xMax, xMin;
  Duration xDifference;

  int xDifferenceAddedDateTimeNow=0;
  double yLineDifference, xLineDifference, xMinLineDifference=0;

  List<YDataPositionOnGraph> yDataPosition = [];
  List<XDataPositionOnGraph> xDataPosition = [];
  List<double> yLabelsInDouble = [];
  List<DateTime> xLabelInDateTime = [];

  int holder;
  double stepDifference;

  List<DataEntry> dataEntryList = [];

  @override
  void paint(Canvas canvas, Size size) {
    leftOffsetStart = size.width * 0.07;
    topOffsetEnd = size.height * 0.9;
    drawingWidth = size.width * 0.93;
    drawingHeight = topOffsetEnd;
    sortMaxAndMinValue(dataEntryList);

    int sinceEpoch1 = dataEntryList[3].dataTime.millisecondsSinceEpoch;

    int sinceEpoch0 = dataEntryList[0].dataTime.millisecondsSinceEpoch;

    int diffEpoch = sinceEpoch1 - sinceEpoch0;

    print(
        'from Epoch ${DateTime.fromMillisecondsSinceEpoch(diffEpoch).minute} duration  is ${dataEntryList[3].dataTime.difference(dataEntryList[0].dataTime).inMinutes}');

    //print('after sortMaxMinValue diff is $yDifference');
    drawHorizontalLinesAndLabels(dataEntryList, size, canvas, xDifference,
        yDifference, yMax, yMin, xMax, xMin);
  }

  @override
  bool shouldRepaint(GraphWidget old) => true;

  GraphWidget(this.dataEntryList);
}

GraphCardWidget -- 基本上是用卡片包裹它

import 'package:flowy/models/data_entry.dart';
import 'package:flowy/state_management/main.dart';
import 'package:flowy/widget/graph_widget.dart';
import 'package:flowy/widget/graph_widget_without_labels.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';




class GraphCardWidget extends StatefulWidget {
  double height, width;
  List dataEntryList;
  bool withLabel;

  GraphCardWidget(this.height, this.width, this.dataEntryList,
      {this.withLabel = true});

  @override
  State<StatefulWidget> createState() {
    return GraphCardWidgetState();
  }


}


class GraphCardWidgetState extends State<GraphCardWidget> {



  double _value = 0.0;

  void _setvalue(double value) => setState(() => _value = value);

  @override
  Widget build(BuildContext context) {





    return
      widget.withLabel == true ? Column(
          children: <Widget>[ Card(
              child: Column(
                children: <Widget>[
                  Container(
                    padding: EdgeInsets.only(bottom: widget.height * 0.03,
                        right: widget.width * 0.05)
                    ,
                    height: widget.height * 0.4,
                    width: widget.width * 0.94,


                    child:

                         CustomPaint(
                          size: Size(widget.height * 0.1, widget.width * 0.01),
                          painter: GraphWidget(widget.dataEntryList),
                        )
                  ),

                  new Slider(value: _value, onChanged: _setvalue)

                ],
              )),

          ]

      ) : Card(
        child: Container(
          padding: EdgeInsets.only(
              bottom: widget.height * 0.03, right: widget.width * 0.05),
          height: widget.height * 0.4,
          width: widget.width * 0.94,
//        child: GestureDetector(

          child: CustomPaint(
            size: Size(widget.height * 0.1, widget.width * 0.01),
            painter: GraphWidgetWithoutLabels(widget.dataEntryList),
          ),
        ),
        );

  }

}

我构建 GraphCardWidget 的页面




import 'package:flutter/material.dart';

//Third party library import
import 'package:provider/provider.dart';

//Local import
import 'package:flowy/widget/drawer_widget.dart';
import 'package:flowy/state_management/main.dart';
import 'package:flowy/models/data_entry.dart';
import 'package:flowy/utils/dummy_data.dart';
import 'package:flowy/widget/graph_card_widget.dart';

/// Pressure = Volume for Petroleum
class PressurePage extends StatefulWidget {
  MainStateManager manager;

  PressurePage(this.manager);

  @override
  State<StatefulWidget> createState() {
    return _PressurePageState();
  }
}

class _PressurePageState extends State<PressurePage> {
  List<String> _RTUList;
  List<DataEntry> _dataEntryList;
  int _index;
  String _dropDownBtnSelectedVal;

  @override
  void initState() {
    if (widget.manager.dataIndex == null) {
      _index = 0;
    } else {
      _index = widget.manager.dataIndex;
    }
    _RTUList = DummyData('Volume').RTUList;
    _dataEntryList = DummyData('Volume').buildDataEntry()[_index];
    _dropDownBtnSelectedVal = _RTUList[_index];
    print('RTUList is $_RTUList');
    print('dropdownValue is $_dropDownBtnSelectedVal');
    super.initState();
  }

  DropdownButton _buildDropDownButton() {
    final List<DropdownMenuItem<String>> _dropDownMenuItems = _RTUList.map(
      (String value) => DropdownMenuItem<String>(
            value: value,
            child: Text(value),
          ),
    ).toList();
    return DropdownButton<String>(
      value: _dropDownBtnSelectedVal,
      onChanged: ((String newValue) {
        setState(() {
          _dropDownBtnSelectedVal = newValue;
          _dataEntryList = DummyData('Volume')
              .buildDataEntry()[_RTUList.indexOf(_dropDownBtnSelectedVal)];
        });
      }),
      items: _dropDownMenuItems,
    );
  }

  @override
  Widget build(BuildContext context) {
    print('dataEntryList is $_dataEntryList');
    final double width = MediaQuery.of(context).size.width;
    final double height = MediaQuery.of(context).size.height;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).accentColor,
        title: Text('Volume'),
      ),
      body: Stack(
        children: <Widget>[
          Container(
            color: Theme.of(context).primaryColor,
          ),
          Container(
            alignment: Alignment.center,
            child: Consumer<MainStateManager>(builder:
                (BuildContext context, MainStateManager manager, Widget child) {
              return Center(
                child: Column(
                  children: <Widget>[
                    ListTile(
                      title: _buildDropDownButton(),
                    ),
                    Consumer<MainStateManager>(builder: (BuildContext context,
                        MainStateManager manager, child) {
                      return GraphCardWidget(
                          height, width, manager.handleInputDateTime());
                    }),
                    Expanded(
                        child: Container(
                      child: Card(
                          child: RaisedButton(
                              child: Text('hehe '),
                              onPressed: () {

                              })),
                    ))
                  ],
                ),
              );
            }),
          )
        ],
      ),
    );
  }
}



期望 CustomPaint 小部件不会在没有实际 onPressed 回调的情况下为每个按钮点击进行绘制

【问题讨论】:

    标签: canvas flutter triggers widget paint


    【解决方案1】:

    我发现了问题。 这实际上是 Flutter FMK 中的一个错误,详细信息如下:https://github.com/flutter/flutter/issues/49298

    解决方案(嗯,解决方法...)是将CustomPaint 包装在RepaintBoundary 中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      • 2018-02-01
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多