Latest source merged from Syncfusion

This commit is contained in:
pipeline 2021-03-30 15:06:48 +05:30
Родитель bf5a03ebc0
Коммит 15bdf65e0e
250 изменённых файлов: 14103 добавлений и 2045 удалений

Просмотреть файл

@ -0,0 +1,17 @@
---
title: Essential Studio for Flutter 2021 volume 1 Main Release Notes
description: Essential Studio for Flutter 2021 volume 1 Main Release Notes
platform: flutter
documentation: ug
---
# Essential Studio for Flutter Release Notes
{% include release-info.html date="March 30, 2021" version="v19.1.0.54" %}
{% directory path: _includes/release-notes/v19.1.0.54 %}
{% include {{file.url}} %}
{% enddirectory %}

Просмотреть файл

@ -114,6 +114,75 @@ To position the annotation based on the pixel values, set the [`CoordinateUnit`]
![Positioning based on coordinateUnit as pixels](images/annotation/annotation_pixel.jpg)
**Positioning based on region**
Annotations can be placed with respect to either [`AnnotationRegion.plotArea`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/AnnotationRegion-class.html) or [`AnnotationRegion.chart`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/AnnotationRegion-class.html) in [`region`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation/region.html) property.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
child: SfCartesianChart(
annotations: <CartesianChartAnnotation>[
CartesianChartAnnotation(
widget: Container(
child: const Text('Text')
),
region: AnnotationRegion.chartArea,
coordinateUnit: CoordinateUnit.logicalPixel,
x: 150,
y: 200
)
]
)
)
)
)
);
}
{% endhighlight %}
## Alignment of annotation
[`CartesianChartAnnotation`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation-class.html) can be aligned to center, near and far using the [`horizontalAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation/horizontalAlignment.html) and [`verticalAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation/verticalAlignment.html) properties of annotation.
The following code example demonstrates how to set the [`horizontalAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation/horizontalAlignment.html) for annotation
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
child: SfCartesianChart(
annotations: <CartesianChartAnnotation>[
CartesianChartAnnotation(
widget: Container(
child: const Text('Text')
),
region: AnnotationRegion.chartArea,
coordinateUnit: CoordinateUnit.logicalPixel,
x: 150,
y: 200,
HorizontalAlignment: HorizontalAlignment.near,
)
]
)
)
)
)
);
}
{% endhighlight %}
## Adding multiple annotation
You can add multiple annotations to the Chart by adding multiple widgets to the [`annotations`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianChartAnnotation-class.html) property. as depicted in below code snippet.

Просмотреть файл

@ -652,6 +652,8 @@ The following properties are used to configure the plot bands:
* [`verticalTextAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/PlotBand/verticalTextAlignment.html) - Aligns the text vertically.
* [`isVisible`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/PlotBand/isVisible.html) - Changes the visibility of the plot band in chart axis.
* [`shouldRenderAboveSeries`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/PlotBand/shouldRenderAboveSeries.html) - Changes the rendering order of the plot band.
* [`isRepeatable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/PlotBand/isRepeatable.html) - specifies the plot band need to be repeated in specified interval.
* [`textStyle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/textStyle.html) - customizes the text style of plot band.
![Plotband](images/axis-customization/plotband.jpg)
@ -1081,6 +1083,63 @@ N> If both [`maximumLabelWidth`](https://pub.dev/documentation/syncfusion_flutte
![Axis label trim](images/axis-customization/axis-label-trim.gif)
## Auto scrolling
Auto scrolling feature available in SfCartesianChart is used to ensure that specified range of data is always visible in the chart and you can view the remaining data points by scrolling. The [`autoScrollingDelta `](~) property of the chart axis can be used to set the number of data points to be always visible in the chart. It always shows the recently added data points and scrolling will be reset to the start or end of the range, based on [`autoScrollingMode`](~) property's value, whenever a new point is added dynamically.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
primaryYAxis: DateTimeAxis(
autoScrollingDelta: 7
),
)
);
}
{% endhighlight %}
### AutoScrollingMode
[`AutoScrollingMode`](~) property can be used to determine whether the axis should be scrolled from start position or end position. The default value of [`AutoScrollingMode`](~) is `end`.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
primaryYAxis: NumericAxis(
autoScrollingMode: AutoScrollingMode.start
),
)
);
}
{% endhighlight %}
### AutoScrollingDeltaType
In [`DateTimeAxis`](~), you can apply auto scrolling delta value in Years, Months, Days, Hours, Minutes, Seconds and auto by setting [`AutoScrollingDeltaType`](~) property. Default value of this property is `auto` and the delta will be calculated automatically based on range.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
primaryYAxis: DateTimeAxis(
autoScrollingDeltaType: DateTimeIntervalType.months
),
)
);
}
{% endhighlight %}
## See Also
* [Rendering a particular part of a data using visible minimum and visible maximum in the Cartesian chart](https://www.syncfusion.com/kb/11308/how-to-render-particular-part-of-a-data-in-cartesian-charts-sfcartesianchart).

Просмотреть файл

@ -16,6 +16,7 @@ Vertical(Y) axis always uses numerical scale. Horizontal(X) axis supports the fo
* Category
* Numeric
* Date-time
* Date-time category
* Logarithmic
## Numeric axis
@ -688,6 +689,120 @@ The [`dateFormat`](https://pub.dev/documentation/syncfusion_flutter_charts/lates
Also refer [label format](./axis-customization#formatting-axis-label-content) and [number format](#formatting-the-labels) for formatting the labels further.
## Date-time category axis
Date-time category axis is a combination of both [`DateTimeAxis`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DateTimeAxis/DateTimeAxis.html) and [`CategoryAxis`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CategoryAxis-class.html). Date-time category axis is used to display the date-time values with non-linear intervals. For example, the business days alone have been depicted in a week here.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SfCartesianChart(
primaryXAxis: DateTimeCategoryAxis()
)
)
)
);
}
{% endhighlight %}
![DateTimeCategory axis](images/axis-types/datetimecategory.jpg)
### Customizing range
To customize the range of an axis, use the [`minimum`](~) and [`maximum`](~) properties of [`DateTimeCategoryAxis`](~). By default, nice range will be calculated automatically based on the provided data.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SfCartesianChart(
primaryXAxis: DateTimeCategoryAxis(
minimum: DateTime(2010, 2, 3),
maximum: DateTime(2010, 2, 10)
)
)
)
)
);
}
{% endhighlight %}
![DateTimeCategory range](images/axis-types/datetimecategory_range.jpg)
### Date-time intervals
The date-time category intervals can be customized using the [`interval`](~) and [`intervalType`](~) properties of [`DateTimeCategoryAxis`](~). For example, To display the axis labels after a fixed interval n, set the [`interval`](~) property of ChartAxis to n and to display the labels in months, set the [`intervalType`](~) property of DateTimeCategoryAxis as months.
The Flutter Chart supports the following types of interval for date-time category axis:
* auto
* years
* months
* days
* hours
* minutes
* seconds
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SfCartesianChart(
primaryXAxis: DateTimeCategoryAxis(
// Interval type will be years
intervalType: DateTimeIntervalType.months,
interval: 2
)
)
)
)
);
}
{% endhighlight %}
![DateTimeCategory intervals](images/axis-types/datetimecategory_interval.jpg)
### Formatting the labels
The [`dateFormat`](~) property formats the date-time category axis labels. The default data-time category axis label can be formatted with various built-in [`date formats`](https://api.flutter.dev/flutter/intl/DateFormat-class.html), which depend on the given data source.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SfCartesianChart(
primaryXAxis: DateTimeCategoryAxis(
// X axis labels will be rendered based on the below format
dateFormat: DateFormat.yMMMd()
)
)
)
)
);
}
{% endhighlight %}
![DateTimeCategory date format](images/axis-types/datetimecategory_dateFormat.jpg)
Also refer [label format](./axis-customization#formatting-axis-label-content) and [number format](#formatting-the-labels) for formatting the labels further.
## Logarithmic axis
Logarithmic axis uses logarithmic scale and displays numbers as axis labels.

Просмотреть файл

@ -802,7 +802,37 @@ N> This callback will not be called, when the builder is specified for data labe
{% endhighlight %}
## onPlotAreaSwipe
Triggers while swiping on the plot area. Whenever the swiping happens on the plot area (the series rendering area), [`onPlotAreaSwipe`](~) callback will be called. It provides options to get the direction of swiping. If the chart is swiped from left to right direction, the direction is [`ChartSwipeDirection.start`](~) and if the swipe happens from right to left direction, the direction is [`ChartSwipeDirection.end`](~). Using this callback, the user will be able to achieve pagination functionality (i.e., on swiping over chart area, next set of data points can be loaded to the chart).
{% highlight dart %}
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
onPlotAreaSwipe:
(ChartSwipeDirection direction) =>
performSwipe(direction),
series: <ChartSeries<SalesData, num>>[
AreaSeries<SalesData, num>(
dataSource: chartData,
),
],
)
);
}
Widget performSwipe(ChartSwipeDirection direction) {
if (direction == ChartSwipeDirection.end) {
chartData.add(ChartSampleData(
x: chartData[chartData.length - 1].x + 1,
y: 10));
seriesController.updateDataSource(addedDataIndex: chartData.length - 1);
}
}
{% endhighlight %}
## See Also

Просмотреть файл

@ -13,6 +13,11 @@ documentation: ug
Chart renders based on the parent widget size. If you need the chart to be rendered in specific size, then set the size(width/height) to the parent widget.
You can also customize the following properties:
* [`backgroundColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeries/backgroundColor.html) - used to changes the background color of the chart.
* [`borderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeries/borderWidth.html) - used to change the border width.
* [`borderColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeries/borderColor.html) - used to change the color of the chart border.
{% highlight dart %}
@override

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 400 KiB

Двоичные данные
Flutter/cartesian-charts/images/axis-types/datetimecategory.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 28 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 42 KiB

Просмотреть файл

@ -51,6 +51,12 @@ The [`name`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/char
* [`borderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/borderWidth.html) - used to change the stroke width of the legend icon shape.
* [`iconBorderColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/iconBorderColor.html) - used to change the stroke color of the legend icon shape.
* [`itemPadding`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/itemPadding.html) - used to add padding between the first legend text and the second legend icon shape.
* [`height`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/height.html) - the height of the legend.
* [`width`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/width.html) - the width of the legend.
* [`isResponsive`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/isResponsive.html) - toggles the visibility of the legend. If the width or height of the legend is greater than the plot area bounds.
* [`iconBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/iconBorderWidth.html) - border width of the icon in the legend items. Used to change the stroke width of the legend icon shape.
* [`overflowMode`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/overflowMode.html) - overflow legend items.
{% highlight dart %}

Просмотреть файл

@ -147,6 +147,9 @@ Data label can be added to a chart series by enabling the [`isVisible`](https://
* [`borderRadius`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/borderRadius.html) - used to add the rounded corners to the data label shape.
* [`angle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/angle.html) - used to rotate the labels.
* [`offset`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/offset.html) - used to movethedata label vertically or horizontally from its position.
* [`showCumulativeValues`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/showCumulativeValues.html) - to show the cumulative values in stacked type series charts.
* [`labelIntersectAction`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelIntersectAction.html) - action on data labels intersection. The intersecting data labels can be hidden.
* [`labelPosition`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelPosition.html) - position of the data label.
{% highlight dart %}

Просмотреть файл

@ -0,0 +1,57 @@
---
layout: post
title: On demand loading feature in Syncfusion Flutter charts
description: Learn how to achieve infinite scrolling functionality in Syncfusion Flutter Cartesian charts using the on demand loading feature.
platform: flutter
control: Chart
documentation: ug
---
# On-demand loading in Cartesian chart
[`SfCartesianChart`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart-class.html) provides support to return a widget which can be used to load more data to the chart when the visible range reaches the end on dragging in the chart with the help of the [`loadMoreIndicatorBuilder`](~) builder.
## Infinite scrolling
The [`loadMoreIndicatorBuilder`](~) builds the widget at the top of the chart area (ex., loading indicator or load more button) when horizontal scrolling reaches the start or end of the chart and if the chart is transposed then, this will be called when the vertical scrolling reaches the top or bottom of the chart. this can be used to achieve the functionalities like infinite scrolling in the chart.
The below example demonstrates the infinite scrolling by showing the circular progress indicator until the data is loaded when horizontal scrolling reaches the end of the chart.
{% highlight dart %}
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
loadMoreIndicatorBuilder:
(BuildContext context, ChartSwipeDirection direction) =>
getLoadMoreViewBuilder(context, direction),
series: <ChartSeries<SalesData, num>>[
AreaSeries<SalesData, num>(
dataSource: chartData,
),
],
)
);
}
Widget getLoadMoreViewBuilder(
BuildContext context, ChartSwipeDirection direction) {
if (direction == ChartSwipeDirection.end) {
return FutureBuilder<String>(
future: _updateData(), /// Adding data by updateDataSource method
builder:
(BuildContext futureContext, AsyncSnapshot<String> snapShot) {
return snapShot.connectionState != ConnectionState.done
? const CircularProgressIndicator()
: SizedBox.fromSize(size: Size.zero);
},
);
} else {
return SizedBox.fromSize(size: Size.zero);
}
}
{% endhighlight %}
![Infinite_scrolling](images/on-demand-loading/infinite_scrolling.gif)

Просмотреть файл

@ -56,6 +56,7 @@ You can customize the segments using the below properties.
* [`unselectedBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/unselectedBorderWidth.html) - used to change the stroke width of the unselected segment.
* [`selectedOpacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/selectedOpacity.html) - used to control the transparency of the selected segment.
* [`unselectedOpacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/unselectedOpacity.html) - used to control the transparency of the unselected segment.
* [`selectionController`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/selectionController.html) - to customize the minimum range of selected series or points.
{% highlight dart %}

Просмотреть файл

@ -60,6 +60,11 @@ You can use the following properties to customize the tooltip appearance.
* [`header`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/header.html) - specifies the header for tooltip. By default, the series name will be displayed in the header.
* [`format`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/format.html) - formats the tooltip text. By default, the tooltip will be rendered with x and y-values. You can add prefix or suffix to x, y, and series name values in the tooltip by formatting them.
* [`shadowColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shadowColor.html) - specifies the color of the tooltip shadow.
* [`shouldAlwaysShow`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shouldAlwaysShow.html) - Shows or hides the tooltip. By default, the tooltip will be hidden on touch. To avoid this, set this property to true.
* [`textAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/textAlignment.html) - alignment of the text in the tooltip.
* [`header`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/header.html) - header of the tooltip. By default, the series name will be displayed in the header.
* [`textStyle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/textStyle.html) - customizes the tooltip text.
* [`shared`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shared.html) - share the tooltip with same index points.
{% highlight dart %}

Просмотреть файл

@ -30,7 +30,7 @@ You can use the following properties to customize the appearance of trackball to
* [`tooltipSettings.textStyle.fontFamily`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTextStyle/fontFamily.html) - used to change the font family for tooltip text.
* [`tooltipSettings.textStyle.fontStyle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTextStyle/fontStyle.html) - used to change the font style for tooltip text.
* [`tooltipSettings.textStyle.fontSize`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTextStyle/fontSize.html) - used to change the font size for tooltip text.
* `hideDelay` - used to specify disappear delay for trackball.
* [`hideDelay`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballBehavior/hideDelay.html ) - used to specify disappear delay for trackball.
N> The above mentioned properties are only applicable for SfCartesian types of charts.
@ -290,7 +290,7 @@ The ActivationMode enum contains the following values:
![Trackball tooltip overlap](images/trackball-crosshair/trackball_overlap.png)
### Trackball marker
### Trackball marker settings
Trackball markers are used to provide information about the exact point location. You can add a shape to adorn each data point when the trackball is visible. Trackball markers can be enabled by using the [`markerVisibility`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballMarkerSettings/markerVisibility.html) property of [`TrackballMarkerSettings`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballMarkerSettings-class.html). The below [`markerVisibility`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballMarkerSettings/markerVisibility.html) property values determines whether the trackball marker should be visible or not when the trackball is enabled in the chart
@ -415,11 +415,74 @@ You can customize the appearance of the trackball tooltip with your own widgets
{% endhighlight %}
![Trackball template](images/trackball-crosshair/trackball_template.jpg)
### Trackball grouping mode info
[TrackballGroupingModeInfo](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo-class.html) is store the group mode details of trackball template.
The following properties are available in [`TrackballGroupingModeInfo`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo-class.html):
* [`points`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo/points.html) - it specifies the Cartesian chart points.
* [`currentPointIndices`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo/currentPointIndices.html) - it specifies the current point indices.
* [`visibleSeriesIndices`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo/visibleSeriesIndices.html) - it specifies the visible series indices.
* [`visibleSeriesList`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TrackballGroupingModeInfo/visibleSeriesList.html) - it specifies the Cartesian visible series list.
### Trackball tooltip Marker
The [`canShowMarker`]() is used to toggle the visibility of the marker in the trackball tooltip.
Markers are rendered with the series color and placed near the value in trackball tooltip to convey which value belongs to which series.
Trackball tooltip marker uses the same shape specified for the series marker. But trackball tooltip marker will render based on the value specified to this property irrespective of considering the series marker's visibility.
Defaults to `true`.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
child: Center(
child: Container(
child: SfCartesianChart(
trackballBehavior: TrackballBehavior(
enable: true,
),
series: <LineSeries<SalesData, double>>[
LineSeries<SalesData, double>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales),
LineSeries<SalesData, double>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales2),
LineSeries<SalesData, double>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales3),
LineSeries<SalesData, double>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales4),
LineSeries<SalesData, double>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales5, _) => sales.sales),
]
)
)
)
);
}
{% endhighlight %}
![Trackball tooltip marker](images/trackball-crosshair/trackball_tooltip_marker.png)
## Crosshair
Crosshair has a vertical and horizontal line to view the value of the axis.
Crosshair lines can be enabled by using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/enable.html) property in the [`crosshairBehavior`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/CrosshairBehavior.html). Likewise tooltip label for an axis can be enabled by using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/enable.html) property of [`crosshairTooltip`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/crosshairTooltip.html) in the corresponding axis. The `hideDelay` property can be used to specify a disappear delay for the crosshair.
Crosshair lines can be enabled by using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/enable.html) property in the [`crosshairBehavior`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/CrosshairBehavior.html). Likewise tooltip label for an axis can be enabled by using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/enable.html) property of [`interactiveTooltip`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/interactiveTooltip.html) in the corresponding axis. The [`hideDelay`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/hideDelay.html) property can be used to specify a disappear delay for the crosshair.
N> The above mentioned properties are only applicable for SfCartesian types of charts.
@ -469,6 +532,7 @@ The appearance of the track line in crosshair can be customized using the follow
* [`lineColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/lineColor.html) - specifies the color of the crosshair line.
* [`lineWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/lineWidth.html) - specifies the stroke width of the crosshair line.
* [`lineDashArray`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/lineDashArray.html) - used to render crosshair line with dashes.
* [`shouldAlwaysShow`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CrosshairBehavior/shouldAlwaysShow.html) - enables or disables the crosshair. Defaults to false.
{% highlight dart %}
@ -507,7 +571,7 @@ The appearance of the track line in crosshair can be customized using the follow
### Show axis tooltip
The axis tooltip can be enabled using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/InteractiveTooltip/enable.html) property of [`crosshairTooltip`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/crosshairTooltip.html). You can customize the appearance of axis tooltip using the following properties.
The axis tooltip can be enabled using [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/InteractiveTooltip/enable.html) property of [`interactiveTooltip`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/interactiveTooltip.html). You can customize the appearance of axis tooltip using the following properties.
* [`enable`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/InteractiveTooltip/enable.html) - used to enable the axis tooltip.
* [`borderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/InteractiveTooltip/borderWidth.html) - used to change the stroke width of the axis tooltip.

Просмотреть файл

@ -24,6 +24,11 @@ You can use the following properties to customize the behavior and appearance of
* [`period`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/period.html) -Used to determine the starting point for the trendline.
* [`polynomialOrder`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/polynomialOrder.html) -used to provide the polynomial order for polynomial type trendlines.
* [` animationDuration`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/animationDuration.html) - Used to animate the trendlines. By default, animationDuration has a value of 1500. When animationDuration is set to zero no animation takes place.
* [`dashArray`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/AxisLine/dashArray.html) - pattern of dashes and gaps used to stroke the trendline.
* [`opacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/opacity.html) - opacity of the trendline.
* [`valueField`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/valueField.html) - used to choose the valueField(low or high) to render the trendline. Defaults to low.
* [`isVisibleInLegend`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/isVisibleInLegend.html) - show/hides the legend for trendline.
* [`legendIconType`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Trendline/legendIconType.html) - specifies the type of legend icon for trendline
## Types of trendlines

Просмотреть файл

@ -194,6 +194,40 @@ The axis tooltip on selection zooming can be enabled using [`enable`](https://pu
{% endhighlight %}
## Mouse wheel zooming
The [enableMouseWheelZooming](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ZoomPanBehavior/enableMouseWheelZooming.html) can be performed by rolling the mouse wheel up or down. The place where the cursor is hovering gets zoomed in or out according to the mouse wheel rolling up or down.
{% highlight dart %}
ZoomPanBehavior _zoomPanBehavior;
@override
void initState(){
_zoomPanBehavior = ZoomPanBehavior(
enableMouseWheelZooming : true);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
height: 300,
width: 350,
child: SfCartesianChart(
zoomPanBehavior: _zoomPanBehavior
)
)
)
)
);
}
{% endhighlight %}
## Auto interval on zooming
The [`enableAutoIntervalOnZooming`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/enableAutoIntervalOnZooming.html) property determines the update of axis internal based on the current visible range while zooming the chart. Default value of this property is true. If this property is false, the nice internal will not be calculated for new range after zoom in and actual interval will be sustained.
@ -288,7 +322,7 @@ If zoom mode is set to [`zoomMode.x`](https://pub.dev/documentation/syncfusion_f
![Panning](images/zooming-panning/panning.gif)
Also refer [zooming](./events#onzooming), [zoom start](./events#onzoomstart) and [zoom end](./events#onzoomend) events for customizing the zooming further.
Also refer [zooming](./callbacks#onzooming), [zoom start](./callbacks#onzoomstart) and [zoom end](./callbacks#onzoomend) events for customizing the zooming further.
## See Also

Просмотреть файл

@ -91,6 +91,7 @@ Triggers when data label is rendering. Text and text styles such as color, font
* [`seriesRenderer`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelRenderArgs/seriesRenderer.html) - specifies current series.
* [`color`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelRenderArgs/color.html) - to get and set the color of data label.
* [`viewportPointIndex`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelRenderArgs/viewportPointIndex.html) - to get the viewport index value of the tapped data label.
* [`dataPoints`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelRenderArgs/dataPoints.html) - to get the data points of the series.
{% highlight dart %}
@ -183,7 +184,7 @@ Triggers while selection changes. Here you can customize the selectedColor, unse
* [`selectedBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionArgs/selectedBorderWidth.html) - specifies border width of the selected data points or series.
* [`unselectedBorderColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionArgs/unselectedBorderColor.html) - specifies border color of the unselected data points or series.
* [`unselectedBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionArgs/unselectedBorderWidth.html) - specifies border width of the unselected data points or series.
* [`overallDataPointIndex`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionArgs/overallDataPointIndex.html) - to get the overall point index.
* [`viewportPointIndex`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionArgs/viewportPointIndex.html) - to get the overall point index.
{% highlight dart %}
@ -251,4 +252,84 @@ N> This callback will not be called, when the builder is specified for data labe
);
}
{% endhighlight %}
{% endhighlight %}
## onChartTouchInteractionUp
Triggers when tapped or clicked on the chart area. You can get the position of the taped region using this callback.
The callback contains the following argument:
* [`position`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTouchInteractionArgs/position.html) - used to get the position of the touch interaction.
{% highlight dart %}
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onChartTouchInteractionUp: (ChartTouchInteractionArgs args){
print(args.position.dx.toString());
print(args.position.dy.toString());
}
)
);
}
{% endhighlight %}
## onChartTouchInteractionMove
Triggers when touched or clicked and moved on the chart area. You can get the position of the moving region using this callback.
The callback contains the following argument:
* [`position`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTouchInteractionArgs/position.html) - used to get the position of the touch interaction.
{% highlight dart %}
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onChartTouchInteractionMove: (ChartTouchInteractionArgs args){
print(args.position.dx.toString());
print(args.position.dy.toString());
}
)
);
}
{% endhighlight %}
## onChartTouchInteractionDown
Triggers when touched or clicked on the chart area. You can get the position of the touched region using this callback.
The callback contains the following argument:
* [`position`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartTouchInteractionArgs/position.html) - used to get the position of the touch interaction.
{% highlight dart %}
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onChartTouchInteractionDown: (ChartTouchInteractionArgs args){
print(args.position.dx.toString());
print(args.position.dy.toString());
}
)
);
}
{% endhighlight %}
## onCreateShader
Using this callback, you can fill the data points of circular charts series with gradient and image shader.
The callback contains the following argument:
* [`ChartShaderDetails`](~) - provides options to get the outer rect, inner rect, and render type (either series or legend)
The onCreateShader callback is called once while rendering
the data points and legend. For further reference on this callback, Check the [Gradient and image shader](./circular-series-customization#Gradient-fill-and-shader) section.

Просмотреть файл

@ -64,6 +64,8 @@ You can customize the Area of the chart using the below properties.
* [`backgroundColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/backgroundColor.html) - used to change the Chart area background color.
* [`backgroundImage`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/backgroundImage.html) - used to set the image path.
* [`borderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/borderWidth.html) - used to change chart area the border width.
* [`borderColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/bordeColor.html) - used to change the chart area border color.
{% highlight dart %}

Просмотреть файл

@ -17,6 +17,8 @@ To render a pie chart, create an instance of [`PieSeries`](https://pub.dev/docum
* [`strokeWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/borderWidth.html) - Changes the stroke width of the series.
* [`strokeColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/borderColor.html) - Changes the stroke color of the series.
* [`pointColorMapper`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/pointColorMapper.html) - Maps the color for individual points from the data source.
* [`pointShaderMapper`](~) - Maps the shader (gradient or image shader) for individual points from the data source.
* [`pointRenderMode`](~) - Defines the painting mode for the data points either as segment or gradient.
{% highlight dart %}
@ -273,6 +275,9 @@ To render a doughnut chart, create an instance of [`DoughnutSeries`](https://pub
* [`strokeWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartPoint/strokeWidth.html) - Changes the stroke width of the series.
* [`strokeColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartPoint/strokeColor.html) - Changes the stroke color of the series.
* [`pointColorMapper`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/pointColorMapper.html) - Maps the color for individual points from the data source.
* [`pointShaderMapper`](~) - Maps the shader (gradient or image shader) for individual points from the data source.
* [`pointRenderMode`](~) - Defines the painting mode for the data points either as segment or gradient.
{% highlight dart %}
@ -638,6 +643,7 @@ The radial bar chart is used for showing the comparisons among the categories us
* [`trackBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/RadialBarSeries/trackBorderWidth.html) - Changes the width of the track border.
* [`trackOpacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/RadialBarSeries/trackOpacity.html) - Controls the transparency of the track area.
* [`useSeriesColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/RadialBarSeries/useSeriesColor.html) - Uses the point color for filling the track area.
* [`pointShaderMapper`](~) - Maps the shader (gradient or image shader) for individual points from the data source.
{% highlight dart %}

Просмотреть файл

@ -71,6 +71,404 @@ documentation: ug
![Color Palette](images/circular-customization/color_palette.jpg)
## Color mapping for data points
The [`pointColorMapper`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/pointColorMapper.html) property is used to map the color field from the data source.
{% highlight dart %}
@override
Widget build(BuildContext context) {
static dynamic chartData = <SalesData>[
SalesData('Rent', 1000,Colors.teal),
SalesData('Food', 2500,Colors.lightBlue),
SalesData('Savings', 760,Colors.brown),
SalesData('Tax', 1897,Colors.grey),
SalesData('Others', 2987,Colors.blueGrey)
];
return Scaffold(
body: Center(
child: Container(
child: SfCircularChart(
primaryXAxis: CategoryAxis(),
series: <PieSeries<SalesData, String>>[
PieSeries<SalesData, String>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales,
//map Color for each dataPoint datasource.
pointColorMapper: (SalesData sales,_) => sales.color,
)
]
)
)
)
);
}
{% endhighlight %}
![mapcolor](images/circular-customization/color-mapping.jpg)
## Gradient and image shader
The [`onCreateShader`](~) callback is used to fill the circular chart series data points with gradient and image shader. This callback is called once while rendering
the data points and legend.
N> All the data points of the circular chart are considered together as a single segment and the shader is applied commonly.
### Gradient fill
The data points of pie, doughnut and radial bar charts can be filled with three types of [`gradient`](https://api.flutter.dev/flutter/dart-ui/Gradient-class.html) such as [`linear`](https://api.flutter.dev/flutter/dart-ui/Gradient/Gradient.linear.html), [`sweep`](https://api.flutter.dev/flutter/dart-ui/Gradient/Gradient.sweep.html) and [`radial`](https://api.flutter.dev/flutter/dart-ui/Gradient/Gradient.radial.html). All the data points in the circular chart are together considered as a single segment and the shader is applied commonly.
#### Linear gradient
{% highlight dart %}
List<Color> colors = <Color>[
const Color.fromRGBO(75, 135, 185, 1),
const Color.fromRGBO(192, 108, 132, 1),
const Color.fromRGBO(246, 114, 128, 1),
const Color.fromRGBO(248, 177, 149, 1),
const Color.fromRGBO(116, 180, 155, 1)
];
List<double> stops = <double>[
0.2,
0.4,
0.6,
0.8,
1,
];
@override
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onCreateShader: (ChartShaderDetails chartShaderDetails) {
return Gradient.linear(chartShaderDetails.outerRect.topRight,
chartShaderDetails.outerRect.centerLeft, colors, stops);
},
series: <CircularSeries<_SalesData, dynamic>>[
PieSeries<_SalesData, dynamic>(
dataSource: chartData,
xValueMapper: (_SalesData sales, _) => sales.year,
xValueMapper: (_SalesData sales, _) => sales.year,
)
]
));
}
{% endhighlight %}
![shader linear](images/circular-customization/pie_linear.jpg)
#### Sweep gradient
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onCreateShader: (ChartShaderDetails chartShaderDetails) {
return Gradient.sweep(
chartShaderDetails.outerRect.center,
colors,
stops,
TileMode.clamp,
_degreeToRadian(0),
_degreeToRadian(360),
_resolveTransform(chartShaderDetails.outerRect, TextDirection.ltr)
);
},
series: <CircularSeries<_SalesData, dynamic>>[
RadialBarSeries<_SalesData, dynamic>(
dataSource: chartData,
xValueMapper: (_SalesData sales, _) => sales.year,
xValueMapper: (_SalesData sales, _) => sales.year,
)
]
));
}
// otate the sweep gradient according to the start angle
Float64List _resolveTransform(Rect bounds, TextDirection textDirection) {
final GradientTransform transform = GradientRotation(_degreeToRadian(-90));
return transform.transform(bounds, textDirection: textDirection)!.storage;
}
// Convert degree to radian
double _degreeToRadian(int deg) => deg * (3.141592653589793 / 180);
{% endhighlight %}
![shader sweep](images/circular-customization/radialbar_sweep.jpg)
#### Radial gradient
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Container(
child: SfCircularChart(
onCreateShader: (ChartShaderDetails chartShaderDetails) {
return Gradient.radial(
chartShaderDetails.outerRect.center,
chartShaderDetails.outerRect.right - chartShaderDetails.outerRect.center.dx,
colors,
stops
);
},
series: <CircularSeries<_SalesData, dynamic>>[
DoughnutSeries<_SalesData, dynamic>(
dataSource: chartData,
xValueMapper: (_SalesData sales, _) => sales.year,
xValueMapper: (_SalesData sales, _) => sales.year,
)
]
));
}
{% endhighlight %}
![shader radial](images/circular-customization/doughnut_radial.jpg)
### Image fill
The data points of pie, doughnut and radial bar charts can also be filled with image by returning [`ImageShader`](https://api.flutter.dev/flutter/dart-ui/ImageShader-class.html) with required parameters.
{% highlight dart %}
/// Package import
import 'dart:async';
import 'dart:ui' as ui;
Image image;
Future<void> getImage() async {
const ImageProvider imageProvider = AssetImage('assets/apple.png');
final Completer<ImageInfo> completer = Completer<ImageInfo>();
imageProvider.resolve(const ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(info);
}));
final ImageInfo imageInfo = await completer.future;
image = imageInfo.image;
isLoadedImage = true;
}
@override
Widget build(BuildContext context) {
getImage();
return Container(
child: SfCircularChart(
onCreateShader: (ChartShaderDetails chartShaderDetails) {
return ImageShader(
image,
TileMode.mirror,
TileMode.mirror,
Matrix4.identity().scaled(0.4).storage
);
},
series: <CircularSeries<_SalesData, dynamic>>[
PieSeries<_SalesData, dynamic>(
dataSource: chartData,
xValueMapper: (_SalesData sales, _) => sales.year,
xValueMapper: (_SalesData sales, _) => sales.year,
)
]
));
}
{% endhighlight %}
![Image shader](images/circular-customization/pie_imageshader.jpg)
## Shader mapping for data points
The [`pointShaderMapper`](~) property is used to map the shader field from the chart data source. You can map different [`gradient`](https://api.flutter.dev/flutter/dart-ui/Gradient-class.html) types and [`image shader`](https://api.flutter.dev/flutter/dart-ui/ImageShader-class.html) for individual data points using this mapper callback.
{% highlight dart %}
/// Package import
import 'dart:async';
import 'dart:ui' as ui;
ui.Image image1;
ui.Image image2;
ui.Image image3;
ui.Image image4;
// To get the images from asset folder
void getImage() async {
final Completer<ImageInfo> completer = Completer();
final ImageProvider imageProvider = AssetImage('images/apple.png');
imageProvider.resolve(const ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) async {
completer.complete(info);
final ImageInfo imageInfo = await completer.future;
image1 = imageInfo.image;
}));
final Completer<ImageInfo> completer1 = Completer();
final ImageProvider imageProvider1 = AssetImage('images/orange.png');
imageProvider1.resolve(const ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) async {
completer1.complete(info);
final ImageInfo imageInfo1 = await completer1.future;
image2 = imageInfo1.image;
}));
final Completer<ImageInfo> completer2 = Completer();
final ImageProvider imageProvider2 = AssetImage('images/pears.png');
imageProvider2.resolve(const ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) async {
completer2.complete(info);
final ImageInfo imageInfo2 = await completer2.future;
image3 = imageInfo2.image;
}));
final Completer<ImageInfo> completer3 = Completer();
final ImageProvider imageProvider3 = AssetImage('images/other_fruits.png');
imageProvider3.resolve(const ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info, bool _) async {
completer3.complete(info);
final ImageInfo imageInfo4 = await completer3.future;
image4 = imageInfo4.image;
if (mounted) {
setState(() {});
}
}));
}
Widget renderWidget;
@override
Widget build(BuildContext context) {
getImage();
if (image1 != null && image2 != null && image3 != null && image4 != null) {
renderWidget = SfCircularChart(
title: ChartTitle(text: 'Sales comparison of fruits in a shop'),
series: <PieSeries<_ChartShaderData, String>>[
PieSeries<_ChartShaderData, String>(
dataSource: <_ChartShaderData>[
_ChartShaderData(
'Apple',
25,
'25%',
ui.ImageShader(
image1,
TileMode.repeated,
TileMode.repeated,
Matrix4.identity().scaled(0.5).storage,
),
),
_ChartShaderData(
'Orange',
35,
'35%',
ui.ImageShader(
image2,
TileMode.repeated,
TileMode.repeated,
Matrix4.identity().scaled(0.6).storage,
),
),
_ChartShaderData(
'Pears',
22,
'22%',
ui.ImageShader(
image3,
TileMode.repeated,
TileMode.repeated,
Matrix4.identity().scaled(0.6).storage,
),
),
_ChartShaderData(
'Others',
18,
'18%',
ui.ImageShader(
image4,
TileMode.repeated,
TileMode.repeated,
Matrix4.identity().scaled(0.5).storage,
),
),
],
strokeColor: Colors.black.withOpacity(0.5),
strokeWidth: 1.5,
explodeAll: true,
explodeOffset: '3%',
explode: true,
xValueMapper: (_ChartShaderData data, _) => data.x,
yValueMapper: (_ChartShaderData data, _) => data.y,
dataLabelMapper: (_ChartShaderData data, _) => data.text,
// mapped the shader data from the chart's data source
pointShaderMapper: (_ChartShaderData data, _, Color color, Rect rect) => data.shader,
radius: '83%',
),
],
);
} else {
getImage();
renderWidget = Center(child: CircularProgressIndicator());
}
return Scaffold(
body: renderWidget
);
}
class _ChartShaderData {
_ChartShaderData(this.x, this.y, this.text, this.shader);
final String x;
final num y;
final String text;
final Shader shader;
}
{% endhighlight %}
![Image pointshadermapper](images/circular-customization/pie_pointshadermapper.jpg)
## Point render mode
The [`pointRenderMode`](~) property is used to define the painting mode for the data points. The data points in the pie and doughnut chart can be filled either with solid colors or with sweep gradient by using this property. This property is not applicable for [`RadialBarSeries`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/RadialBarSeries-class.html).
* If `PointRenderMode.segment` is specified, the data points are filled with solid colors from the palette or with the colors mentioned in [`pointColorMapper`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/pointColorMapper.html) property.
* If `PointRenderMode.gradient` is specified, a sweep gradient is formed with the solid colors and fills the data points.
N> This property is applicable only if the [`onCreateShader`](~) or [`pointShaderMapper`](~) is null.
{% highlight dart %}
@override
Widget build(BuildContext context) {
getImage();
return Container(
child: SfCircularChart(
series: <CircularSeries<_SalesData, dynamic>>[
PieSeries<_SalesData, dynamic>(
dataSource: chartData,
// Sweep gradient will be formed with default palette colors.
pointRenderMode: PointRenderMode.gradient,
xValueMapper: (_SalesData sales, _) => sales.year,
xValueMapper: (_SalesData sales, _) => sales.year,
)
]
)
);
}
{% endhighlight %}
![Image pointshadermapper](images/circular-customization/pie_rendermode.jpg)
## Dynamic animation
[`SfCircularChart`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart-class.html) also provide the dynamic animation support for the series. The series can be dynamically added to the charts, it will animated by setting the timer value. when you set the [`animationDuration`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/animationDuration.html) value to 0, the series won't be animated.
@ -184,42 +582,3 @@ The charts data source can be sorted using the [`sortingOrder`](https://pub.d
{% endhighlight %}
![Sorting](images/circular-customization/sortings.jpg)
## Color mapping for data points
The [`pointColorMapper`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CircularSeries/pointColorMapper.html) property is used to map the color field from the data source.
{% highlight dart %}
@override
Widget build(BuildContext context) {
static dynamic chartData = <SalesData>[
SalesData('Rent', 1000,Colors.teal),
SalesData('Food', 2500,Colors.lightBlue),
SalesData('Savings', 760,Colors.brown),
SalesData('Tax', 1897,Colors.grey),
SalesData('Others', 2987,Colors.blueGrey)
];
return Scaffold(
body: Center(
child: Container(
child: SfCircularChart(
primaryXAxis: CategoryAxis(),
series: <PieSeries<SalesData, String>>[
PieSeries<SalesData, String>(
dataSource: chartData,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales,
//map Color for each dataPoint datasource.
pointColorMapper: (SalesData sales,_) => sales.color,
)
]
)
)
)
);
}
{% endhighlight %}
![mapcolor](images/circular-customization/color-mapping.jpg)

Просмотреть файл

@ -26,6 +26,9 @@ Data label can be added to a chart series by enabling the [`isVisible`](https://
* [`labelAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelAlignment.html) - used to align the Circular data label positions. The available options to customize the positions are [`outer`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`auto`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`top`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`bottom`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) and [`middle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html).
* [`borderRadius`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/borderRadius.html) - used to add the rounded corners to the data label shape.
* [`angle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/angle.html) - used to rotate the labels.
* [`offset`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/offset.html) - used to movethedata label vertically or horizontally from its position.
* [`showCumulativeValues`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/showCumulativeValues.html) - to show the cumulative values in stacked type series charts.
* [`labelIntersectAction`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelIntersectAction.html) - action on data labels intersection. The intersecting data labels can be hidden.
{% highlight dart %}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 28 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 30 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Просмотреть файл

@ -59,6 +59,7 @@ You can customize the segments using the below properties.
* [`unselectedBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/unselectedBorderWidth.html) - used to change the stroke width of the unselected segment.
* [`selectedOpacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/selectedOpacity.html) - used to control the transparency of the selected segment.
* [`unselectedOpacity`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/unselectedOpacity.html) - used to control the transparency of the unselected segment.
* [`selectionController`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SelectionBehavior/selectionController.html) - used to customize the minimum range of selected series or points.
{% highlight dart %}

Просмотреть файл

@ -61,6 +61,11 @@ You can use the following properties to customize the tooltip appearance.
* [`header`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/header.html) - specifies the header for tooltip. By default, the series name will be displayed in the header.
* [`format`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/format.html) - formats the tooltip text. By default, the tooltip will be rendered with x and y-values. You can add prefix or suffix to x, y, and series name values in the tooltip by formatting them.
* [`shadowColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shadowColor.html) - specifies the color of the tooltip shadow.
* [`shouldAlwaysShow`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shouldAlwaysShow.html) - used to shows or hides the tooltip.
* [`textAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/textAlignment.html) - alignment of the text in the tooltip.
* [`decimalPlaces`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/decimalPlaces.html) - used to specifies the number decimals to be displayed in tooltip text.
* [`shared`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shared.html) - used to share the tooltip with same index points.
{% highlight dart %}

Просмотреть файл

@ -13,10 +13,7 @@ documentation: ug
| Mode | Description |
|---------------------------|-----------------------------------------------------|
| ColumnWidthMode.auto | Calculates the width of column based on header and cell contents. So, header and cell contents are not truncated.|
| ColumnWidthMode.cells | Calculates the width of column based on cell contents. So, cell contents are not truncated. |
| ColumnWidthMode.header | Calculates the width of column based on header content. So, header content is not truncated. |
| ColumnWidthMode.lastColumnFill | Applies `ColumnWidthMode.auto` width to all the columns except last column which is visible and the remaining width from total width of SfDataGrid is set to last column. |
| ColumnWidthMode.lastColumnFill | Applies default Column width to all the columns except last column which is visible and the remaining width from total width of SfDataGrid is set to last column. |
| ColumnWidthMode.fill | Divides the total width equally for columns. |
| ColumnWidthMode.none | No sizing. Default column width or defined width set to column. |
@ -34,17 +31,67 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'city',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
@ -66,11 +113,51 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.lastColumnFill,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation')
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -91,13 +178,52 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.auto,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name')
..columnWidthMode = ColumnWidthMode.lastColumnFill,
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
columnWidthMode: ColumnWidthMode.lastColumnFill,
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -108,112 +234,6 @@ Widget build(BuildContext context) {
![Name column is filled with remaining available space in flutter datagrid](images/autofit-columns/flutter-datagrid-fill-anycolumn.png)
## Autofit based on string length
By default, the auto size of the column is calculated based on the string size. To improve the performance of the column auto sizing, the auto size calculation logic of column can be calculated based on the length of the cell value by using [SfDataGrid.columnWidthCalculationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthCalculationMode.html) property.
The default is `ColumnWidthCalculationMode.textSize` which calculates size for all the cells formatted text. The columns can also be auto sized based on string length of the cell using the `ColumnWidthCalculationMode.textLength` which calculates the size for the cell which has longest string.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationMode: ColumnWidthCalculationMode.textLength,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
## Calculate the column width for all the rows
By default, the column auto size is calculated for the visible rows. The column auto size can be calculated for the all the available rows by using the [SfDataGrid.columnWidthCalculationRange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthCalculationRange.html) property.
The default is `ColumnWidthCalculationRange.visibleRows` which considers visible rows for auto sizing. The columns can also be auto sized by considering all the rows using the `ColumnWidthCalculationRange.allRows` mode.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.auto,
columnWidthCalculationRange: ColumnWidthCalculationRange.allRows,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
## Customizing built-in column sizing logic
The column auto sizing operations of the `SfDataGrid` is processed in the [ColumnSizer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer-class.html) class. The column sizing operations can be customized by overriding `ColumnSizer` and set it to [SfDataGrid.columnSizer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnSizer.html) property.
{% tabs %}
{% highlight Dart %}
class CustomGridColumnSizer extends ColumnSizer {
// Calculate width for column when ColumnWidthMode is auto.
@override
double calculateAllCellsWidth(GridColumn column, [bool isAuto = false]) {
return super.calculateAllCellsWidth(column, isAuto);
}
// Calculate width for column when ColumnWidthMode is header.
@override
double calculateColumnHeaderWidth(GridColumn column, [bool setWidth = true]) {
return super.calculateColumnHeaderWidth(column, setWidth);
}
// Calculate width for column when ColumnWidthMode is cells.
@override
double calculateAllCellsExceptHeaderWidth(GridColumn column,
[bool setWidth = true]) {
return super.calculateAllCellsExceptHeaderWidth(column, setWidth);
}
}
final CustomGridColumnSizer _customGridColumnSizer = CustomGridColumnSizer();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columnSizer: _customGridColumnSizer,
columnWidthMode: ColumnWidthMode.auto,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
## Recalculating column widths when datasource is changed
By default, column widths are calculated based on the `columnWidthMode` property on initial loading of datagrid. When the datasource is changed for same datagrid at run time, datagrid does not recalculate the column widths. To recalculate the column widths at run time when datasource is changed or data is updated, you can override the [shouldRecalculateColumnWidths](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/shouldRecalculateColumnWidths.html) method and return `true`.
@ -223,35 +243,47 @@ Returning true may impact performance as the column widths are recalculated agai
{% tabs %}
{% highlight Dart %}
class EmployeeDataSource extends DataGridSource<Employee> {
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
]))
.toList();
}
List<DataGridRow> dataGridRows;
@override
List<Employee> get dataSource => _employees;
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
bool shouldRecalculateColumnWidths() {
return true;
}
@override
getValue(Employee employee, String columnName){
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
}
}
{% endhighlight %}
{% endtabs %}

Просмотреть файл

@ -9,16 +9,13 @@ documentation: ug
# Column Types in Flutter DataGrid
[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for various built-in column types. Each column has its own properties and renderer to handle different types of data. Based on the requirements, any column can be used.
[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for load any type of widget in each column.
The following table describes the types of columns and its usage:
| Column Type | Renderer | Description |
|-----------------------|---------------------------------|----------------------------------------|
| GridTextColumn | GridCellTextFieldRenderer | Use to display the String data |
| GridNumericColumn | GridCellNumericTextFieldRenderer| Use to display the Numeric data |
| GridDateTimeColumn | GridCellDateTimeRenderer | Use to display the DateTime value |
| GridWidgetColumn | GridCellWidgetRenderer | Use to display the Widget in each row |
## GridColumn
@ -26,7 +23,7 @@ GridColumn is a class that provides base functionalities for all the column type
### Mapping column to a property
Column can be bound to a property in data object using [GridColumn.mappingName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/mappingName.html) property. [headerText](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerText.html) is used to display the required text in a column header. If the `headerText` is not mentioned, `mappingName` is considered.
Column can be bound to a property in data object using [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/mappingName.html) property. [label](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerText.html) is used to display the required widget in a column header.
{% tabs %}
{% highlight Dart %}
@ -36,37 +33,51 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
],
),
);
}
{% endhighlight %}
{% endtabs %}
### Set padding for column
[GridColumn.padding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/padding.html) property can be used to set the padding for the cells in the column. It is also applicable to the column header cell except [GridWidgetColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridWidgetColumn-class.html). The default value of padding is 16.0.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID',padding:
EdgeInsets.all(20.0)),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -90,11 +101,52 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary',visible: false)
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
visible: false,
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -117,12 +169,53 @@ Widget build(BuildContext context) {
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name',width: 100.0),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
source: employeeDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
width: 100.0,
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -131,218 +224,9 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
### Set alignment for column
[GridColumn.textAlignment](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/textAlignment.html) and [GridColumn.headerTextAlignment](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerTextAlignment.html) can be used to customize the alignment for the cells and header cells in the column.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID', textAlignment: Alignment.center, headerTextAlignment: Alignment.center),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
### Set text wrapping for column
When the text for the record and header cells exceeds the content area, wrap the record and header cells by setting the [GridColumn.softWrap](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/softWrap.html) and [GridColumn.headerTextSoftWrap](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerTextSoftWrap.html) as `true` respectively. The default values of `softWrap` and `headerTextSoftWrap` are false.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation', softWrap: true, headerTextSoftWrap: true),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
### Change text overflow behavior
[GridColumn.overflow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/overflow.html) and [GridColumn.headerTextOverflow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerTextOverflow.html) properties can be used to change the behavior of the record and header cells text overflow respectively. The default values of `overflow` and `headerTextOverfow` are ellipsis.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID', overflow: TextOverflow.fade),
GridTextColumn(mappingName: 'name', headerText: 'Name', overflow: TextOverflow.clip, headerTextOverflow: TextOverflow.clip),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
## Load widget in header
The SfDataGrid allows you to load any widget in header cell using [headerCellBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerCellBuilder.html) callback. You can return a required widget in a callback.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
headerCellBuilder: (BuildContext context, GridColumn column) {
if (column.mappingName == 'city')
return Row(
children: <Widget>[
Icon(Icons.location_on),
SizedBox(width: 5),
Flexible(
child: Text(
column.headerText,
style: TextStyle(fontWeight: FontWeight.bold),
)
)
],
);
else
return null;
},
columns: [
GridNumericColumn(mappingName: 'id',headerText:'ID'),
GridTextColumn(mappingName: 'name',headerText: 'Name'),
GridTextColumn(mappingName: 'city',headerText: 'City'),
GridTextColumn(mappingName: 'price',headerText: 'Price')
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows image in a header](images/column-types/flutter-datagrid-header-widget.png)
## Column styling
GridColumn provides support to customize the style of column using [GridColumn.cellStyle](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/cellStyle.html) and [GridColumn.headerStyle](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerStyle.html) properties. The type of `cellStyle` and `headerStyle` property is `DataGridCellStyle` and `DataGridHeaderCellStyle`. For more information, refer [Styling](styles.md\#styling-in-flutter-dataGrid) section.
All the style classes such as [DataGridCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridCellStyle-class.html), [DataGridHeaderCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridHeaderCellStyle-class.html) related to `SfDataGrid` are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. To access those classes, import the below file in your application,
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_core/theme.dart';
{% endhighlight %}
{% endtabs %}
### Change column text style
`GridColumn.cellStyle.textStyle` and `GridColumn.headerStyle.textStyle` properties can be used to change the text style for the column's cells.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(
mappingName: 'id',
headerText: 'ID',
headerStyle: DataGridHeaderCellStyle(
textStyle: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold)),
cellStyle:
DataGridCellStyle(textStyle: TextStyle(color: Colors.red))),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows columns with text style](images/column-types/flutter-datagrid-change-textstyle.png)
### Change column background color
`GridColumn.cellStyle.backgroundColor` and `GridColumn.headerStyle.backgroundColor` properties can be used to change the background color for the column's cells.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation',
headerText: 'Designation',
headerStyle: DataGridHeaderCellStyle(
textStyle: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
backgroundColor: Colors.deepPurple),
cellStyle:
DataGridCellStyle(backgroundColor: Colors.deepPurple[200])),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows columns with backgroundcolor](images/column-types/flutter-datagrid-change-backgroundcolor.png)
## GridTextColumn
[GridTextColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridTextColumn-class.html) inherits all the properties of GridColumn. It is used to display the textual content to the column's cells.
[GridTextColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridTextColumn-class.html) inherits all the properties of GridColumn.
{% tabs %}
{% highlight Dart %}
@ -352,155 +236,55 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
## GridNumericColumn
[GridNumericColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridNumericColumn-class.html) inherits all the properties of GridColumn. It is used to display the columns data as numeric values.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
### Number formatting
The numeric value can be formatted by using [GridNumericColumn.numberFormat](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridNumericColumn/numberFormat.html) property, which contains the set of predefined number patterns. For more information about predefined patterns, refer [NumberFormat](https://api.flutter.dev/flutter/intl/NumberFormat-class.html) class.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
..numberFormat =
NumberFormat.currency(locale: 'en_US', symbol: '\$')
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows columns with number formatting](images/column-types/flutter-datagrid-numberformatting.png)
## GridDateTimeColumn
[GridDateTimeColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridDateTimeColumn-class.html) inherits all the properties of GridColumn. It is used to display the columns data as datetime values.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
GridDateTimeColumn(
mappingName: 'dateOfJoining', headerText: 'Date of Joining')
],
),
);
}
{% endhighlight %}
{% endtabs %}
### Date formatting
The datetime value can be formatted by using [GridDateTimeColumn.dateFormat](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridDateTimeColumn/dateFormat.html) property, which contains the set of predefined datetime patterns. The default format of a date is `dd-MM-yyyy`. For more information about predefined patterns, refer [DateFormat](https://api.flutter.dev/flutter/intl/DateFormat-class.html) class.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridDateTimeColumn(
mappingName: 'dateOfJoining', headerText: 'Date of Joining', dateFormat: DateFormat('dd/MM/yyyy')),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows columns with date formatting](images/column-types/flutter-datagrid-dateformatting.png)
## GridWidgetColumn
[GridWidgetColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridWidgetColumn-class.html) is used to load any custom widget or multiple widgets to the column's cells. Any widget can be loaded using the [cellBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/cellBuilder.html) callback. You can simply return a required widget in a callback.
In the below example, image is returned in `cellBuilder` callback. Image is already added in the Employee class.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
cellBuilder: (BuildContext context, GridColumn column, int rowindex) {
return employees[rowIndex].image;
},
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridWidgetColumn(mappingName: 'image', headerText: 'Image'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows image in a column through widget column](images/column-types/flutter-datagrid-widget-column.png)
{% endtabs %}

Просмотреть файл

@ -9,62 +9,138 @@ documentation: ug
# Conditional Styling in Flutter DataGrid
The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows to customize the style of the individual cells and rows based on the requirements. It can be customized in the following ways:
* Using [onQueryCellStyle](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onQueryCellStyle.html) Callback
* Using [onQueryRowStyle](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onQueryRowStyle.html) Callback
All the style classes such as [DataGridCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridCellStyle-class.html), [DataGridHeaderCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridHeaderCellStyle-class.html) related to `SfDataGrid` are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. To access those classes, import the below file in your application,
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_core/theme.dart';
{% endhighlight %}
{% endtabs %}
The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows to customize the style of the individual cells and rows based on the requirements. You can customize your widget in the `DataGridSource.buildRow` method with the help of `DataGridRowAdapter`.
## Cells
### Styling based on content
The appearance of the cells in `SfDataGrid` can be customized conditionally based on the content by handling the `SfDataGrid.onQueryCellStyle` callback.
Callback requires [QueryCellStyleArgs](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/QueryCellStyleArgs-class.html) as parameter which provides all the required options to know about the cell.
The appearance of the cells in `SfDataGrid` can be customized conditionally based on the content and set your widget to the `DataGridRowAdapter.cells`.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
onQueryCellStyle: (QueryCellStyleArgs args) {
if (args.column.mappingName == 'designation') {
if (args.cellValue == 'Developer') {
return DataGridCellStyle(
textStyle: TextStyle(fontStyle: FontStyle.italic),
backgroundColor: Colors.tealAccent);
} else if (args.cellValue == 'Manager') {
return DataGridCellStyle(
textStyle: TextStyle(fontStyle: FontStyle.italic),
backgroundColor: Colors.blue[200]);
}
}
return null;
}),
source: _employeeDataSource,
columnWidthMode: ColumnWidthMode.lastColumnFill,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows;
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
Color getColor() {
if (dataGridCell.columnName == 'designation') {
if (dataGridCell.value == 'Developer') {
return Colors.tealAccent;
} else if (dataGridCell.value == 'Manager') {
return Colors.blue[200]!;
}
}
return Colors.transparent;
}
TextStyle? getTextStyle() {
if (dataGridCell.columnName == 'designation') {
if (dataGridCell.value == 'Developer') {
return TextStyle(fontStyle: FontStyle.italic);
} else if (dataGridCell.value == 'Manager') {
return TextStyle(fontStyle: FontStyle.italic);
}
}
return null;
}
return Container(
color: getColor(),
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: getTextStyle(),
));
}).toList());
}
}
{% endhighlight %}
{% endtabs %}
@ -72,38 +148,61 @@ Widget build(BuildContext context) {
### Styling alternate cells
The appearance of the alternating cells in a column can be customized conditionally by using the `SfDataGrid.onQueryCellStyle` callback.
The appearance of the alternating cells in a column can be customized conditionally by using the `DataGridSource.buildRow` method.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
onQueryCellStyle: (QueryCellStyleArgs args) {
if (args.column.mappingName == 'id') {
if (args.rowIndex % 2 != 0) {
return DataGridCellStyle(
textStyle: TextStyle(fontStyle: FontStyle.italic),
backgroundColor: Colors.blueAccent);
}
}
return null;
}),
);
List<DataGridRow> dataGridRows;
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
if (dataGridCell.columnName == 'id') {
final int index = dataGridRows.indexOf(row);
return Container(
color: (index % 2 != 0) ? Colors.blueAccent : Colors.transparent,
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: (index % 2 != 0)
? TextStyle(fontStyle: FontStyle.italic)
: null,
));
}
return Container(
alignment: (dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
}
{% endhighlight %}
{% endtabs %}
@ -113,42 +212,74 @@ Widget build(BuildContext context) {
### Styling based on content
The appearance of the rows in `SfDataGrid` can be customized conditionally based on the content by handling the `SfDataGrid.onQueryRowStyle` callback.
Callback requires [QueryRowStyleArgs](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/QueryRowStyleArgs-class.html) as parameter which provides all the required options to know about the cell.
The appearance of the rows in `SfDataGrid` can be customized conditionally based on the content in `DataGridRowAdapter.color`.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
],
onQueryRowStyle: (QueryRowStyleArgs args) {
Employee employee = _employeeCollection[args.rowIndex];
if (employee.salary >= 10000 && employee.salary < 15000) {
return DataGridCellStyle(
textStyle: TextStyle(color: Colors.white),
backgroundColor: Colors.blue[300]);
} else if (employee.salary <= 15000) {
return DataGridCellStyle(
textStyle: TextStyle(color: Colors.white),
backgroundColor: Colors.orange[300]);
}
return null;
}),
);
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows;
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
Color getRowBackgroundColor() {
final int salary = row.getCells()[3].value;
if (salary >= 10000 && salary < 15000) {
return Colors.blue[300]!;
} else if (salary <= 15000) {
return Colors.orange[300]!;
}
return Colors.transparent;
}
TextStyle? getTextStyle() {
final int salary = row.getCells()[3].value;
if (salary >= 10000 && salary < 15000) {
return TextStyle(color: Colors.white);
} else if (salary <= 15000) {
return TextStyle(color: Colors.white);
}
return null;
}
return DataGridRowAdapter(
color: getRowBackgroundColor(),
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: getTextStyle(),
));
}).toList());
}
}
{% endhighlight %}
{% endtabs %}
@ -156,32 +287,58 @@ Widget build(BuildContext context) {
### Styling alternate rows
The appearance of the alternating rows in `SfDataGrid` can be customized by using the `SfDataGrid.onQueryRowStyle` callback.
The appearance of the alternating rows in `SfDataGrid` can be customized by using the `DataGridRowAdapter.color`.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation')
],
onQueryRowStyle: (QueryRowStyleArgs args) {
if (args.rowIndex % 2 != 0) {
return DataGridCellStyle(backgroundColor: Colors.lightGreen[300]);
}
return null;
}),
);
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows;
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
Color getRowBackgroundColor() {
final int index = dataGridRows.indexOf(row);
if (index % 2 != 0) {
return Colors.lightGreen[300]!;
}
return Colors.transparent;
}
return DataGridRowAdapter(
color: getRowBackgroundColor(),
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
}
{% endhighlight %}

Просмотреть файл

@ -13,11 +13,9 @@ documentation: ug
The following APIs in the `DataGridSource` are mandatory to process the data,
* [dataSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/dataSource.html) - The number of rows in a datagrid and row selection depends
on the [dataSource]. So, set the collection required for datagrid in
`dataSource`.
* [getValue](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/getValue.html) - The data needed for the cells is obtained from
`getValue`.
* [rows] - The number of rows in a datagrid and row selection depends on the [rows]. So, set the `DataGridRow` collection required for datagrid in
`rows`.
* [buildRow]- The widget needed for the cells is obtained from `DataGridRowAdapter`.
`DataGridSource` objects are expected to be long-lived, not recreated with each build.
@ -26,31 +24,40 @@ The following example shows how to create the `DataGridSource`,
{% tabs %}
{% highlight dart %}
final List<Employee> _employees = <Employee>[];
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows;
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => _employees
List<DataGridRow> get rows => dataGridRows;
@override
getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
}
@ -69,11 +76,52 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnWidthMode: ColumnWidthMode.lastColumnFill,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
@ -102,25 +150,63 @@ final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Syncfusion Flutter DataGrid'),
),
body: Column(
children: [
FlatButton(
child: const Text('Add row'),
onPressed: () {
_employees.add(Employee(10011, 'Steve', 'Designer', 15000));
_employees
.add(Employee(10011, 'Steve', 'Designer', 15000));
_employeeDataSource.buildDataGridRows();
_employeeDataSource.updateDataGridSource();
}),
SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
],
@ -128,30 +214,44 @@ Widget build(BuildContext context) {
);
}
class EmployeeDataSource extends DataGridSource<Employee> {
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource(List<Employee> employees) {
buildDataGridRows();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows;
@override
List<Employee> get dataSource => _employees
List<DataGridRow> get rows => dataGridRows;
@override
getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
void updateDataGridSource() {
@ -186,17 +286,66 @@ Widget build(BuildContext context) {
child: const Text('Update cell value'),
onPressed: () {
_employees[0].salary = 25000;
_employeeDataSource.dataGridRows[0] = DataGridRow(cells: [
DataGridCell(value: employees[0].id, columnName: 'id'),
DataGridCell(value: employees[0].name, columnName: 'name'),
DataGridCell(
value: employees[0].designation,
columnName: 'designation'),
DataGridCell(
value: employees[0].salary, columnName: 'salary'),
]);
_employeeDataSource.updateDataGridSource(
rowColumnIndex: RowColumnIndex(0, 3));
}),
SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
],
@ -204,30 +353,44 @@ Widget build(BuildContext context) {
);
}
class EmployeeDataSource extends DataGridSource<Employee> {
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
buildDataGridRows();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<DataGridRow> dataGridRows = [];
@override
List<Employee> get dataSource => _employees
List<DataGridRow> get rows => dataGridRows;
@override
getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
void updateDataGridSource({RowColumnIndex rowColumnIndex}) {

Просмотреть файл

@ -61,24 +61,105 @@ The following code example shows how to freeze a column at left using `frozenCol
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridNumericColumn(mappingName: 'productId', headerText: 'Product ID'),
GridTextColumn(mappingName: 'name', headerText: 'Customer Name'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'quantity', headerText: 'Quantity'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'unitPrice', headerText: 'Unit Price'),
],
frozenColumnsCount: 1,
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
frozenColumnsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
);
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
@ -91,22 +172,102 @@ The following code example shows how to freeze a column at right using `footerFr
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridNumericColumn(mappingName: 'productId', headerText: 'Product ID'),
GridTextColumn(mappingName: 'name', headerText: 'Customer Name'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'quantity', headerText: 'Quantity'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'unitPrice', headerText: 'Unit Price'),
],
footerFrozenColumnsCount: 1,
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
footerFrozenColumnsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
);
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
@ -129,23 +290,104 @@ The following code example shows how to freeze a row at top using `frozenRowsCou
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridNumericColumn(mappingName: 'productId', headerText: 'Product ID'),
GridTextColumn(mappingName: 'name', headerText: 'Customer Name'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'quantity', headerText: 'Quantity'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'unitPrice', headerText: 'Unit Price'),
],
frozenRowsCount: 1,
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
frozenRowsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
);
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
@ -158,22 +400,102 @@ The following code example shows how to freeze a row at bottom using `footerFroz
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridNumericColumn(mappingName: 'productId', headerText: 'Product ID'),
GridTextColumn(mappingName: 'name', headerText: 'Customer Name'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'quantity', headerText: 'Quantity'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'unitPrice', headerText: 'Unit Price'),
],
footerFrozenRowsCount: 1,
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
footerFrozenRowsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
);
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
);
}
{% endhighlight %}
@ -189,7 +511,7 @@ N> Header row is frozen by default and works regardless of the `frozenRowsCount`
## Appearance
`SfDataGrid` allows to customize the appearance of the freeze pane through [SfDataGridTheme.SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) property.
`SfDataGrid` allows to customize the appearance of the freeze pane through [SfDataGridTheme.SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) property. The frozen line will be shown only the `SfDataGridThemeData.frozenPaneElevation` property to 0.
The freeze pane line and freeze pane width can be changed by [frozenPaneLineColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineColor.html) and [frozenPaneLineWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineWidth.html).
@ -198,31 +520,344 @@ The freeze pane line and freeze pane width can be changed by [frozenPaneLineColo
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
frozenPaneLineColor: Colors.red, frozenPaneLineWidth: 1.5),
child: SfDataGrid(
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridNumericColumn(mappingName: 'productId', headerText: 'Product ID'),
GridTextColumn(mappingName: 'name', headerText: 'Customer Name'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'quantity', headerText: 'Quantity'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'unitPrice', headerText: 'Unit Price'),
],
frozenRowsCount: 1,
footerFrozenRowsCount: 1,
frozenColumnsCount: 1,
footerFrozenColumnsCount: 1,
)),
);
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
frozenPaneElevation: 0.0,
frozenPaneLineColor: Colors.red,
frozenPaneLineWidth: 1.5),
child: SfDataGrid(
source: _orderDataGridSource,
frozenRowsCount: 1,
footerFrozenRowsCount: 1,
frozenColumnsCount: 1,
footerFrozenColumnsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
)),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows freeze pane customization](images/frozen-pane/flutter-datagrid-frozen-pane-customization.png)
![flutter datagrid shows freeze pane customization](images/frozen-pane/flutter-datagrid-frozen-pane-customization.png)
`SfDataGrid` allows to customize the appearance of the freeze pane elevation by using the `SfDataGridThemeData.frozenPaneElevation`. The default value of frozenPaneElevation is 5.0.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(frozenPaneElevation: 7.0),
child: SfDataGrid(
source: _orderDataGridSource,
frozenRowsCount: 1,
frozenColumnsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
)),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows customization of freeze pane elevation](images/frozen-pane/flutter-datagrid-customized-frozen-elevation.png)
## Hide freeze pane elevation
By default, elevation effect is applied to frozen panes. If you want to hide the freeze pane elevation and show only the frozen pane line, you can simply set `SfDataGridThemeData.frozenPaneElevation` property to 0. You can customize the appearance of frozen line by using `SfDataGridThemeData.frozenPaneLineColor` and `SfDataGridThemeData.frozenPaneLineWidth` properties.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
frozenPaneElevation: 0.0,
frozenPaneLineColor: Colors.red,
frozenPaneLineWidth: 1.5),
child: SfDataGrid(
source: _orderDataGridSource,
frozenRowsCount: 1,
frozenColumnsCount: 1,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Product ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'quantity',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Quantity',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'unitPrice',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Unit Price',
overflow: TextOverflow.ellipsis,
),
),
),
],
)),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows how to hide the frozen pane elevation](images/frozen-pane/flutter-datagrid-hide-frozen-elevation.png)

Просмотреть файл

@ -64,10 +64,42 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText:'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
);
@ -93,30 +125,34 @@ class Employee {
{% endhighlight %}
{% endtabs %}
Create the collection of Employee data with the required number of data objects. Here, the `populateData` method which is used to populate the data objects is initialized in `initState()`.
Create the collection of Employee data with the required number of data objects. Here, the `getEmployeeData` method which is used to populate the data objects is initialized in `initState()`.
{% tabs %}
{% highlight Dart %}
final List<Employee> _employees = <Employee>[];
List<Employee> _employees = <Employee>[];
EmployeeDataSource _employeeDataSource;
@override
void initState() {
super.initState();
populateData();
_employees = getEmployeeData();
employeeDataSource = EmployeeDataSource(employeeData: _employees);
}
void populateData() {
_employees.add(Employee(10001, 'James', 'Project Lead', 20000));
_employees.add(Employee(10002, 'Kathryn', 'Manager', 30000));
_employees.add(Employee(10003, 'Lara', 'Developer', 15000));
_employees.add(Employee(10004, 'Michael', 'Designer', 15000));
_employees.add(Employee(10005, 'Martin', 'Developer', 15000));
_employees.add(Employee(10006, 'Newberry', 'Developer', 15000));
_employees.add(Employee(10007, 'Balnc', 'Developer', 15000));
_employees.add(Employee(10008, 'Perry', 'Developer', 15000));
_employees.add(Employee(10009, 'Gable', 'Developer', 15000));
_employees.add(Employee(10010, 'Grimes', 'Developer', 15000));
List<Employee> getEmployeeData() {
return [
Employee(10001, 'James', 'Project Lead', 20000),
Employee(10002, 'Kathryn', 'Manager', 30000),
Employee(10003, 'Lara', 'Developer', 15000),
Employee(10004, 'Michael', 'Designer', 15000),
Employee(10005, 'Martin', 'Developer', 15000),
Employee(10006, 'Newberry', 'Developer', 15000),
Employee(10007, 'Balnc', 'Developer', 15000),
Employee(10008, 'Perry', 'Developer', 15000),
Employee(10009, 'Gable', 'Developer', 15000),
Employee(10010, 'Grimes', 'Developer', 15000)
];
}
{% endhighlight %}
@ -126,41 +162,46 @@ void populateData() {
[DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) is used to obtain the row data for the `SfDataGrid`. So, create the DataSource from the DataGridSource and override the following APIs in it,
* **`dataSource`** - To fetch the number of rows available for data population. Also, it is used to fetch the corresponding data object to process the selection.
* **`getValue`** - To fetch the value for each cell.
* **`rows`** - Fetches the rows available for data population. Also, it is used to fetch the corresponding data object to process the selection. This contains the collection of `DataGridRow` where each row contains the collection of `DataGridCell`. Each cell should have the cell value in `value` property. `value` is used to perform the sorting for columns.
* **`buildRow`** - Fetches the widget for each cell with `DataGridRowAdapter`.
`DataGridSource` objects are expected to be long-lived, not recreated with each build.
{% tabs %}
{% highlight Dart %}
final List<Employee> _employees = <Employee>[];
class EmployeeDataSource extends DataGridSource {
List<DataGridRow> dataGridRows;
EmployeeDataSource({List<Employee> employeeData}) {
dataGridRows = employeeData
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => _employees;
List<DataGridRow> get rows => _employeeData;
@override
getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
}
@ -176,7 +217,7 @@ Create an instance of `DataGridSource` and set this object to `source` property
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
source: _employeeDataSource,
));
}
@ -185,13 +226,12 @@ Widget build(BuildContext context) {
## Defining columns
`SfDataGrid` supports to show different data types (int, double, String and DateTime) in different types of columns. You can add the column collection to the `columns` property.
You can also load any widget in a column using the [GridWidgetColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridWidgetColumn-class.html) and [cellBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/cellBuilder.html) property in `SfDataGrid`.
`SfDataGrid` supports to add any widget in a column using the [GridTextColumn] property. You can add the column collection to the `columns` property.
{% tabs %}
{% highlight Dart %}
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
final EmployeeDataSource _employeeDataSource = EmployeeDataSource(employeeData: _employees);
@override
Widget build(BuildContext context) {
@ -199,10 +239,42 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
);
@ -220,7 +292,7 @@ Widget build(BuildContext context) {
{% tabs %}
{% highlight Dart %}
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
final EmployeeDataSource _employeeDataSource = EmployeeDataSource(employeeData: _employees);
@override
Widget build(BuildContext context) {
@ -228,10 +300,42 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
selectionMode: SelectionMode.multiple,
),
@ -250,7 +354,7 @@ The information about the rows that are selected can be retrieved using [selecte
{% tabs %}
{% highlight Dart %}
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
final EmployeeDataSource _employeeDataSource = EmployeeDataSource(employeeData: _employees);
final DataGridController _controller = DataGridController();
@ -273,11 +377,42 @@ Widget build(BuildContext context) {
child: SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
selectionMode: SelectionMode.multiple,
@ -292,4 +427,4 @@ Widget build(BuildContext context) {
{% endtabs %}
>**NOTE**
`SfDataGrid` supports selection via keyboard interaction for the Web platform when `selectionMode` is not `none`.
`SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`.

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 67 KiB

После

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 58 KiB

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 160 KiB

После

Ширина:  |  Высота:  |  Размер: 453 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 63 KiB

После

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 207 KiB

После

Ширина:  |  Высота:  |  Размер: 481 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 38 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 48 KiB

После

Ширина:  |  Высота:  |  Размер: 7.1 KiB

Просмотреть файл

@ -61,87 +61,143 @@ Widget build(BuildContext context) {
);
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
);
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
int startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
buildDataGridRows();
}
return employeeData;
}
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => employees;
List<DataGridRow> dataGridRows = [];
@override
Object getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
Future<void> handleLoadMoreRows() async {
await Future.delayed(Duration(seconds: 5));
_addMoreRows(employees, 15);
buildDataGridRows();
notifyListeners();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
final startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
}
return employeeData;
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
}
{% endhighlight %}
@ -235,87 +291,143 @@ Widget build(BuildContext context) {
});
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
);
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
int startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
}
return employeeData;
}
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => employees;
@override
Object getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'salary':
return employee.salary;
break;
case 'designation':
return employee.designation;
break;
default:
return ' ';
break;
}
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource() {
buildDataGridRows();
}
List<DataGridRow> dataGridRows = [];
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
Future<void> handleLoadMoreRows() async {
await Future.delayed(Duration(seconds: 5));
_addMoreRows(employees, 15);
buildDataGridRows();
notifyListeners();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
final startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
}
return employeeData;
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
}
{% endhighlight %}

Просмотреть файл

@ -30,6 +30,7 @@ Next, import the `flutter_localizations` library and specify [localizationsDeleg
import 'package:flutter_localizations/flutter_localizations.dart';
final int rowsPerPage = 15;
@override
Widget build(BuildContext context) {
return MaterialApp(
@ -52,25 +53,64 @@ Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: constraints.maxHeight - 60,
width: constraints.maxWidth,
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation',
headerText: 'Designation'),
GridNumericColumn(
mappingName: 'salary', headerText: 'Salary')
])),
height: constraints.maxHeight - 60,
width: constraints.maxWidth,
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
),
Container(
height: 60,
width: constraints.maxWidth,
child: SfDataPager(
delegate: _employeeDataSource,
rowsPerPage: 20,
pageCount: employees.length / rowsPerPage,
visibleItemsCount: 5,
direction: Axis.horizontal,
),
@ -112,6 +152,8 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation
{% tabs %}
{% highlight Dart %}
final int rowsPerPage = 15;
@override
Widget build(BuildContext context) {
return MaterialApp(
@ -135,25 +177,64 @@ Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: constraints.maxHeight - 60,
width: constraints.maxWidth,
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation',
headerText: 'Designation'),
GridNumericColumn(
mappingName: 'salary', headerText: 'Salary')
])),
height: constraints.maxHeight - 60,
width: constraints.maxWidth,
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
),
Container(
height: 60,
width: constraints.maxWidth,
child: SfDataPager(
delegate: _employeeDataSource,
rowsPerPage: 20,
pageCount: employees.length / rowsPerPage,
visibleItemsCount: 5,
direction: Axis.horizontal,
),

Просмотреть файл

@ -16,13 +16,18 @@ The Syncfusion Flutter DataGrid is used to display and manipulate data in a tabu
## Key Features
* **Column types** : Provides the option to show different data types (int, double, string, and date-time) in different types of columns. Also, it can load any widget in a column.
* **Column sizing** : Sets the width of columns with various sizing options. Columns can also be fitted based on their content.
* **Auto row height** : Provides the option to set the height for rows based on the content of their cells.
* **Sorting** : Sort one or more columns in the ascending or descending order.
* **Selection** : Selects one or more rows. Keyboard navigation is supported for web platforms.
* **Styling** : Customizes the appearance of cells and headers. Conditional styling is also supported.
* **Column types** - Support to load any widget in a each column.
* **Column sizing** - Set the width of columns with various sizing options.
* **Row height** - Set the height for header and data rows. Also, set the different height for specific rows.
* **Sorting** - Sort one or more columns in the ascending or descending order.
* **Selection** - Select one or more rows. Keyboard navigation is supported for web platforms.
* **Styling** - Customize the appearance of cells and headers. Conditional styling is also supported.
* **Stacked headers** - Show unbound header rows. Unbound header rows span stacked header columns across multiple rows and columns.
* **Load more** - Display an interactive view when the grid reaches its maximum offset while scrolling down. Tapping the interactive view triggers a callback to add more data from the data source of the grid at run time.
* **Paging** - Load data in segments. It is useful when loading huge amounts of data.
* **Theme** : Use a dark or light theme.
* **Accessibility** : The DataGrid can easily be accessed by screen readers.
* **Right to Left (RTL)** : Right-to-left direction support for users working in RTL languages like Hebrew and Arabic.
* **Freeze Panes** - Freeze the rows and columns when scrolling the grid.
* **Swiping** - Swipe a row right to left or left to right for custom actions such as deleting, editing, and so on. When the user swipes a row, the row will be moved and the swipe view will show the custom actions.
* **Pull to refresh** - Allows users to refresh data when the DataGrid is pulled down.
* **Theme** - Use a dark or light theme.
* **Accessibility** - The DataGrid can easily be accessed by screen readers.
* **Right to Left (RTL)** - Right-to-left direction support for users working in RTL languages like Hebrew and Arabic.

Просмотреть файл

@ -14,9 +14,8 @@ The datagrid interactively supports the manipulation of data using [SfDataPager]
The datagrid performs paging of data using the `SfDataPager`. To enable paging, follow below procedure
* Create a new `SfDataPager` widget, and set the [SfDataGrid.DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) to the [SfDataPager.delegate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/delegate.html) property.
* Set the number of rows to be displayed on a page by setting the [SfDataPager.rowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/rowsPerPage.html) property.
* Set the number of pages required to be displayed in data pager by setting the `SfDataPager.pageCount` property.
* Set the number of buttons that should be displayed in view by setting the [SfDataPager.visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html) property.
* Override the [SfDataPager.delegate.rowCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerDelegate/rowCount.html) property and [SfDataPager.delegate.handlePageChanges](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerDelegate/handlePageChange.html) method in `SfDataGrid.DataGridSource`.
* You can load the data for the specific page in `handlePageChanges` method. This method is called for every page navigation from data pager.
N> The `SfDataPager.visibleItemsCount` property default value is 5.
@ -26,91 +25,166 @@ The following code example illustrates using `SfDataPager` with the datagrid con
{% tabs %}
{% highlight Dart %}
List<OrderInfo> paginatedDataSource = [];
final int rowsPerPage = 15;
final double dataPagerHeight = 60.0;
List<OrderInfo> orders = [];
List<OrderInfo> paginatedOrders = [];
final OrderInfoDataSource _orderInfoDataSource = OrderInfoDataSource();
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraint) {
return Column(
children: [
SizedBox(
height: constraint.maxHeight - 60,
width: constraint.maxWidth,
child: SfDataGrid(
source: _orderInfoDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridNumericColumn(
mappingName: 'orderID', headerText: 'Order ID'),
GridTextColumn(
mappingName: 'customerID',
headerText: 'Customer Name'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(
mappingName: 'freight', headerText: 'Freight'),
]),
),
Container(
height: 60,
child: SfDataPager(
delegate: _orderInfoDataSource,
rowsPerPage: 20,
direction: Axis.horizontal,
return LayoutBuilder(builder: (context, constraint) {
return Column(
children: [
SizedBox(
height: constraint.maxHeight - dataPagerHeight,
width: constraint.maxWidth,
child: SfDataGrid(
source: _orderInfoDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridTextColumn(
columnName: 'orderID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order ID',
overflow: TextOverflow.ellipsis,
),
),
),
)
],
);
},
),
);
GridTextColumn(
columnName: 'customerID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
)),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
),
),
),
],
),
),
Container(
height: dataPagerHeight,
child: SfDataPager(
delegate: _orderInfoDataSource,
pageCount: orders.length / rowsPerPage,
direction: Axis.horizontal,
),
)
],
);
});
}
class OrderInfoDataSource extends DataGridSource<OrderInfo> {
@override
List<OrderInfo> get dataSource => paginatedDataSource;
@override
Object getValue(OrderInfo orderInfos, String columnName) {
switch (columnName) {
case 'orderID':
return orderInfos.orderID;
break;
case 'customerID':
return orderInfos.customerID;
break;
case 'freight':
return orderInfos.freight;
break;
case 'orderDate':
return orderInfos.orderData;
break;
default:
return '';
break;
}
class OrderInfoDataSource extends DataGridSource{
OrderInfoDataSource() {
paginatedOrders = orders.getRange(0, 19).toList(growable: false);
buildPaginateDataGridRows();
}
@override
int get rowCount => orderInfos.length;
List<DataGridRow> dataGridRows = [];
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex,
int startRowIndex, int rowsPerPage) async {
int endIndex = startRowIndex + rowsPerPage;
if (endIndex > orderInfos.length) {
endIndex = orderInfos.length - 1;
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
if (dataGridCell.columnName == 'orderID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
),
);
} else if (dataGridCell.columnName == 'customerID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
} else if (dataGridCell.columnName == 'orderDate') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
DateFormat.yMd().format(dataGridCell.value).toString(),
overflow: TextOverflow.ellipsis,
));
} else {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
NumberFormat.currency(locale: 'en_US', symbol: '\$')
.format(dataGridCell.value)
.toString(),
overflow: TextOverflow.ellipsis,
));
}
}).toList());
}
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex) async {
int startIndex = newPageIndex * rowsPerPage;
int endIndex = startIndex + rowsPerPage;
if(startIndex < orders.length && endIndex <= orders.length){
paginatedOrders = orders.getRange(startIndex, endIndex).toList(growable: false);
buildPaginatedDataGridRows();
notifyListeners();
}else{
paginatedOrders = [];
}
paginatedDataSource = List.from(
orderInfos.getRange(startRowIndex, endIndex).toList(growable: false));
notifyListeners();
return true;
}
void buildPaginatedDataGridRows() {
dataGridRows = paginatedOrders.map<DataGridRow>((dataGridRow) {
return DataGridRow(cells: [
DataGridCell(columnName: 'orderID', value: dataGridRow.orderID),
DataGridCell(columnName: 'customerID', value: dataGridRow.customerID),
DataGridCell(columnName: 'orderDate', value: dataGridRow.orderData),
DataGridCell(columnName: 'freight', value: dataGridRow.freight),
]);
}).toList(growable: false);
}
}
{% endhighlight %}
@ -145,7 +219,7 @@ Widget build(BuildContext context) {
height: 60,
width: constraints.maxWidth,
child: SfDataPager(
rowsPerPage: 20,
pageCount: orders.length / rowsPerPage,
direction: Axis.horizontal,
onPageNavigationStart: (int pageIndex) {
//You can do your customization
@ -169,31 +243,132 @@ Widget buildDataGrid(BoxConstraints constraint) {
source: _orderInfoDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'orderID', headerText: 'Order ID'),
GridTextColumn(
mappingName: 'customerID', headerText: 'Customer Name'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight'),
]);
columnName: 'orderID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'customerID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
)),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
),
),
),
],
);
}
class OrderInfoDataSource extends DataGridSource<OrderInfo> {
class OrderInfoDataSource extends DataGridSource{
OrderInfoDataSource() {
paginatedOrders = orders.getRange(0, 19).toList(growable: false);
buildPaginatedDataGridRows();
}
List<DataGridRow> dataGridRows = [];
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex,
int startRowIndex, int rowsPerPage) async {
int endIndex = startRowIndex + rowsPerPage;
if (endIndex > orderInfos.length) {
endIndex = orderInfos.length - 1;
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
if (dataGridCell.columnName == 'orderID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
),
);
} else if (dataGridCell.columnName == 'customerID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
} else if (dataGridCell.columnName == 'orderDate') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
DateFormat.yMd().format(dataGridCell.value).toString(),
overflow: TextOverflow.ellipsis,
));
} else {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
NumberFormat.currency(locale: 'en_US', symbol: '\$')
.format(dataGridCell.value)
.toString(),
overflow: TextOverflow.ellipsis,
));
}
}).toList());
}
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex) async {
int startIndex = newPageIndex * rowsPerPage;
int endIndex = startIndex + rowsPerPage;
if(startIndex < orders.length && endIndex <= orders.length){
paginatedOrders = orders.getRange(startIndex, endIndex).toList(growable: false);
buildPaginatedDataGridRows();
notifyListeners();
}else{
paginatedOrders = [];
}
await Future.delayed(Duration(milliseconds: 2000));
paginatedDataSource = List.from(
orderInfos.getRange(startRowIndex, endIndex).toList(growable: false));
notifyListeners();
return true;
}
void buildPaginatedDataGridRows() {
dataGridRows = paginatedOrders.map<DataGridRow>((dataGridRow) {
return DataGridRow(cells: [
DataGridCell(columnName: 'orderID', value: dataGridRow.orderID),
DataGridCell(columnName: 'customerID', value: dataGridRow.customerID),
DataGridCell(columnName: 'orderDate', value: dataGridRow.orderData),
DataGridCell(columnName: 'freight', value: dataGridRow.freight),
]);
}).toList(growable: false);
}
}
{% endhighlight %}
@ -214,6 +389,7 @@ final OrderInfoDataSource _orderInfoDataSource = OrderInfoDataSource();
bool showLoadingIndicator = true;
@override
Widget build(BuildContext context) {
return Scaffold(
@ -230,7 +406,8 @@ Widget build(BuildContext context) {
height: 60,
width: constraints.maxWidth,
child: SfDataPager(
rowsPerPage: 20,
pageCount:
orders.length / rowsPerPage,
direction: Axis.horizontal,
onPageNavigationStart: (int pageIndex) {
setState(() {
@ -258,13 +435,51 @@ Widget buildDataGrid(BoxConstraints constraint) {
source: _orderInfoDataSource,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'orderID', headerText: 'Order ID'),
GridTextColumn(
mappingName: 'customerID', headerText: 'Customer Name'),
GridDateTimeColumn(
mappingName: 'orderDate', headerText: 'Order Date'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight'),
]);
columnName: 'orderID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order ID',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'customerID',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Customer Name',
overflow: TextOverflow.ellipsis,
),
)),
GridTextColumn(
columnName: 'orderDate',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Order Date',
overflow: TextOverflow.ellipsis,
),
),
),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
),
),
),
],
);
}
Widget buildStack(BoxConstraints constraints) {
@ -294,22 +509,86 @@ Widget buildStack(BoxConstraints constraints) {
);
}
class OrderInfoDataSource extends DataGridSource<OrderInfo> {
class OrderInfoDataSource extends DataGridSource{
OrderInfoDataSource() {
paginatedOrders = orders.getRange(0, 19).toList(growable: false);
buildPaginateDataGridRows();
}
List<DataGridRow> dataGridRows = [];
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex,
int startRowIndex, int rowsPerPage) async {
int endIndex = startRowIndex + rowsPerPage;
if (endIndex > orderInfos.length) {
endIndex = orderInfos.length - 1;
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
if (dataGridCell.columnName == 'orderID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
),
);
} else if (dataGridCell.columnName == 'customerID') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
} else if (dataGridCell.columnName == 'orderDate') {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
DateFormat.yMd().format(dataGridCell.value).toString(),
overflow: TextOverflow.ellipsis,
));
} else {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.center,
child: Text(
NumberFormat.currency(locale: 'en_US', symbol: '\$')
.format(dataGridCell.value)
.toString(),
overflow: TextOverflow.ellipsis,
));
}
}).toList());
}
@override
Future<bool> handlePageChange(int oldPageIndex, int newPageIndex) async {
int startIndex = newPageIndex * rowsPerPage;
int endIndex = startIndex + rowsPerPage;
if(startIndex < orders.length && endIndex <= orders.length){
await Future.delayed(Duration(milliseconds: 2000));
paginatedOrders = orders.getRange(startIndex, endIndex).toList(growable: false);
buildPaginatedDataGridRows();
notifyListeners();
}else{
paginatedOrders = [];
}
await Future.delayed(Duration(milliseconds: 2000));
paginatedDataSource = List.from(
orderInfos.getRange(startRowIndex, endIndex).toList(growable: false));
notifyListeners();
return true;
}
void buildPaginatedDataGridRows() {
dataGridRows = paginatedOrders.map<DataGridRow>((dataGridRow) {
return DataGridRow(cells: [
DataGridCell(columnName: 'orderID', value: dataGridRow.orderID),
DataGridCell(columnName: 'customerID', value: dataGridRow.customerID),
DataGridCell(columnName: 'orderDate', value: dataGridRow.orderData),
DataGridCell(columnName: 'freight', value: dataGridRow.freight),
]);
}).toList(growable: false);
}
}
{% endhighlight %}
@ -374,18 +653,19 @@ The following code example illustrates using `SfDataPagerThemeData` with the dat
Widget build(BuildContext context) {
return Scaffold(
body: SfDataPagerTheme(
data: SfDataPagerThemeData(
itemColor: Colors.white,
selectedItemColor: Colors.lightGreen,
itemBorderRadius: BorderRadius.circular(5),
backgroundColor: Colors.teal,
data: SfDataPagerThemeData(
itemColor: Colors.white,
selectedItemColor: Colors.lightGreen,
itemBorderRadius: BorderRadius.circular(5),
backgroundColor: Colors.teal,
),
child: SfDataPager(
delegate: _orderInfoDataSource,
pageCount: orders.length / rowsPerPage,
direction: Axis.horizontal,
),
),
child: SfDataPager(
delegate: _orderInfoDataSource,
rowsPerPage: 20,
direction: Axis.horizontal,
),
));
);
}
{% endhighlight %}

Просмотреть файл

@ -0,0 +1,394 @@
---
layout: post
title: Pull to Refresh in Flutter DataGrid | DataTable | Syncfusion
description: Learn about how to add more data at runtime by using pull to refresh support and how to show refresh indicator programmatically in Syncfusion Flutter DataGrid.
platform: flutter
control: SfDataGrid
documentation: ug
---
# Pull to Refresh in Flutter DataGrid
The Flutter DataTable provides support to add more data at runtime by using the PullToRefresh feature.
You can simply enable the PullToRefresh option by setting the `SfDataGrid.allowPullToRefresh` property to `true` and override the `DataGridSource.handleRefresh` method to include the data which is going to add to the data source at runtime and then notify the data grid about the changes.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return SfDataGrid(
allowPullToRefresh: true,
source: employeeDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
);
}
class EmployeeDataSource extends DataGridSource {
List<DataGridRow> dataGridRows;
EmployeeDataSource({List<Employee> employeesData}) {
buildDataGridRows();
}
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
Future<void> handleRefresh() async {
await Future.delayed(Duration(seconds: 5));
_addMoreRows(employees, 15);
buildDataGridRows();
notifyListeners();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
final startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
}
return employeeData;
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows default view of refresh indicator](images/pull-to-refresh/flutter-datagrid-pull-to-refresh.gif)
## Customizing the refresh indicator
SfDataGrid displays the [RefreshIndicator](https://api.flutter.dev/flutter/material/RefreshIndicator-class.html) for `pull to refresh` action. So, you can set the color and background color of refresh indicator by using [ThemeData.accentColor](https://api.flutter.dev/flutter/material/ThemeData/accentColor.html) and [ThemeData.canvasColor](https://api.flutter.dev/flutter/material/ThemeData/canvasColor.html) properties.
You can also change the stroke width and displacement of refresh indicator by using `SfDataGrid.refreshIndicatorStrokeWidth` and `SfDataGrid.refreshIndicatorDisplacement` properties.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return Theme(
data: ThemeData(
accentColor: Colors.white,
canvasColor: Colors.lightBlue,
),
child: SfDataGrid(
allowPullToRefresh: true,
source: employeeDataSource,
refreshIndicatorStrokeWidth: 3.0,
refreshIndicatorDisplacement: 60.0,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows customized refresh indicator](images/pull-to-refresh/flutter-datagrid-customized-pull-to-refresh-indicator.gif)
## Programmatic Pull to Refresh
If you want to refresh data without showing a refresh indicator, you can pass `false` to the `showRefreshIndicator` optional parameter of `refresh` method. By doing this, `DataGridSource.handleRefresh` method will be called without showing the `RefreshIndicator` in UI.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
final GlobalKey<SfDataGridState> key = GlobalKey<SfDataGridState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DataGrid Demo'),
),
body: SfDataGrid(
key: key,
allowPullToRefresh: true,
source: employeeDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.refresh),
onPressed: () {
key.currentState.refresh();
},
),
);
}
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource({List<Employee> employeesData}) {
buildDataGridRows();
}
List<DataGridRow> dataGridRows = [];
@override
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
Future<void> handleRefresh() async {
await Future.delayed(Duration(seconds: 5));
_addMoreRows(employees, 15);
buildDataGridRows();
notifyListeners();
}
void buildDataGridRows() {
dataGridRows = employees
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(
columnName: 'salary', value: dataGridRow.salary),
]))
.toList();
}
List<Employee> _addMoreRows(List<Employee> employeeData, int count) {
final Random _random = Random();
final startIndex = employeeData.isNotEmpty ? employeeData.length : 0,
endIndex = startIndex + count;
for (int i = startIndex; i < endIndex; i++) {
employeeData.add(Employee(
1000 + i,
_names[_random.nextInt(_names.length - 1)],
_designation[_random.nextInt(_designation.length - 1)],
10000 + _random.nextInt(10000),
));
}
return employeeData;
}
final List<String> _names = <String>[
'Welli',
'Blonp',
'Folko',
'Furip',
'Folig',
'Picco',
'Frans',
'Warth',
'Linod',
'Simop',
'Merep',
'Riscu',
'Seves',
'Vaffe',
'Alfki'
];
final List<String> _designation = <String>[
'Project Lead',
'Developer',
'Manager',
'Designer',
'System Analyst',
'CEO'
];
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows programmatic refresh indicator](images/pull-to-refresh/flutter-datagrid-programmatic-pull-to-refresh.gif)

Просмотреть файл

@ -25,10 +25,42 @@ Widget build(BuildContext context) {
source: _employeeDatasource,
headerRowHeight: 70,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -52,10 +84,42 @@ Widget build(BuildContext context) {
source: _employeeDatasource,
rowHeight: 60,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -65,237 +129,6 @@ Widget build(BuildContext context) {
![flutter datagrid shows rows except header row with custom height](images/row-height-customization/flutter-datagrid-row-height.jpg)
## Fit row height based on its content
The row height can be fitted based on its content in [onQueryRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onQueryRowHeight.html) callback using [getAutoRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer/getAutoRowHeight.html) method which is available in [ColumnSizer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer-class.html).
To access the `getAutoRowHeight` method, create an instance of `ColumnSizer`, set this instance in `columnSizer` property and use it in `onQueryRowHeight` callback.
`ColumnSizer` objects are expected to be long-lived, not recreated with each build.
>**NOTE**
By default, the display texts overflow behavior is ellipsis. So, to enable the wrap for the display text, set the `softWrap` property as `true` and `overflow` property as clip.
{% tabs %}
{% highlight Dart %}
final ColumnSizer _columnSizer = ColumnSizer();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDatasource,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
double height = _columnSizer.getAutoRowHeight(details.rowIndex);
return height;
},
columns: <GridColumn>[
GridTextColumn(mappingName: 'id',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'ID'),
GridTextColumn(mappingName: 'contactName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Contact Name'),
GridTextColumn(mappingName: 'companyName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Company Name'),
GridTextColumn(mappingName: 'city',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'City'),
GridTextColumn(mappingName: 'address',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Address'),
GridTextColumn(mappingName: 'designation',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Designation'),
GridTextColumn(mappingName: 'country',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Country'),
]));
}
{% endhighlight %}
{% endtabs %}
![rows are fitted in flutter datagrid ](images/row-height-customization/flutter-datagrid-auto-fit-row.jpg)
### Auto fit row height options
#### Exclude the certain columns from auto-fit row calculation
By default, `getAutoRowHeight` method calculates the row height based on all columns. To skip the specific columns from the row height calculation, add that columns to the `excludeColumns` parameter in `getAutoRowHeight` method.
{% tabs %}
{% highlight Dart %}
final List<String> _excludeColumns = [
'designation',
'address',
'city',
];
final ColumnSizer _columnSizer = ColumnSizer();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _autoRowHeightDataGridSource,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
final double height = _columnSizer.getAutoRowHeight(details.rowIndex,
excludedColumns: _excludeColumns);
return height;
},
columns: <GridColumn>[
GridTextColumn(mappingName: 'id',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'ID'),
GridTextColumn(mappingName: 'contactName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Contact Name'),
GridTextColumn(mappingName: 'companyName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Company Name'),
GridTextColumn(mappingName: 'address',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Address'),
GridTextColumn(mappingName: 'city',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'City'),
GridTextColumn(mappingName: 'designation',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Designation'),
GridTextColumn(mappingName: 'country',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Country'),
]));
}
{% endhighlight %}
{% endtabs %}
#### Include the hidden columns in auto-fit row calculation
The hidden columns can also be considered for the row height calculation by using the `canIncludeHiddenColumns` parameter in
`getAutoRowHeight` method.
{% tabs %}
{% highlight Dart %}
final ColumnSizer _columnSizer = ColumnSizer();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _autoRowHeightDataGridSource,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
final double height = _columnSizer.getAutoRowHeight(details.rowIndex,
canIncludeHiddenColumns: true);
return height;
},
columns: <GridColumn>[
GridTextColumn(mappingName: 'id',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'ID'),
GridTextColumn(mappingName: 'contactName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Contact Name'),
GridTextColumn(mappingName: 'companyName',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Company Name'),
GridTextColumn(mappingName: 'country',
softWrap: true,
overflow: TextOverflow.clip,
headerText: 'Country'),
GridTextColumn(mappingName: 'address',
softWrap: true,
visible: false,
overflow: TextOverflow.clip,
headerText: 'Address'),
GridTextColumn(mappingName: 'city',
softWrap: true,
visible: false,
overflow: TextOverflow.clip,
headerText: 'City'),
GridTextColumn(mappingName: 'designation',
softWrap: true,
visible: false,
overflow: TextOverflow.clip,
headerText: 'Designation'),
]));
}
{% endhighlight %}
{% endtabs %}
## Fit header row height based on its content
The datagrid allows you to customize the height of the header row based on its content using the `onQueryRowHeight` callback and getAutoRowHeight method which is available in ColumnSizer.
>**NOTE**
By default, the header texts overflow behavior is ellipsis. So, to enable the wrap for the display text, set the [headerTextSoftWrap](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerTextSoftWrap.html) property as true and [headerTextOverflow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerTextOverflow.html) property as clip.
{% tabs %}
{% highlight Dart %}
final ColumnSizer _columnSizer = ColumnSizer();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDatasource,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
final double height = _columnSizer.getAutoRowHeight(details.rowIndex);
// The header row index.
if(details.rowIndex == 0) {
return height;
}
return 49.0;
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation',
headerTextSoftWrap: true,
headerTextOverflow: TextOverflow.clip,
headerText: 'Employee Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
],
));
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows header row with custom height](images/row-height-customization/flutter-datagrid-auto-fit-header-row.png)
## Refresh row height for specific row
The `SfDataGrid` allows you to update or refresh specific row and it's height when
@ -314,9 +147,9 @@ In the below example, row data is updated when the `refreshRow` is called in `on
{% tabs %}
{% highlight Dart %}
final List<Employee> _employees = <Employee>[];
List<Employee> _employees;
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
EmployeeDataSource _employeeDataSource;
final DataGridController _controller = DataGridController();
@ -338,20 +171,56 @@ Widget build(BuildContext context) {
_employeeData[0].designation = 'Sales Representative';
_employees[0].salary = 25000;
_controller.refreshRow(0);
_employeeDataSource.getData(_employees);
_employeeDataSource.updateDataSource();
}),
SfDataGrid(
source: _employeeDataSource,
controller: _controller,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
return _columnSizer.getAutoRowHeight(details.rowIndex);
},
if (details.rowIndex == 0) {
return 100.0;
}
return 50.0;
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
],
@ -367,9 +236,9 @@ In the below example, row data is refreshed along with its row height when the `
{% tabs %}
{% highlight Dart %}
final List<Employee> _employees = <Employee>[];
List<Employee> _employees;
final EmployeeDataSource _employeeDataSource = EmployeeDataSource();
EmployeeDataSource _employeeDataSource;
final DataGridController _controller = DataGridController();
@ -391,20 +260,56 @@ Widget build(BuildContext context) {
_employeeData[0].designation = 'Sales Representative';
_employees[0].salary = 25000;
_controller.refreshRow(0, recalculateRowHeight: true);
_employeeDataSource.getData(_employees);
_employeeDataSource.updateDataSource();
}),
SfDataGrid(
source: _employeeDataSource,
controller: _controller,
columnSizer: _columnSizer,
onQueryRowHeight: (RowHeightDetails details) {
return _columnSizer.getAutoRowHeight(details.rowIndex);
},
if (details.rowIndex == 0) {
return 100;
}
return 50;
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(
mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
],
@ -414,8 +319,3 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}

Просмотреть файл

@ -27,10 +27,42 @@ N> The default value of `isScrollbarAlwaysShown` is false.
source: _employeeDataSource,
isScrollbarAlwaysShown: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
);
@ -58,10 +90,42 @@ The following example shows how to disable the horizontal and vertical scrolling
horizontalScrollPhysics: NeverScrollableScrollPhysics(),
verticalScrollPhysics: NeverScrollableScrollPhysics(),
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation', headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
);
@ -69,3 +133,435 @@ The following example shows how to disable the horizontal and vertical scrolling
{% endhighlight %}
{% endtabs %}
## Programmatic scrolling
The Flutter DataTable provides support to scroll to a particular row and column index programmatically.
### Scroll to cell
Scroll programmatically to a particular cell can be achieved by passing the row and column index in the `scrollToCell` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in `scrollToCell` method.
N> The default value of `canAnimate` is `false`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToCell'),
onPressed: () {
_controller.scrollToCell(15, 2);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
![Flutter DataTable shows programmatic scrolling to cell](images/scrolling/flutter-datagrid-programmatic-scrolling-scroll-to-cell.gif)
### Scroll to row
You can scroll programmatically to a particular row by passing the row index in the `scrollToRow` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in `scrollToRow` method.
N> The default value of `canAnimate` is `false`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToRow'),
onPressed: () {
_controller.scrollToRow(15);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
### Scroll to column
You can scroll programmatically to a particular column by passing the column index in the `scrollToColumn` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in `scrollToColumn` method.
N> The default value of `canAnimate` is `false`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToColumn'),
onPressed: () {
_controller.scrollToColumn(2);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
![Flutter DataTable shows programmatic scrolling to column](images/scrolling/flutter-datagrid-programmatic-scrolling-scroll-to-column.gif)
### Scroll to specific position
`SfDataGrid` allows to position the scrolled row or column in view programmatically by passing `DataGridScrollPosition` to `rowPosition` and `columnPosition` arguments respectively in `scrollToCell` and `position` argument of `scrollToRow` and `scrollToColumn` methods. Below are the four types of positions available,
`makeVisible`: Scroll to make a specified row/column visible in datagrid. If the specified row/column is already in view, scrolling will not occur.
`start`: Scroll to make the row/column positioned at the start of the datagrid.
`center`: Scroll to make the row/column positioned at the center of the datagrid.
`end`: Scroll to make the row/column positioned at the end of the datagrid.
N> The default value of `DataGridScrollPosition` is `Start`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToCell'),
onPressed: () {
_controller.scrollToCell(15, 2,
canAnimate: true,
rowPosition: DataGridScrollPosition.start,
columnPosition: DataGridScrollPosition.start);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
### Scroll to vertical offset
The Flutter DataTable supports to scroll programmatically to a particular vertical offset by passing the offset value to the `scrollToVerticalOffset` method. Also, it allows to enable the scrolling animation by passing `true` to the `canAnimate` parameter in `scrollToVerticalOffset` method.
N> The default value of `canAnimate` is `false`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToVerticalOffset'),
onPressed: () {
_controller.scrollToVerticalOffset(500);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
### Scroll to horizontal offset
The Flutter DataTable supports to scroll programmatically to a particular horizontal offset by passing the offset value to the `scrollToHorizontalOffset` method. Also, it allows to enable the scrolling animation by passing `true` to the `canAnimate` parameter in `scrollToHorizontalOffset` method.
N> The default value of `canAnimate` is `false`.
{% tabs %}
{% highlight Dart %}
final DataGridController _controller = DataGridController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
FlatButton(
child: Text('ScrollToHorizontalOffset'),
onPressed: () {
_controller.scrollToHorizontalOffset(400);
},
),
Expanded( child:SfDataGrid(
source: _employeeDataSource,
columns: [
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
controller: _controller,
)),
);
}
{% endhighlight %}
{% endtabs %}
N> The vertical and horizontal scrolled offset can be retrieved by using `DataGridController.verticalOffset` and `DataGridController.horizontalOffset` properties.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -34,14 +34,46 @@ Widget build(BuildContext context) {
SfDataGrid(
source: _employeeDataSource,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: FlatButton(
onPressed: () {
_employeeDataSource.sortedColumns.add(SortColumnDetails(
@ -64,7 +96,8 @@ Widget build(BuildContext context) {
## Multi-column sorting
The datagrid sorts the data against more than one columns by setting the [SfDataGrid.allowMultiColumnSorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowMultiColumnSorting.html) property to true. The number of columns by which the data can be sorted is unlimited. To apply sorting for multiple columns, tap the desired column headers after setting the `SfDataGrid.allowMultiColumnSorting` property.
To apply sorting for multiple columns in web, you can click the column header by pressing the <kbd>Ctrl</kbd> key.
To apply sorting for multiple columns in web and desktop, you can click the column header by pressing the <kbd>Ctrl</kbd> key.
{% tabs %}
{% highlight Dart %}
@ -79,10 +112,42 @@ Widget build(BuildContext context) {
allowSorting: true,
allowMultiColumnSorting: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -110,10 +175,42 @@ Widget build(BuildContext context) {
allowMultiColumnSorting: true,
allowTriStateSorting: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -140,10 +237,42 @@ Widget build(BuildContext context) {
allowSorting: true,
sortingGestureType: SortingGestureType.doubleTap,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -169,9 +298,42 @@ Widget build(BuildContext context) {
allowMultiColumnSorting: true,
showSortNumbers: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -197,11 +359,43 @@ Widget build(BuildContext context) {
source: _employeeDataSource,
allowSorting: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID',
allowSorting: false),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
allowSorting: false,
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
));
}
@ -211,34 +405,7 @@ Widget build(BuildContext context) {
## Change the color of sort icon
The color of sort icon can be customized by using [SfDataGridThemeData.headerStyle.sortIconColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/headerStyle.html) and [GridColumn.headerStyle.sortIconColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/headerStyle.html).
The following code describes how to change sort icon color by using [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html).
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGrid(
source: _employeeDataSource,
allowSorting: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID',
headerStyle: DataGridHeaderCellStyle(sortIconColor: Colors.redAccent)),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
],
));
}
{% endhighlight %}
{% endtabs %}
The color of sort icon can be customized by using [SfDataGridThemeData.sortIconColor]().
The following code describes how to change sort icon color by using [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html).
@ -253,17 +420,48 @@ Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
headerStyle:
DataGridHeaderCellStyle(sortIconColor: Colors.redAccent)),
sortIconColor: Colors.redAccent),
child: SfDataGrid(
source: _employeeDataSource,
allowSorting: true,
allowMultiColumnSorting: true,
columns: [
GridNumericColumn(mappingName: 'id', headerText: 'ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'city', headerText: 'City'),
GridNumericColumn(mappingName: 'freight', headerText: 'Freight')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'city',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'City',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'freight',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Freight',
overflow: TextOverflow.ellipsis,
))),
],
),
));
@ -290,49 +488,69 @@ The following code shows how to perform custom sorting for the columns based on
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => _employeeData;
@override
Object getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'city':
return employee.city;
break;
case 'freight':
return employee.freight;
break;
default:
return ' ';
break;
}
class EmployeeDataSource extends DataGridSource {
List<DataGridRow> dataGridRows;
EmployeeDataSource({List<Employee> employeesData}) {
dataGridRows = employeesData
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(columnName: 'salary', value: dataGridRow.salary)
]))
.toList();
}
@override
int compare(Employee a, Employee b, SortColumnDetails sortColumn) {
var x = getValue(a, sortColumn.name);
var y = getValue(b, sortColumn.name);
if (x == null || y == null) {
if (sortColumn.sortDirection == DataGridSortDirection.ascending)
return x == null ? -1 : 1;
else
return x == null ? 1 : -1;
}
int xLength = x.toString().length;
int yLength = y.toString().length;
if (xLength.compareTo(yLength) > 0)
return sortColumn.sortDirection == DataGridSortDirection.ascending ? 1 : -1;
else if (xLength.compareTo(yLength) == -1)
return sortColumn.sortDirection == DataGridSortDirection.ascending ? -1 : 1;
else
return 0;
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
int compare(DataGridRow? a, DataGridRow? b, SortColumnDetails sortColumn) {
final String? value1 = a
?.getCells()
.firstWhereOrNull((element) => element.columnName == sortColumn.name)
?.value;
final String? value2 = b
?.getCells()
.firstWhereOrNull((element) => element.columnName == sortColumn.name)
?.value;
int? aLength = value1?.length;
int? bLength = value2?.length;
if (aLength == null || bLength == null) {
return 0;
}
if (aLength.compareTo(bLength) > 0) {
return sortColumn.sortDirection == DataGridSortDirection.ascending
? 1
: -1;
} else if (aLength.compareTo(bLength) == -1) {
return sortColumn.sortDirection == DataGridSortDirection.ascending
? -1
: 1;
} else {
return 0;
}
}
}
@ -354,46 +572,63 @@ The following code shows how to perform custom sorting for the columns based on
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
class EmployeeDataSource extends DataGridSource<Employee> {
@override
List<Employee> get dataSource => _employeeData;
@override
Object getValue(Employee employee, String columnName) {
switch (columnName) {
case 'id':
return employee.id;
break;
case 'name':
return employee.name;
break;
case 'city':
return employee.city;
break;
case 'freight':
return employee.freight;
break;
default:
return ' ';
break;
}
List<DataGridRow> dataGridRows;
EmployeeDataSource({List<Employee> employeesData}) {
dataGridRows = employeesData
.map<DataGridRow>((dataGridRow) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'id', value: dataGridRow.id),
DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
DataGridCell<String>(
columnName: 'designation', value: dataGridRow.designation),
DataGridCell<int>(columnName: 'salary', value: dataGridRow.salary)
]))
.toList();
}
@override
int compare(Employee a, Employee b, SortColumnDetails sortColumn) {
if (sortColumn.name == 'name') {
if (sortColumn.sortDirection == DataGridSortDirection.ascending) {
if (a.name == null || b.name == null)
return a.name == null ? -1 : 1;
else
return a.name.toLowerCase().compareTo(b.name.toLowerCase());
} else {
if (a.name == null || b.name == null)
return a.name == null ? 1 : -1;
else
return b.name.toLowerCase().compareTo(a.name.toLowerCase());
}
}
return super.compare(a, b, sortColumn);
List<DataGridRow> get rows => dataGridRows;
@override
DataGridRowAdapter? buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id' ||
dataGridCell.columnName == 'salary')
? Alignment.centerRight
: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
));
}).toList());
}
@override
int compare(DataGridRow? a, DataGridRow? b, SortColumnDetails sortColumn) {
if (sortColumn.name == 'name') {
final String? value1 = a
?.getCells()
.firstWhereOrNull((element) => element.columnName == sortColumn.name)
?.value;
final String? value2 = b
?.getCells()
.firstWhereOrNull((element) => element.columnName == sortColumn.name)
?.value;
if (value1 == null || value2 == null) {
return 0;
}
if (sortColumn.sortDirection == DataGridSortDirection.ascending) {
return value1.compareTo(value2);
} else {
return value2.compareTo(value1);
}
}
return super.compare(a, b, sortColumn);
}
}

Просмотреть файл

@ -11,7 +11,7 @@ documentation: ug
The datagrid provides support to display an additional unbound header rows known as [StackedHeaderRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/stackedHeaderRows.html) that are spanned across the DataGrid columns. You can group one or more columns under each stacked header.
Each [StackedHeaderRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderRow-class.html) contains [cells](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderRow/cells.html) that hold a list of [StackedHeaderCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell-class.html) where each `StackedHeaderCell` contains a number of child columns. The [StackedHeaderCell.columnNames](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell/columnNames.html) property returns the columns grouped under the stacked header row. The [GridColumn.mappingName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/mappingName.html) is a unique name used for mapping specific child columns grouped under the same stacked header row. The [StackedHeaderCell.child](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell/child.html) property is used to load any type of widget to the corresponding stacked header cell.
Each [StackedHeaderRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderRow-class.html) contains [cells](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderRow/cells.html) that hold a list of [StackedHeaderCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell-class.html) where each `StackedHeaderCell` contains a number of child columns. The [StackedHeaderCell.columnNames](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell/columnNames.html) property returns the columns grouped under the stacked header row. The [GridColumn.columnName]() is a unique name used for mapping specific child columns grouped under the same stacked header row. The [StackedHeaderCell.child](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/StackedHeaderCell/child.html) property is used to load any type of widget to the corresponding stacked header cell.
{% tabs %}
{% highlight Dart %}
@ -21,35 +21,62 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return SfDataGridTheme(
data: SfDataGridThemeData(
headerStyle: DataGridHeaderCellStyle(
backgroundColor: const Color(0xFFF1F1F1))),
child: SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'orderId', headerText: 'ID'),
GridTextColumn(mappingName: 'customerName', headerText: 'Name'),
GridNumericColumn(mappingName: 'productId', headerText: 'ID'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
),
return SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'orderId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'customerName',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
))),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
);
}
@ -70,42 +97,69 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return SfDataGridTheme(
data: SfDataGridThemeData(
headerStyle: DataGridHeaderCellStyle(
backgroundColor: const Color(0xFFF1F1F1))),
child: SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'orderId', headerText: 'ID'),
GridTextColumn(mappingName: 'customerName', headerText: 'Name'),
GridNumericColumn(mappingName: 'productId', headerText: 'ID'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName', 'productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Order Shipment Details')))),
]),
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
),
return SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
columns: <GridColumn>[
GridTextColumn(
columnName: 'orderId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'customerName',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
))),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName', 'productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Order Shipment Details')))),
]),
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
);
}
@ -128,41 +182,68 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return SfDataGridTheme(
data: SfDataGridThemeData(
headerStyle: DataGridHeaderCellStyle(
backgroundColor: const Color(0xFFF1F1F1))),
child: SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
onQueryRowHeight: (RowHeightDetails details) {
if (details.rowIndex == 0) {
return 70.0;
}
return null;
},
columns: <GridColumn>[
GridNumericColumn(mappingName: 'orderId', headerText: 'ID'),
GridTextColumn(mappingName: 'customerName', headerText: 'Name'),
GridNumericColumn(mappingName: 'productId', headerText: 'ID'),
GridTextColumn(mappingName: 'product', headerText: 'Product'),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
),
return SfDataGrid(
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
source: _productDataSource,
onQueryRowHeight: (RowHeightDetails details) {
if (details.rowIndex == 0) {
return 70.0;
}
return details.rowHeight;;
},
columns: <GridColumn>[
GridTextColumn(
columnName: 'orderId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'customerName',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'productId',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'product',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Product',
overflow: TextOverflow.ellipsis,
))),
],
stackedHeaderRows: <StackedHeaderRow>[
StackedHeaderRow(cells: [
StackedHeaderCell(
columnNames: ['orderId', 'customerName'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Customer Details')))),
StackedHeaderCell(
columnNames: ['productId', 'product'],
child: Container(
color: const Color(0xFFF1F1F1),
child: Center(child: Text('Product Details'))))
])
],
);
}

Просмотреть файл

@ -9,91 +9,7 @@ documentation: ug
# Styling in Flutter DataGrid
The data grid applies style for all its elements by writing a Style class overriding from `DataGridCellStyle`. The styling can be applied to DataGrid by using the [SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) in [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html). The DataGrid should be wrapped inside the `SfDataGridTheme`.
All the style classes such as [DataGridCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridCellStyle-class.html), [DataGridHeaderCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridHeaderCellStyle-class.html) related to `SfDataGrid` are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. To access those classes, import the below file in your application,
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_core/theme.dart';
{% endhighlight %}
{% endtabs %}
## Styling row
The appearance of cell can be customized by using the [SfDataGridThemeData.cellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/cellStyle.html). It is applicable for all the record cells except column header.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
cellStyle: DataGridCellStyle(
textStyle: TextStyle(color: Colors.white),
backgroundColor: Colors.indigo[300])),
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridTextColumn(mappingName: 'designation',
headerText: 'Designation'),
GridNumericColumn(mappingName: 'salary',headerText: 'Salary',
],
),
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows rows with styling](images/styles/flutter-datagrid-rows-styling.png)
## Styling column header
The appearance of cell can be customized by using the `SfDataGridThemeData.cellStyle`. It is applicable for all the record cells except column header.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:syncfusion_flutter_core/theme.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfDataGridTheme(
data: SfDataGridThemeData(
headerStyle: DataGridHeaderCellStyle(
textStyle:
TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
backgroundColor: Colors.teal)),
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(mappingName: 'designation',headerText: 'Designation')
],
),
),
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows column header with styling](images/styles/flutter-datagrid-column-header-styling.png)
The DataGrid supports to change the appearance of the grid by using the [SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) in [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html). The DataGrid should be wrapped inside the `SfDataGridTheme`.
## Styling grid lines
@ -111,11 +27,42 @@ Widget build(BuildContext context) {
child: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id', headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(mappingName: 'designation',
headerText: 'Designation')
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
),
),
@ -152,10 +99,42 @@ Widget build(BuildContext context) {
body: SfDataGrid(
source: _employeeDataSource,
columns: <GridColumn>[
GridNumericColumn(mappingName: 'id',headerText: 'Order ID'),
GridTextColumn(mappingName: 'name', headerText: 'Name'),
GridNumericColumn(mappingName: 'salary', headerText: 'Salary'),
GridTextColumn(mappingName: 'designation',headerText: 'Designation'),
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both),

216
Flutter/datagrid/swiping.md Normal file
Просмотреть файл

@ -0,0 +1,216 @@
---
layout: post
title: Swiping in Flutter DataGrid | DataTable | Syncfusion
description: Learn about how to provide swiping support to the data rows in both directions in Syncfusion Flutter DataGrid.
platform: flutter
control: SfDataGrid
documentation: ug
---
# Swiping in Flutter DataGrid
The Flutter DataTable provides support to swipe a row by setting the `SfDataGrid.allowSwiping` property to true. Swipe actions will be displayed when swiping a row from `left to right` or `right to left` direction. The swipe dragging gesture can be restricted to a certain point on the row by setting the `SfDataGrid.maxSwipeOffset` property.
## Swipe action builders
The Flutter DataTable enables you to load the desired widget behind the swiped row by using `SfDataGrid.startSwipeActionsBuilder` and `SfDataGrid.endSwipeActionsBuilder` properties. The swipe widget's width that loads from the actions builder is arranged based on the `SfDataGrid.maxSwipeOffset` property and it takes height based on the current swiping row height.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return SfDataGrid(
allowSwiping: true,
swipeMaxOffset: 100.0,
source: employeeDataSource,
startSwipeActionsBuilder: (BuildContext context, DataGridRow row) {
return GestureDetector(
onTap: () {
_employeeDataSource.dataGridRows.insert(
_employeeDataSource.dataGridRows.indexOf(row),
DataGridRow(cells: [
DataGridCell(value: 1011, columnName: 'id'),
DataGridCell(value: 'Tom Bass', columnName: 'name'),
DataGridCell(value: 'Developer', columnName: 'designation'),
DataGridCell(value: 20000, columnName: 'salary')
]));
_employeeDataSource.updateDataSource();
},
child: Container(
color: Colors.greenAccent,
child: Center(
child: Icon(Icons.add),
),
),
);
},
endSwipeActionsBuilder: (BuildContext context, DataGridRow row) {
return GestureDetector(
onTap: () {
_employeeDataSource.dataGridRows.removeAt(
_employeeDataSource.dataGridRows.indexOf(row));
_employeeDataSource.updateDataSource();
},
child: Container(
color: Colors.redAccent,
child: Center(
child: Icon(Icons.delete),
),
),
);
},
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
);
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows swiping a row in both directions](images/swiping/flutter-datagrid-swiping.gif)
## Swipe callbacks
The data grid provides the following callbacks to notify the swiping stages:
* `onSwipeStart`: Called when the swipe offset changes from its initial value. The swipe action can be canceled by return `false`.
* `onSwipeUpdate`: Called while swiping a row is in progress. The swipe action can be canceled by return `false`.
* `onSwipeEnd`: called when the swipe offset value reaches the `SfDataGrid.maxSwipeOffset` indicating that the swipe action is completed.
The swipe callbacks provide the following properties in their arguments:
* `RowIndex`: Defines the swiping row index.
* `SwipeDirection`: Defines the swipe direction of the swiped row.
* `SwipeOffset`: Defines the current swipe offset of the row being swiped.
By handling the swipe callbacks, you can use these properties value from the arguments to perform any desired action such as deleting the row, editing the data, etc.
## Customized swipes delete functionality
You can perform customized swipe functionality using the swiping callbacks. The below example shows how to delete a row when swiping a data row from one to another end.
{% tabs %}
{% highlight Dart %}
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return SfDataGrid(
allowSwiping: true,
swipeMaxOffset: constraints.maxWidth,
source: employeeDataSource,
startSwipeActionsBuilder: (BuildContext context, DataGridRow row) {
return GestureDetector(
onTap: () {
_employeeDataSource.dataGridRows.removeAt(
_employeeDataSource.dataGridRows.indexOf(row));
_employeeDataSource.updateDataSource();
},
child: Container(
color: Colors.green,
padding: EdgeInsets.only(left: 30.0),
alignment: Alignment.centerLeft,
child: Text('Delete', style: TextStyle(color: Colors.white)),
),
);
},
onSwipeUpdate: (details) {
isReachedCenter =
(details.swipeOffset >= constraints.maxWidth / 2) ? true : false;
return true;
},
onSwipeEnd: (details) async {
if (isReachedCenter &&
_employeeDataSource.dataGridRows.isNotEmpty) {
_employeeDataSource.dataGridRows.removeAt(details.rowIndex);
_employeeDataSource.updateDataSource();
isReachedCenter = false;
}
},
columns: <GridColumn>[
GridTextColumn(
columnName: 'id',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'ID',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'name',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Name',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'designation',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text(
'Designation',
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
columnName: 'salary',
label: Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerRight,
child: Text(
'Salary',
overflow: TextOverflow.ellipsis,
))),
],
);
});
}
{% endhighlight %}
{% endtabs %}
![flutter datagrid shows customized swiping delete functionality](images/swiping/flutter-datagrid-customized-swiping-delete-funtionality.gif)

Просмотреть файл

@ -108,6 +108,14 @@ This page helps to navigate to the public API's available in the Syncfusion Flut
<a href="https://pub.dev/documentation/syncfusion_flutter_sliders/latest/sliders/SfSlider-class.html">Link</a>
</td>
</tr>
<tr>
<td>
Treemap
</td>
<td>
<a href="https://pub.dev/documentation/syncfusion_flutter_charts/latest/treemap/SfTreemap-class.html">Link</a>
</td>
</tr>
<tr>
<td>
Spark Charts

Просмотреть файл

@ -36,7 +36,7 @@ The section contains the GitHub link for each widgets code examples. This is
<tr>
<td><p><a href="https://help.syncfusion.com/flutter/cartesian-charts/overview">Cartesian chart</a></p></td>
<td><p><a href="https://github.com/syncfusion/flutter-examples/tree/master/lib/samples/chart/cartesian_charts">samples/chart/cartesian_charts</a></p></td>
<td><p><a href="https://github.com/syncfusion/flutter-examples/tree/master/lib/samples/chart/cartesian_charts">samples/chart/Cartesian_charts</a></p></td>
</tr>
<tr>
@ -138,4 +138,4 @@ The section contains the GitHub link for each widgets code examples. This is
<td><p><a href="https://github.com/syncfusion/flutter-examples/tree/master/lib/samples/signature_pad">samples/signaturepad</a></p></td>
</tr>
</table>
</table>

Просмотреть файл

@ -85,6 +85,11 @@ This section provides the user guide link for each widget and its package link.
<td><p><a href="https://pub.dev/packages/syncfusion_flutter_maps">syncfusion_flutter_maps</a></p></td>
</tr>
<tr>
<td><p><a href="https://help.syncfusion.com/flutter/treemap/overview">Treemap</a></p></td>
<td><p><a href="https://pub.dev/packages/syncfusion_flutter_treemap">syncfusion_flutter_treemap</a></p></td>
</tr>
<tr>
<td rowspan="2"><p>Calendar</p></td>
<td><p><a href="https://help.syncfusion.com/flutter/calendar/overview">Event Calendar</a></p></td>

Двоичные данные
Flutter/maps/images/circle-layer/inverted-circle.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 64 KiB

Двоичные данные
Flutter/maps/images/legend/first-label-customization.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 65 KiB

Двоичные данные
Flutter/maps/images/legend/legend-title.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 60 KiB

Двоичные данные
Flutter/maps/images/polygon-layer/inverted-polygon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 44 KiB

Двоичные данные
Flutter/maps/images/shape-sublayer/equal_color_mapping.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 54 KiB

Двоичные данные
Flutter/maps/images/shape-sublayer/range_color_mapping.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 54 KiB

Просмотреть файл

@ -249,6 +249,73 @@ class Model {
N>
* Refer the [`MapLegend`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLegend/MapLegend.html), for showing default legend.
## Title
You can add title to the legend using the `MapLegend.title` property.
N> It is applicable for both shape and bar legend.
{% tabs %}
{% highlight Dart %}
MapShapeSource _dataSource;
List<DataModel> _data;
@override
void initState() {
_data = const <DataModel>[
DataModel('Asia', 280),
DataModel('Europe', 120),
DataModel('Africa', 40),
DataModel('North America', 90),
DataModel('South America', 190),
DataModel('Australia', 210),
];
_dataSource = MapShapeSource.asset(
'assets/world_map.json',
shapeDataField: 'continent',
dataCount: _data.length,
primaryValueMapper: (int index) => _data[index].continent,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SfMaps(
layers: <MapShapeLayer>[
MapShapeLayer(
source: _dataSource,
legend: MapLegend(
MapElement.shape,
title: Text('Continents',
style:
TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
),
),
],
),
],
),
);
}
class DataModel {
const DataModel(this.continent, this.size);
final String continent;
final double size;
}
{% endhighlight %}
{% endtabs %}
![Legend title](images/legend/legend-title.png)
## Icon and text customization
The icons color of the legend is applied based on the colors returned from the [`MapShapeLayerDelegate.shapeColorValueMapper`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSource/shapeColorValueMapper.html) property and the text is taken from the [`shapeDataField`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSource/shapeDataField.html). It is possible to customize the legend icons color and texts using the [`MapColorMapper.color`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/color.html) and [`MapColorMapper.text`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/text.html) properties based on the [`MapColorMapper.value`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/value.html) or [`MapColorMapper.from`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/from.html) and [`MapColorMapper.to`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/to.html) properties.
@ -319,6 +386,82 @@ class Model {
![Legend text customization](images/legend/legend-text-customization.png)
## First segment label customization
You can customize the first segment label of the legend using the [`MapColorMapper.text`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/text.html) property with curly braces. The first curly brace value will be applied as segment start label and the next curly brace value will be applied as segment end label. By default, the [`MapColorMapper.from`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/from.html) value is placed at the starting position of first segment and the [`MapColorMapper.to`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/to.html) value is placed at the ending position of the first segment.
{% tabs %}
{% highlight Dart %}
List<DataModel> _data;
MapShapeSource _shapeSource;
@override
void initState() {
_data = <DataModel>[
DataModel('India', 280),
DataModel('United States of America', 190),
DataModel('Kazakhstan', 37),
DataModel('Italy', 201),
DataModel('Korea', 512),
DataModel('Japan', 335),
DataModel('Cuba', 103),
DataModel('China', 148)
];
_shapeSource = MapShapeSource.asset("assets/world_map.json",
shapeDataField: "name",
dataCount: _data.length,
primaryValueMapper: (int index) => _data[index].country,
shapeColorValueMapper: (int index) => _data[index].density,
shapeColorMappers: [
MapColorMapper(from: 0, to: 100, color: Colors.red, text: '{>0.0},{100.0}'),
MapColorMapper(from: 101, to: 200, color: Colors.green),
MapColorMapper(from: 201, to: 300, color: Colors.blue),
MapColorMapper(from: 301, to: 400, color: Colors.orange),
MapColorMapper(from: 401, to: 500, color: Colors.teal),
MapColorMapper(from: 501, to: 600, color: Colors.deepPurple),
],
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: 350,
child: Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: SfMaps(
layers: [
MapShapeLayer(
source: _shapeSource,
legend: MapLegend.bar(
MapElement.shape,
),
)
],
),
),
),
),
);
}
class DataModel {
const DataModel(this.country, this.density);
final String country;
final double density;
}
{% endhighlight %}
{% endtabs %}
![First label customization](images/legend/first-label-customization.png)
## Position
You can position the legend items in different directions using the [`MapLegend.position`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLegend/position.html) property. The default value of the [`position`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapLegend/position.html) property is `MapLegendPosition.top`. The possible values are `left`, `right`, `top`, and `bottom`.

Просмотреть файл

@ -171,6 +171,154 @@ return Scaffold(
![Shape sublayer color](images/shape-sublayer/sublayer-color.png)
## Equal color mapping
You can apply color to the sublayer shape by comparing a value that returns from the [`shapeColorValueMapper`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSource/shapeColorValueMapper.html) with the [`MapColorMapper.value`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/value.html). For the matched values, the [`MapColorMapper.color`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/color.html) will be applied to the respective shapes.
{% tabs %}
{% highlight Dart %}
List<Model> data;
MapShapeSource sublayerDataSource;
MapShapeSource shapeDataSource;
@override
void initState() {
data = <Model>[
Model('Algeria', "Low"),
Model('Nigeria', "High"),
Model('Libya', "High"),
];
shapeDataSource = MapShapeSource.asset(
"assets/world_map.json",
shapeDataField: 'continent',
);
sublayerDataSource = MapShapeSource.asset(
"assets/africa.json",
shapeDataField: "name",
dataCount: data.length,
primaryValueMapper: (int index) {
return data[index].state;
},
shapeColorValueMapper: (int index) {
return data[index].storage;
},
shapeColorMappers: [
MapColorMapper(value: "Low", color: Colors.red),
MapColorMapper(value: "High", color: Colors.green)
],
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: SfMaps(
layers: <MapShapeLayer>[
MapShapeLayer(
source: shapeDataSource,
sublayers: [
MapShapeSublayer(
source: sublayerDataSource,
)
],
),
],
),
),
);
}
class Model {
const Model(this.state, this.storage);
final String state;
final String storage;
}
{% endhighlight %}
{% endtabs %}
![Equal color mapping](images/shape-sublayer/equal_color_mapping.png)
## Range color mapping
You can apply color to the sublayer shape based on whether the value returned from [`shapeColorValueMapper`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSource/shapeColorValueMapper.html) falls within the [`MapColorMapper.from`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/from.html) and [`MapColorMapper.to`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/to.html). Then, the [`MapColorMapper.color`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapColorMapper/color.html) will be applied to the respective shapes.
{% tabs %}
{% highlight Dart %}
List<Model> data;
MapShapeSource sublayerDataSource;
MapShapeSource shapeDataSource;
@override
void initState() {
data = <Model>[
Model('Algeria', 196),
Model('Nigeria', 280),
Model('Libya', 45),
];
shapeDataSource = MapShapeSource.asset(
"assets/world_map.json",
shapeDataField: 'continent',
);
sublayerDataSource = MapShapeSource.asset(
"assets/africa.json",
shapeDataField: "name",
dataCount: data.length,
primaryValueMapper: (int index) {
return data[index].state;
},
shapeColorValueMapper: (int index) => data[index].count,
shapeColorMappers: [
MapColorMapper(from: 0, to: 100, color: Colors.red),
MapColorMapper(from: 101, to: 300, color: Colors.green)
],
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: SfMaps(
layers: <MapShapeLayer>[
MapShapeLayer(
source: shapeDataSource,
sublayers: [
MapShapeSublayer(
source: sublayerDataSource,
)
],
),
],
),
),
);
}
class Model {
const Model(this.state, this.count);
final String state;
final double count;
}
{% endhighlight %}
{% endtabs %}
![Range color mapping](images/shape-sublayer/range_color_mapping.png)
## Enable data labels and its customization
You can enable data labels to the shape sublayer using the [`showDataLabels`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSublayer/showDataLabels.html) property and customize the data labels text using the [`dataLabelMapper`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapShapeSource/dataLabelMapper.html) property.

Просмотреть файл

@ -15,12 +15,14 @@ The tile layer renders the tiles returned from web map tile services such as Bin
The [`MapTileLayer`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer-class.html) needs to be added in the [layers](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/SfMaps/layers.html) collection in [`SfMaps`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/SfMaps-class.html). The URL of the providers must be set in the [`MapTileLayer.urlTemplate`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer/urlTemplate.html) property.
The [`urlTemplate`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer/urlTemplate.html) property accepts the URL in WMTS format i.e. {z} — zoom level, {x} and {y} — tile coordinates. This URL might vary slightly depends on the providers. The formats can be,
The [`urlTemplate`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer/urlTemplate.html) property accepts the URL in [`WMTS`](https://en.wikipedia.org/wiki/Web_Map_Tile_Service) format i.e. {z} — zoom level, {x} and {y} — tile coordinates. This URL might vary slightly depends on the providers. The formats can be,
https://example_provider/{z}/{x}/{y}.png,
https://example_provider/z={z}/x={x}/y={y}.png,
https://example_provider/z={z}/x={x}/y={y}.png?key=subscription_key, etc. We will replace the {z}, {x}, {y} internally based on the current focal latitude and longitude and the zoom level.
https://example_provider/z={z}/x={x}/y={y}.png?key=subscription_key, etc.
Some of the providers may need subscription key. Please include them in the [`urlTemplate`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer/urlTemplate.html) itself as mentioned in the above example. Please note that the format may vary between each map providers. You can check the exact URL format needed for the providers on their official websites.
We will replace the {z}, {x}, {y} internally based on the current focal latitude and longitude and the zoom level.
N> Some of the providers may need subscription key. Please include them in the [`urlTemplate`](https://pub.dev/documentation/syncfusion_flutter_maps/latest/maps/MapTileLayer/urlTemplate.html) itself as mentioned in the above example. Please note that the format may vary between each map providers. You can check the exact URL format needed for the providers on their official websites.
## Adding OSM/OpenStreetMap

Просмотреть файл

@ -727,3 +727,70 @@ Widget build(BuildContext context) {
{% endtabs %}
![Circle tooltip customization](../images/circle-layer/circle-tooltip-customization.png)
## Inverted circle
You can apply color to the inverted circle by initializing the `MapCircleLayer.inverted` constructor. The inner circle color is transparent and the outer portion of the circle covered by an overlay color.
You can customize the inverted circle using the following properties:
* **Stroke color** - Change the stroke color of the circle using the `strokeColor` property.
* **Stroke width** - Change the stroke width of the circle using the `strokeWidth` property. The default value of the `strokeWidth` property is `1`.
* **Overlay color** - Change the outer portion color of the circle using the `color` property.
* **Tooltip** - You can enable tooltip for the inverted circle using the `tooltipBuilder` property.
* **Animation** - You can apply animation for the inverted circle using the `animation` property and able to customize the animation curve and duration.
N> It is applicable for both the tile layer and shape layer.
I> The individual circle customization like `MapCircle.color`, `MapCircle.strokeColor` and `MapCircle.strokeWidth` are not supported for the inverted circle.
{% tabs %}
{% highlight Dart %}
MapZoomPanBehavior zoomPanBehavior;
@override
void initState() {
zoomPanBehavior = MapZoomPanBehavior(zoomLevel: 4, maxZoomLevel: 15);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfMaps(
layers: [
MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialFocalLatLng: MapLatLng(-14.2350, -51.9253),
sublayers: [
MapCircleLayer.inverted(
circles: List<MapCircle>.generate(
1,
(int index) {
return MapCircle(
center: MapLatLng(-14.2350, -51.9253),
radius: 50,
);
},
).toSet(),
color: Colors.black.withOpacity(0.3),
strokeColor: Colors.red,
strokeWidth: 1,
),
],
zoomPanBehavior: zoomPanBehavior,
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
![Inverted circle](../images/circle-layer/inverted-circle.png)
N>
* Refer `tooltip` section, for adding and customizing tooltip to the inverted circle.
* Refer `animation` section, for applying animation to the inverted circle.

Просмотреть файл

@ -540,3 +540,73 @@ class PolygonModel {
{% endhighlight %}
{% endtabs %}
## Inverted polygon
You can apply color to the inverted polygon by initializing the `MapPolygonLayer.inverted` constructor. The inner polygon color is transparent and the outer portion of the polygon covered by an overlay color.
You can customize the inverted polygon using the following properties:
* **Stroke color** - Change the stroke color of the polygon using the `strokeColor` property.
* **Stroke width** - Change the stroke width of the polygon using the `strokeWidth` property. The default value of the `strokeWidth` property is `1`.
* **Overlay color** - Change the outer portion color of the polygon using the `color` property.
* **Tooltip** - You can enable tooltip for the inverted polygon using the `tooltipBuilder` property.
N> It is applicable for both the tile layer and shape layer.
I> The individual polygon customization like `MapPolygon.color`, `MapPolygon.strokeColor` and `MapPolygon.strokeWidth` are not supported for the inverted polygon.
{% tabs %}
{% highlight Dart %}
MapZoomPanBehavior zoomPanBehavior;
List<MapLatLng> _polygon;
@override
void initState() {
_polygon = <MapLatLng>[
MapLatLng(27.6648, -81.5158),
MapLatLng(32.3078, -64.7505),
MapLatLng(18.2208, -66.5901),
];
zoomPanBehavior = MapZoomPanBehavior(zoomLevel: 4);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfMaps(
layers: [
MapTileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
initialFocalLatLng: MapLatLng(25.0119, -73.4842),
sublayers: [
MapPolygonLayer.inverted(
polygons: List<MapPolygon>.generate(
1,
(int index) {
return MapPolygon(
points: _polygon,
);
},
).toSet(),
color: Colors.black.withOpacity(0.3),
strokeColor: Colors.red,
strokeWidth: 1,
),
],
zoomPanBehavior: zoomPanBehavior,
),
],
),
);
}
{% endhighlight %}
{% endtabs %}
![Inverted polgon](../images/polygon-layer/inverted-polygon.png)
N> Refer `tooltip` section, for adding and customizing tooltip to the inverted polygon.

Просмотреть файл

@ -1,14 +1,14 @@
---
layout: post
title: Getting started for Syncfusion Flutter PDF Viewer | Syncfusion
description: This section explains about the steps required to add the PDF Viewer widget and its elements such as scroll head, scroll status and page navigation dialog.
description: This section explains about the steps required to add the PDF Viewer plugin and its elements such as scroll head, scroll status and page navigation dialog.
platform: Flutter
control: SfPdfViewer
documentation: ug
---
# Getting Started with Flutter PDF Viewer (SfPdfViewer)
This section explains the steps required to add the [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) widget and its features. This section covers only the basic features needed to get started with the Syncfusion Flutter PDF Viewer widget.
This section explains the steps required to add the [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) plugin and its features. This section covers only the basic features needed to get started with the Syncfusion Flutter PDF Viewer plugin.
## Add the Flutter PDF Viewer to an application
Create a simple project using the instructions given in the [Getting Started with your first Flutter app](https://flutter.dev/docs/get-started/test-drive?tab=vscode#create-app) documentation.
@ -27,6 +27,19 @@ syncfusion_flutter_pdfviewer: ^xx.x.xx
N> Here **xx.x.xx** denotes the current version of [`Syncfusion Flutter PDF Viewer`](https://pub.dev/packages/syncfusion_flutter_pdfviewer/versions) package.
For web platform, we have used [PdfJs](https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.min.js) for rendering the PDF pages, so the script file must be referred to in your `web/index.html` file.
On your `web/index.html` file, add the following `script` tags, somewhere in the `body` of the document:
```html
<script src="//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.min.js"></script>
<script type="text/javascript">
pdfjsLib.GlobalWorkerOptions.workerSrc = "//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.4.456/pdf.worker.min.js";
</script>
```
**Get packages**
Run the following command to get the required packages.
@ -154,6 +167,44 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
## Get the current scroll offset position
The `SfPdfViewer` allows you to get the current scroll offset position using the [scrollOffset](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfViewerController/scrollOffset.html) property. The following code example explains the same.
{% tabs %}
{% highlight Dart %}
final PdfViewerController _pdfViewerController=PdfViewerController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Syncfusion Flutter PDF Viewer'),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_drop_down_circle,
color: Colors.white,
),
onPressed: () {
_pdfViewerController.jumpToPage(3);
print( _pdfViewerController.scrollOffset.dy);
print( _pdfViewerController.scrollOffset.dx);
},
),
],
),
body: SfPdfViewer.network(
'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
controller: _pdfViewerController,
),
);
}
{% endhighlight %}
{% endtabs %}
## Customize the space being displayed between the PDF pages
By default, the `SfPdfViewer` displays the spacing between the PDF pages with the value of **4 pixels**. You can customize the space being displayed using the [pageSpacing](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer/pageSpacing.html) property. The following code example explains the same.
@ -193,6 +244,8 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
N> On a desktop or mobile web browser, this `canShowScrollHead` property will have no effect since the scroll head will not be displayed there.
## Customize the visibility of page navigation dialog
By default, the page navigation dialog will be displayed when the scroll head is tapped. You can customize the visibility of the page navigation dialog using the [canShowPaginationDialog](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer/canShowPaginationDialog.html) property. The following code example explains the same.
@ -212,6 +265,8 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
N> On a desktop or mobile web browser, this `canShowPaginationDialog` property will have no effect since the pagination dialog will not be displayed there.
## Callbacks
The `SfPdfViewer` loading supports the [PdfDocumentLoadedCallback](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfDocumentLoadedCallback.html) and [PdfDocumentLoadFailedCallback](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfDocumentLoadFailedCallback.html) to notify whether the document has been loaded completely or not.

Просмотреть файл

@ -0,0 +1,55 @@
---
layout: post
title: Interaction modes of Syncfusion Flutter PDF Viewer | Syncfusion
description: This section explains about how to enable the different interaction modes in the Flutter PDF Viewer plugin.
platform: Flutter
control: SfPdfViewer
documentation: ug
---
# Interaction modes in Flutter PDF Viewer (SfPdfViewer)
The [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) supports following interaction modes for easy interaction with the PDF documents on a desktop web browser,
* selection
* pan
N> On a touch device, setting the `[interactionMode](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer/interactionMode.html)` property to `selection` mode will have no effect since panning is the default mode for scrolling and the selection is made by long pressing a word in the document.
## Selection mode
By default, `selection` interaction mode will be enabled on a desktop web browser and allows users to select and copy text from the PDF files. This is helpful for copying and sharing text content. Refer to the following code to enable the `selection` mode in `SfPdfViewer`.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SfPdfViewer.network(
'http://ebooks.syncfusion.com/downloads/flutter-succinctly/flutter-succinctly.pdf',
interactionMode: PdfInteractionMode.selection)));
}
{% endhighlight %}
{% endtabs %}
## Pan mode
In `pan` mode, the dragging and scrolling of the pages can be performed in any direction using mouse and touch interactions on a desktop web browser, but the text selection cannot be performed. Refer to the following code to enable the `pan` mode in `SfPdfViewer`.
{% tabs %}
{% highlight Dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SfPdfViewer.network(
'http://ebooks.syncfusion.com/downloads/flutter-succinctly/flutter-succinctly.pdf',
interactionMode: PdfInteractionMode.pan)));
}
{% endhighlight %}
{% endtabs %}

Просмотреть файл

@ -74,6 +74,8 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
N> On a desktop web browser, this `enableDoubleTapZooming` property will have no effect with mouse interaction.
## Callbacks
The `SfPdfViewer` magnification supports the [PdfZoomLevelChangedCallback](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfZoomLevelChangedCallback.html) to notify the zoom level changes.

Просмотреть файл

@ -1,7 +1,7 @@
---
layout: post
title: Overview of Syncfusion Flutter PDF Viewer | Syncfusion
description: Syncfusion Flutter PDF Viewer has highly interactive and customizable features such as magnification, virtual scrolling, page navigation & bookmark navigation.
description: Flutter PDF Viewer plugin has highly interactive and customizable features such as magnification, text selection, search, bookmark and page navigation.
platform: Flutter
control: SfPdfViewer
documentation: ug
@ -9,7 +9,7 @@ documentation: ug
# Overview of Syncfusion Flutter PDF Viewer
The Syncfusion Flutter PDF Viewer widget lets you view PDF documents seamlessly and efficiently in Android and iOS platforms. It has highly interactive and customizable features such as magnification, virtual scrolling, page navigation, and bookmark navigation.
The Syncfusion Flutter PDF Viewer plugin lets you view PDF documents seamlessly and efficiently in Android, iOS and Web platforms. It has highly interactive and customizable features such as magnification, virtual scrolling, page navigation, text selection, text search, and bookmark navigation.
## Key Features

Просмотреть файл

@ -9,9 +9,11 @@ documentation: ug
# Text selection in Flutter PDF Viewer (SfPdfViewer)
By default, the [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) allows you to select a text in the PDF page by long pressing on it, which in turn displays the selection handles or bubbles at the top-left and bottom-right corners of its bounds. Then, you can use the left handle to select the text at the left and top, and the right handle to select the text at the right and bottom directions.
On a touch device, the [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) allows you to select a text in the PDF page by long pressing on it, which in turn displays the selection handles or bubbles at the top-left and bottom-right corners of its bounds. Then, you can use the left handle to select the text at the left and top, and the right handle to select the text at the right and bottom directions.
N> The images in the document will not be selected and also, the multiple page text selection is not supported for now.
And, on a desktop web browser, the text selection can also be performed using mouse dragging with `[selection](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfInteractionMode-class.html)` interaction mode enabled.
N> The images in the document will not be selected and, the multiple page text selection is not supported for now.
## Enable or disable text selection
@ -32,9 +34,11 @@ Widget build(BuildContext context) {
{% endhighlight %}
{% endtabs %}
N> On a desktop web browser, this `enableTextSelection` property will have no effect with `[pan](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/PdfInteractionMode-class.html)` interaction mode.
## Customize the text selection and its handle color
The [SfPdfViewer] allows you to customize the color used for text selection and its handle based on your requirements. The properties [selectionColor](https://api.flutter.dev/flutter/material/TextSelectionThemeData/selectionColor.html) and [selectionHandleColor](https://api.flutter.dev/flutter/material/TextSelectionThemeData/selectionHandleColor.html) of the [TextSelectionThemeData](https://api.flutter.dev/flutter/material/TextSelectionThemeData-class.html) class can be used to customize them. The following code example explains the same.
The [SfPdfViewer](https://pub.dev/documentation/syncfusion_flutter_pdfviewer/latest/pdfviewer/SfPdfViewer-class.html) allows you to customize the color used for text selection and its handle based on your requirements. The properties [selectionColor](https://api.flutter.dev/flutter/material/TextSelectionThemeData/selectionColor.html) and [selectionHandleColor](https://api.flutter.dev/flutter/material/TextSelectionThemeData/selectionHandleColor.html) of the [TextSelectionThemeData](https://api.flutter.dev/flutter/material/TextSelectionThemeData-class.html) class can be used to customize them. The following code example explains the same.
{% tabs %}
{% highlight Dart %}

Просмотреть файл

@ -313,8 +313,8 @@ PdfTextElement element =
element.brush = PdfBrushes.white;
//Draws the heading on the page
PdfLayoutResult result =
element.draw(page: page, bounds: Rect.fromLTWH(10, bounds.top + 8, 0, 0));
PdfLayoutResult result = element.draw(
page: page, bounds: Rect.fromLTWH(10, bounds.top + 8, 0, 0))!;
String currentDate = 'DATE ' + DateFormat.yMMMd().format(DateTime.now());
//Measures the width of the text to place it in the correct location
@ -336,20 +336,20 @@ element = PdfTextElement(
style: PdfFontStyle.bold));
element.brush = PdfSolidBrush(PdfColor(126, 155, 203));
result = element.draw(
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 25, 0, 0));
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 25, 0, 0))!;
PdfFont timesRoman = PdfStandardFont(PdfFontFamily.timesRoman, 10);
element = PdfTextElement(text: 'Victuailles en stock ', font: timesRoman);
element.brush = PdfBrushes.black;
result = element.draw(
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 10, 0, 0));
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 10, 0, 0))!;
element = PdfTextElement(
text: '2, rue du Commerce, Lyon, France ', font: timesRoman);
element.brush = PdfBrushes.black;
result = element.draw(
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 10, 0, 0));
page: page, bounds: Rect.fromLTWH(10, result.bounds.bottom + 10, 0, 0))!;
//Draws a line at the bottom of the address
graphics.drawLine(
@ -463,7 +463,7 @@ PdfLayoutResult gridResult = grid.draw(
page: page,
bounds: Rect.fromLTWH(0, result.bounds.bottom + 20,
graphics.clientSize.width, graphics.clientSize.height - 100),
format: layoutFormat);
format: layoutFormat)!;
gridResult.page.graphics.drawString(
'Grand Total : \$386.91', subHeadingFont,

Просмотреть файл

@ -288,7 +288,7 @@ The following code example explains how to add the Text Web Link annotation in a
PdfDocument document = PdfDocument();
//Adds a new PDF page
PdfPage page = document.pages.add()
PdfPage page = document.pages.add();
//Creates a new text web link annotation
PdfTextWebLink textWebLink = PdfTextWebLink(
@ -314,7 +314,7 @@ document.dispose();
Annotations can be flattened by removing the existing annotation and replacing it with the graphics objects that would resemble the annotation and it cannot be edited.
This can be achieved by enabling the Flatten property. Please refer to the sample for flattening all the annotations in the PDF document.
This can be achieved by enabling the flattenAllAnnotations method . Please refer to the sample for flattening all the annotations in the PDF document.
{% highlight dart %}
@ -332,7 +332,7 @@ for (int i = 0; i < document.pages.count; i++) {
PdfAnnotationCollection annotationCollection = page.annotations;
//Flattens all the annotations in the page
annotationCollection.flatten = true;
annotationCollection.flattenAllAnnotations();
}
//Saves the document
@ -370,7 +370,7 @@ for (int i = 0; i < document.pages.count; i++) {
if (annotation is PdfRectangleAnnotation) {
//Flattens the rectangle annotation
annotation.flatten = true;
annotation.flatten();
}
}
}
@ -397,7 +397,8 @@ PdfDocument document =
PdfPage page = document.pages[0];
//Gets the first annotation and modify the properties
PdfRectangleAnnotation annotation = page.annotations[0];
PdfRectangleAnnotation annotation =
page.annotations[0] as PdfRectangleAnnotation;
annotation.border = PdfAnnotationBorder(4);
annotation.bounds = Rect.fromLTWH(300, 300, 100, 100);
annotation.color = PdfColor(0, 0, 255);

Просмотреть файл

@ -0,0 +1,230 @@
---
layout: post
title: Document of Syncfusion Flutter PDF
description: Learn how to sign PDF document internally by using certificate with private keys or externally by using the digital signature created from various sources.
platform: flutter
control: PDF
documentation: ug
---
# Working with Digital Signature
Flutter PDF allows you to add a digital signature to the PDF document. You can sign the PDF document internally by using a certificate with private keys or externally by using the digital signature created from various sources such as cloud services like DigitalSign.
## Adding a digital signature
To add a digital signature, you need a certificate with private keys. The following code example explains how to add a digital signature to the PDF document.
{% highlight dart %}
//Creates a new PDF document.
PdfDocument document = PdfDocument();
//Adds a new page.
PdfPage page = document.pages.add();
//Creates a digital signature and sets signature information.
PdfSignatureField field = PdfSignatureField(page, 'signature',
bounds: Rect.fromLTWH(0, 0, 200, 100),
signature: PdfSignature(
//Creates a certificate instance from the PFX file with a private key.
certificate:
PdfCertificate(File('PDF.pfx').readAsBytesSync(), 'password123'),
contactInfo: 'johndoe@owned.us',
locationInfo: 'Honolulu, Hawaii',
reason: 'I am author of this document.',
digestAlgorithm: DigestAlgorithm.sha256,
cryptographicStandard: CryptographicStandard.cms));
//Add a signature field to the form.
document.form.fields.add(field);
//Save and dispose the PDF document.
File('Output.pdf').writeAsBytes(document.save());
document.dispose();
{% endhighlight %}
## Signing an existing document
You can load the signature field from the existing PDF document and add a certificate to the document as follows,
{% highlight dart %}
//Loads an existing PDF document.
PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Gets the first signature field of the PDF document.
PdfSignatureField field = document.form.fields[0] as PdfSignatureField;
//Creates a digital signature and sets the signature information.
field.signature = PdfSignature(
//Creates a certificate instance from the PFX file with a private key.
certificate:
PdfCertificate(File('PDF.pfx').readAsBytesSync(), 'password123'),
contactInfo: 'johndoe@owned.us',
locationInfo: 'Honolulu, Hawaii',
reason: 'I am author of this document.',
digestAlgorithm: DigestAlgorithm.sha512,
cryptographicStandard: CryptographicStandard.cades);
//Save and dispose the PDF document.
File('Output.pdf').writeAsBytes(document.save());
document.dispose();
{% endhighlight %}
## Adding a signature appearance
You can customize the appearance of the signature field by using the [`appearance`](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfSignatureField/appearance.html) property in [`PdfSignatureField`](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfSignatureField-clas.html) as follows,
{% highlight dart %}
//Loads an existing PDF document.
PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Gets the first signature field of the PDF document.
PdfSignatureField field = document.form.fields[0] as PdfSignatureField;
//Creates a digital signature.
field.signature = PdfSignature(
//Creates a certificate instance from the PFX file with a private key.
certificate:
PdfCertificate(File('PDF.pfx').readAsBytesSync(), 'password123'));
//Gets the signature field appearance graphics.
PdfGraphics graphics = field.appearance.normal.graphics;
//Draws the signature image.
graphics.drawImage(
PdfBitmap(File('image.jpg').readAsBytesSync()), field.bounds);
//Save and dispose the PDF document.
File('Output.pdf').writeAsBytes(document.save());
document.dispose();
{% endhighlight %}
## Externally sing a PDF document
You can sign the PDF document from an external digital signature created from various sources such as cloud services like DigitalSign.
The following code example shows how to sign the PDF document from an external signature.
{% highlight dart %}
//Loads an existing PDF document.
PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Gets the first signature field of the PDF document.
PdfSignatureField field = document.form.fields[0] as PdfSignatureField;
//Creates a digital signature.
field.signature = PdfSignature()
..addExternalSigner(
//Creates an external signer.
PdfExternalSigner(),
//Loads a public certificate to generate message digest for signing.
[File('certificate.cer').readAsBytesSync()]);
//Save and dispose the PDF document.
File('Output.pdf').writeAsBytes(document.save());
document.dispose();
{% endhighlight %}
You can create an external digital signature with the [`x509`](https://pub.dev/packages/x509) package by using the following steps:
**Add dependency**
Add this to your package's pubspec.yaml file.
{% highlight dart %}
dependencies:
x509: ^0.1.4
{% endhighlight %}
**Import package**
{% highlight dart %}
import 'package:x509/x509.dart' as x509;
{% endhighlight %}
You can compute the signed message digest by using the x509 package with a corresponding private key of the public certificate.
{% highlight dart %}
//Class for singing a PDF document externally.
class PdfExternalSigner implements IPdfExternalSigner {
//Hash algorithm.
@override
String get hashAlgorithm => 'SHA-256';
//Sign message digest.
@override
SignerResult sign(List<int> message) {
final pem = File('privatekey.pem').readAsBytesSync();
final x509.KeyPair keyPair =
x509.parsePem(String.fromCharCodes(pem)).single;
final privateKey = keyPair.privateKey as x509.RsaPrivateKey;
final signer = privateKey.createSigner(x509.algorithms.signing.rsa.sha256);
final x509.Signature signed = signer.sign(message);
return SignerResult(signed.data.toList());
}
}
{% endhighlight %}
## Adding multiple digital signature
You can apply one or more digital signatures to a PDF document. The following code example shows how to add multiple signatures to the PDF document.
{% highlight dart %}
//Loads an existing PDF document.
PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Gets the first signature field of the PDF document.
PdfSignatureField field = document.form.fields[0] as PdfSignatureField;
//Creates a digital signature and sets signature information.
field.signature = PdfSignature(
//Creates a certificate instance from the PFX file with a private key.
certificate:
PdfCertificate(File('PDF.pfx').readAsBytesSync(), 'password123'),
contactInfo: 'johndoe@owned.us',
locationInfo: 'Honolulu, Hawaii',
reason: 'I am author of this document.',
digestAlgorithm: DigestAlgorithm.sha512,
cryptographicStandard: CryptographicStandard.cades);
//Save and load the PDF document.
document = PdfDocument(inputBytes: document.save());
//Gets the second signature field of the PDF document.
field = document.form.fields[1] as PdfSignatureField;
//Creates a digital signature and sets signature information.
field.signature = PdfSignature(
//Creates a certificate instance from the PFX file with a private key.
certificate: PdfCertificate(
File('Certificate.pfx').readAsBytesSync(), 'password123'),
contactInfo: 'johndoe@owned.us',
locationInfo: 'Honolulu, Hawaii',
reason: 'I am author of this document.',
digestAlgorithm: DigestAlgorithm.sha256,
cryptographicStandard: CryptographicStandard.cms);
//Save and dispose the PDF document.
File('Output.pdf').writeAsBytes(document.save());
document.dispose();
{% endhighlight %}

Просмотреть файл

@ -116,7 +116,7 @@ PDF [`sections`](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf
PdfDocument document = PdfDocument();
//Add a section to PDF document
PdfSection section = document.sections.add();
PdfSection section = document.sections!.add();
//Draw the text by section page graphics
section.pages.add().graphics.drawString(

Просмотреть файл

@ -37,49 +37,41 @@ PdfTextElement textElement = PdfTextElement(
//Draw the paragraph text on page and maintain the position in PdfLayoutResult
PdfLayoutResult layoutResult = textElement.draw(
page: page,
bounds: Rect.fromLTWH(
0, 150, page.getClientSize().width, page.getClientSize().height));
bounds: Rect.fromLTWH(0, 150, page.getClientSize().width,
page.getClientSize().height))!;
//Assign header text to PdfTextElement
textElement.text = 'Top 5 sales stores';
//Assign standard font to PdfTextElement
textElement.font =
PdfStandardFont(PdfFontFamily.helvetica, 14, style: PdfFontStyle.bold);
textElement.font = PdfStandardFont(PdfFontFamily.helvetica, 14,
style: PdfFontStyle.bold);
//Draw the header text on page, below the paragraph text with a height gap of 20 and maintain the position in PdfLayoutResult
layoutResult = textElement.draw(
page: page,
bounds: Rect.fromLTWH(0, layoutResult.bounds.bottom + 20, 0, 0));
bounds: Rect.fromLTWH(0, layoutResult.bounds.bottom + 20, 0, 0))!;
//Initialize PdfGrid for drawing the table
PdfGrid grid = PdfGrid();
//Create data table and set it as a grid source
grid.dataSource = DataTable(
columns: [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
DataColumn(label: Text('Salary'))
],
rows: <DataRow>[
DataRow(cells: [
DataCell(Text('E01')),
DataCell(Text('Clay')),
DataCell(Text('\$10,000'))
]),
DataRow(cells: [
DataCell(Text('E02')),
DataCell(Text('Thomas')),
DataCell(Text('\$10,500'))
]),
DataRow(cells: [
DataCell(Text('E02')),
DataCell(Text('Simon')),
DataCell(Text('\$12,000'))
])
],
);
grid.columns.add(count: 3);
grid.headers.add(1);
PdfGridRow header = grid.headers[0];
header.cells[0].value = 'ID';
header.cells[1].value = 'Name';
header.cells[2].value = 'Salary';
PdfGridRow row1 = grid.rows.add();
row1.cells[0].value = 'E01';
row1.cells[1].value = 'Clay';
row1.cells[2].value = '\$10,000';
PdfGridRow row2 = grid.rows.add();
row2.cells[0].value = 'E02';
row2.cells[1].value = 'Thomas';
row2.cells[2].value = '\$10,500';
PdfGridRow row3 = grid.rows.add();
row3.cells[0].value = 'E02';
row3.cells[1].value = 'Simon';
row3.cells[2].value = '\$12,000';
//Draws the grid
grid.draw(

Просмотреть файл

@ -0,0 +1,832 @@
---
layout: post
title: Working with Forms | Syncfusion
description: This section explains how to create, fill, modify, read only and flatten form fields in the PDF document
platform: flutter
control: PDF
documentation: UG
---
# Working with PDF Forms
An interactive form sometimes referred to as an AcroForm is a collection of fields for gathering information. A PDF document can contain any number of fields appearing on any combination of pages, all that makes a single, globally interactive form spanning the entire document.
## Creating a new PDF form
Flutter PDF allows you to create and manage the form (AcroForm) in PDF documents by using the PdfForm class. The PdfFormFieldCollection class represents the entire field collection of the form.
### Adding the text box field
The [`PdfTextBoxField `](#) class is used to create a text box field in PDF forms.
The following code sample explains how to add a textbox field to a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a text box form field and add it to the document.
document.form.fields.add(PdfTextBoxField(
document.pages.add(), 'TextBox', Rect.fromLTWH(100, 20, 200, 20),
text: 'toType',
font: PdfStandardFont(PdfFontFamily.courier, 12),
isPassword: false,
spellCheck: true,
backColor: PdfColor(0, 255, 0),
borderColor: PdfColor(255, 0, 0),
foreColor: PdfColor(0, 0, 255)));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
The following code sample explains how to add the textbox to an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a text box form field and add it to the existing document.
document.form.fields.add(PdfTextBoxField(
document.pages[0], 'TextBox', Rect.fromLTWH(100, 20, 200, 20),
text: 'toType',
font: PdfStandardFont(PdfFontFamily.courier, 12),
isPassword: false,
spellCheck: true,
backColor: PdfColor(0, 255, 0),
borderColor: PdfColor(255, 0, 0),
foreColor: PdfColor(0, 0, 255)));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the combo box field
The PdfComboBoxField class is used to create a combo box field in PDF forms. You can add a list of items to the combo box by using the PdfListFieldItem class.
Please refer to the following code sample for adding the combo box in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a combo box form field and add it to the document.
document.form.fields.add(PdfComboBoxField(
document.pages.add(), 'comboBox', Rect.fromLTWH(100, 100, 200, 20),
font: PdfStandardFont(PdfFontFamily.helvetica, 12),
alignment: PdfTextAlignment.right,
editable: true,
selectedValue: 'Language 2',
items: [
PdfListFieldItem('Tamil', 'Language 1'),
PdfListFieldItem('English', 'Language 2'),
PdfListFieldItem('French', 'Language 3')
]));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the following code sample for adding the combo box in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a combo box form field and add it to the existing document.
document.form.fields.add(PdfComboBoxField(
document.pages[0], 'comboBox', Rect.fromLTWH(100, 100, 200, 20),
font: PdfStandardFont(PdfFontFamily.helvetica, 12),
alignment: PdfTextAlignment.right,
editable: true,
selectedValue: 'Language 2',
items: [
PdfListFieldItem('Tamil', 'Language 1'),
PdfListFieldItem('English', 'Language 2'),
PdfListFieldItem('French', 'Language 3')
]));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the radio button field
To create the radio button in the PDF forms, you can use the PdfRadioButtonListField class and you can create the radio button list items by using the PdfRadioButtonListItem class.
Please refer to the following code sample for adding the radio button in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a radio button form field and add it to the document.
document.form.fields.add(PdfRadioButtonListField(
document.pages.add(),
'Gender',
items: <PdfRadioButtonListItem>[
PdfRadioButtonListItem('Male', Rect.fromLTWH(100, 150, 35, 35),
style: PdfCheckBoxStyle.diamond,
highlightMode: PdfHighlightMode.push,
foreColor: PdfColor(0, 255, 0),
borderWidth: 3),
PdfRadioButtonListItem('Female', Rect.fromLTWH(100, 200, 35, 35),
highlightMode: PdfHighlightMode.outline,
backColor: PdfColor(153, 12, 102),
foreColor: PdfColor(0, 255, 0),
borderWidth: 2),
PdfRadioButtonListItem('Others', Rect.fromLTWH(100, 250, 35, 35),
highlightMode: PdfHighlightMode.outline,
borderStyle: PdfBorderStyle.dot,
borderColor: PdfColor(230, 0, 172),
foreColor: PdfColor(0, 255, 0),
borderWidth: 1)
],
selectedIndex: 0,
));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
The following code sample shows how to add the radio button in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a radio button form field and add it to the existing document.
document.form.fields.add(PdfRadioButtonListField(
document.pages[0],
'Gender',
items: <PdfRadioButtonListItem>[
PdfRadioButtonListItem('Male', Rect.fromLTWH(100, 150, 35, 35),
style: PdfCheckBoxStyle.diamond,
highlightMode: PdfHighlightMode.push,
foreColor: PdfColor(0, 255, 0),
borderWidth: 3),
PdfRadioButtonListItem('Female', Rect.fromLTWH(100, 200, 35, 35),
highlightMode: PdfHighlightMode.outline,
backColor: PdfColor(153, 12, 102),
foreColor: PdfColor(0, 255, 0),
borderWidth: 2),
PdfRadioButtonListItem('Others', Rect.fromLTWH(100, 250, 35, 35),
highlightMode: PdfHighlightMode.outline,
borderStyle: PdfBorderStyle.dot,
borderColor: PdfColor(230, 0, 172),
foreColor: PdfColor(0, 255, 0),
borderWidth: 1)
],
selectedIndex: 0,
));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Retrieving option values from the acroform radio button
The Flutter PDF supports retrieving values from the acroform radio button. The value property is used to get values of the PdfRadioButtonListItem instance.
The following code example shows how to get values from the acroform radio button.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get a radio button and select the item.
final PdfField radioButtonListField = document.form.fields[0];
if (radioButtonListField is PdfRadioButtonListField &&
radioButtonListField.selectedIndex != 1) {
radioButtonListField.selectedValue = radioButtonListField.items[1].value;
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the list box field
You can create the list box field in PDF forms using the PdfListBoxField class.
Please refer to the following code sample for adding the list box field in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a list form field and add it to the document.
document.form.fields.add(PdfListBoxField(
document.pages.add(), 'listBox', Rect.fromLTWH(100, 100, 100, 50),
alignment: PdfTextAlignment.center,
items: [
PdfListFieldItem('Tamil', 'Language 1'),
PdfListFieldItem('English', 'Language 2'),
PdfListFieldItem('French', 'Language 3')
],
selectedValues: [
'Tamil'
]));
document.form.setDefaultAppearance(true);
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the following code sample for adding the list box field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a list form field and add it to the existing document.
document.form.fields.add(PdfListBoxField(
document.pages[0], 'listBox', Rect.fromLTWH(100, 100, 100, 50),
alignment: PdfTextAlignment.center,
items: [
PdfListFieldItem('Tamil', 'Language 1'),
PdfListFieldItem('English', 'Language 2'),
PdfListFieldItem('French', 'Language 3')
],
selectedValues: [
'Tamil'
]));
document.form.setDefaultAppearance(true);
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the check Box field
You can create the check box field in PDF forms using the PdfCheckBoxField class.
Please refer to the following code sample for adding the check box field in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a list form field and add it to the document.
document.form.fields.add(PdfCheckBoxField(
document.pages.add(), 'CheckBox', Rect.fromLTWH(100, 200, 70, 45),
highlightMode: PdfHighlightMode.push,
borderStyle: PdfBorderStyle.dot,
borderColor: PdfColor(230, 0, 172),
backColor: PdfColor(153, 255, 102),
foreColor: PdfColor(255, 153, 0),
borderWidth: 1,
style: PdfCheckBoxStyle.diamond,
isChecked: true));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the following code sample for adding the check box field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a check box form field and add it to the existing document.
document.form.fields.add(PdfCheckBoxField(
document.pages.add(), 'CheckBox', Rect.fromLTWH(100, 200, 70, 45),
highlightMode: PdfHighlightMode.push,
borderStyle: PdfBorderStyle.dot,
borderColor: PdfColor(230, 0, 172),
backColor: PdfColor(153, 255, 102),
foreColor: PdfColor(255, 153, 0),
borderWidth: 1,
style: PdfCheckBoxStyle.diamond,
isChecked: true));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the signature field
You can add the signature field in PDF forms using the PdfSignatureField class.
Please refer to the following code sample for adding the signature field in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a signature form field and add it to the document.
document.form.fields.add(PdfSignatureField(document.pages.add(), 'Sign',
bounds: Rect.fromLTWH(100, 100, 100, 50)));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the following code sample for adding the signature field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a signature form field and add it to the existing document.
document.form.fields.add(PdfSignatureField(document.pages[0], 'Sign',
bounds: Rect.fromLTWH(100, 100, 100, 50)));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Adding the button field
To create button fields in PDF forms, you can use the PdfButtonField class.
The following code explains how to add the button field in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
// Create a list form field and add it to the document.
document.form.fields.add(PdfButtonField(
document.pages.add(), 'Button field', Rect.fromLTWH(10, 10, 130, 40),
text: 'submit',
font: PdfStandardFont(PdfFontFamily.timesRoman, 14),
backColor: PdfColor(0, 255, 120),
borderColor: PdfColor(255, 131, 0),
foreColor: PdfColor(201, 130, 255),
highlightMode: PdfHighlightMode.push,
borderWidth: 5,
borderStyle: PdfBorderStyle.dashed)
..addPrintAction());
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the following code sample for adding the button field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a PDF button form field and add it to the existing document.
document.form.fields.add(PdfButtonField(
document.pages[0], 'Button field', Rect.fromLTWH(10, 10, 130, 40),
text: 'submit',
font: PdfStandardFont(PdfFontFamily.timesRoman, 14),
backColor: PdfColor(0, 255, 120),
borderColor: PdfColor(255, 131, 0),
foreColor: PdfColor(201, 130, 255),
highlightMode: PdfHighlightMode.push,
borderWidth: 5,
borderStyle: PdfBorderStyle.dashed)
..addPrintAction());
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Set appearance to the PDF form fields
After filling the form fields in the PDF document, it may appear empty due to the absence of the appearance dictionary. By setting the setDefaultAppearance method in PdfForm class to false, you can create the appearance dictionary. By this, the text will be visible in all PDF Viewers.
The following code sample explains how to set appearance to the PDF form fields.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Set the default appearance.
document.form.setDefaultAppearance(true);
//Get the loaded form field and update text.
(document.form.fields[0] as PdfTextBoxField).text = 'Updated';
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Modifying the existing form field in a PDF document
You can modify an existing form field by getting the field from the PdfFormFieldCollection. You can retrieve a field from the field collection by index or by field name.
The following code sample explains how to modify an existing form field in a PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Get the loaded form field and modify the properties.
final PdfField field = document.form.fields[0];
if (field is PdfTextBoxField) {
field.multiline = false;
field.isPassword = false;
field.text = 'new Text';
field.maxLength = 0;
field.spellCheck = false;
field.defaultValue = 'new defaultValue';
field.scrollable = false;
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Retrieving or Modifying the fore, border, and back color of an existing form field
You can retrieve or modify the fore, border, and background color of existing form fields in a PDF document by using the foreColor, borderColor, and backColor properties of the respective form fields. The following code sample explains this.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Get the loaded form field.
final PdfField field = document.form.fields[0];
if (field is PdfTextBoxField) {
//Get colors from the loaded field.
PdfColor fColor = field.foreColor;
PdfColor brColor = field.borderColor;
PdfColor bColor = field.backColor;
//Set colors for the loaded field.
field.foreColor = brColor;
field.borderColor = bColor;
field.backColor = fColor;
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Filling form fields in an existing PDF Document
Flutter PDF allows you to fill the form fields using the PdfField class.
### Filling the text box field
You can fill a text box field using the text property of PdfTextBoxField class. The following code sample explains this.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Get the loaded form field and update text.
(document.form.fields[0] as PdfTextBoxField).text = 'Updated';
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Filling the combo box field
You can fill a combo box field using the selectedValue or selectedIndex properties of PdfLoadedComboBoxField class. Please refer to the following code sample to fill the combo box field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get a combo box field and select the item.
final PdfField comboBox = document.form.fields[0];
if (comboBox is PdfComboBoxField && comboBox.selectedIndex != 1) {
comboBox.selectedValue = comboBox.items[1].value;
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Filling the radio button field
You can fill a radio button field using the selectedValue or selectedIndex properties of PdfRadioButtonListField class. Please refer to the following code sample to fill the radio button field in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get a radio button and select the item.
final PdfField radioButtonListField = document.form.fields[0];
if (radioButtonListField is PdfRadioButtonListField &&
radioButtonListField.selectedIndex != 1) {
radioButtonListField.selectedValue = radioButtonListField.items[1].value;
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Filling the list box field
The following code sample explains how to fill the list box field in an existing PDF document using the selectedIndex property of PdfListBoxField class.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get a list box field and select the items.
(document.form.fields[0] as PdfListBoxField).selectedIndexes = [1,3];
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Filling the check box field
You can fill a check box field by enabling the checked property of PdfCheckBoxField class. Please refer to the following code sample to fill the check box field.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get and fill the check box field.
(document.form.fields[0] as PdfCheckBoxField).isChecked = true;
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
### Enumerate the form fields
All the form fields are maintained in the PdfFormFieldCollection class. You can enumerate the fields from this form field collection and fill them.
The following code example explains this.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Enumerates the form fields.
for (int i = 0; i < document.form.fields.count; i++) {
PdfField field = document.form.fields[i];
if (field is PdfTextBoxField) {
field.text = 'Updated';
}
}
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Removing editing capability of form fields
The form field editing or filling capabilities can be removed by either flattening the PDF document or marking the form or field as read-only.
Flutter PDF provides the support to flatten a form field by removing the existing form field and replacing it with graphical objects that would resemble the form field and cannot be edited.
Please refer to the sample for flattening the form fields in a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
//Flatten the whole form fields.
document.form.flattenAllFields();
// Create a textbox form field and add it to the document.
document.form.fields.add(PdfTextBoxField(
document.pages.add(), 'TextBox', Rect.fromLTWH(100, 20, 200, 20),
text: 'toType', isPassword: true, spellCheck: true));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
Please refer to the sample for flattening the form fields in an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Get and fill the text box field.
(document.form.fields[0] as PdfTextBoxField).text = 'Updated';
//Flatten the whole existing form fields.
document.form.flattenAllFields();
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
To prevent the user from changing the form field content, you can also use the readOnly property.
The following code sample explains how to set the readOnly property to a new PDF document.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
//Set the form as read-only.
document.form.readOnly = true;
// Create a text box form field and add it to the document.
document.form.fields.add(PdfTextBoxField(
document.pages.add(), 'TextBox', Rect.fromLTWH(100, 20, 200, 20),
text: 'toType', isPassword: true, spellCheck: true));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
The following code sample explains how to set the ReadOnly property to an existing PDF document.
{% highlight dart %}
//Loads an existing PDF document and set the form as read-only.
PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync())
..form.readOnly = true;
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Removing the form fields from the existing PDF document
You can remove the form fields from an existing PDF document using the remove or removeAt methods of PdfFormFieldCollection class.
The following code explains how to remove the form fields from the existing PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
//Get the loaded form.
PdfFormFieldCollection collection = document.form.fields;
//Remove the field at index 1.
collection.removeAt(1);
//Remove the field.
collection.remove(collection[0]);
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Auto naming of form fields
Flutter PDF supports auto naming of form fields in a PDF document while creating form fields with the same name. The fieldAutoNaming property of PdfForm is used to enable or disable auto naming of a form field.
While enabling this property, the field names are auto naming. If the fields are created using the same or common name, the created fields will act as an individual.
While disabling this property, the field names are not auto naming, and the created fields are saved in a single group. The same value will be referred in all the same name fields.
By default, the value is set to true. This is explained in the following code sample.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
//Enable the field auto naming.
document.form.fieldAutoNaming = true;
// Create a text box form field and add it to the document.
document.form.fields.add(PdfTextBoxField(
document.pages.add(), 'TextBox', Rect.fromLTWH(100, 20, 200, 20),
text: 'First name', spellCheck: true));
// Create a text box form field and add it to the document.
document.form.fields.add(PdfTextBoxField(
document.pages[0], 'TextBox', Rect.fromLTWH(100, 50, 200, 20),
text: 'Last name', spellCheck: true));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Adding an action to the form field
Flutter PDF provides support to add various actions to the form fields. The PdfFieldActions class is used to create the form field actions.
The following code example explains this.
{% highlight dart %}
//Create a new PDF document.
final PdfDocument document = PdfDocument();
//Create a button field with the filed actions and added to the form fields.
document.form.fields.add(PdfButtonField(document.pages.add(),
'Submit with actions', Rect.fromLTWH(100, 60, 50, 20),
actions: PdfFieldActions(
PdfAnnotationActions(
mouseEnter: PdfSubmitAction('https://www.google.co.in/',
dataFormat: SubmitDataFormat.pdf, submitCoordinates: true)),
keyPressed: PdfJavaScriptAction(
'app.alert(\"You are looking at Java script action of PDF \")'),
)));
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}
## Troubleshooting
Sometimes, Form fields may appear empty in an adobe reader due to the absence of the appearance dictionary. To resolve this, you need to enable the Adobe Reader default appearance by using the setDefaultAppearance method in PdfForm class.
The following code explains how to enable the default appearance in a new PDF document.
{% highlight dart %}
//Loads an existing PDF document.
final PdfDocument document =
PdfDocument(inputBytes: File('input.pdf').readAsBytesSync());
// Create a list form field and add it to the existing document.
document.form.fields.add(PdfListBoxField(
document.pages[0], 'listBox', Rect.fromLTWH(100, 100, 100, 50),
alignment: PdfTextAlignment.center,
items: [
PdfListFieldItem('Tamil', 'Language 1'),
PdfListFieldItem('English', 'Language 2'),
PdfListFieldItem('French', 'Language 3')
],
selectedValues: [
'Tamil'
]));
document.form.setDefaultAppearance(true);
//Save the PDF document.
File('output.pdf').writeAsBytesSync(document.save());
{% endhighlight %}

Просмотреть файл

@ -62,7 +62,7 @@ PdfDocumentLinkAnnotation docLink = PdfDocumentLinkAnnotation(
PdfDestination(document.pages.add(), Offset(10, 0)));
//Set the destination mode
docLink.destination.mode = PdfDestinationMode.fitToPage;
docLink.destination!.mode = PdfDestinationMode.fitToPage;
//Add the document link to the page
page.annotations.add(docLink);

Просмотреть файл

@ -90,7 +90,7 @@ PdfFont font = PdfStandardFont(PdfFontFamily.helvetica, 14);
//Section - 1
//Add section to the document
PdfSection section = document.sections.add();
PdfSection section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle0;
@ -102,7 +102,7 @@ section.pages.add().graphics.drawString('Rotated by 0 degrees', font,
//Section - 2
//Add section to the document
section = document.sections.add();
section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle90;
@ -114,7 +114,7 @@ section.pages.add().graphics.drawString('Rotated by 90 degrees', font,
//Section - 3
//Add section to the document
section = document.sections.add();
section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle180;
@ -126,7 +126,7 @@ section.pages.add().graphics.drawString('Rotated by 180 degrees', font,
//Section - 4
//Add section to the document
section = document.sections.add();
section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle270;
@ -170,7 +170,7 @@ You can [`rotate`](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/p
PdfDocument document = PdfDocument();
//Add section to the document
PdfSection section = document.sections.add();
PdfSection section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle180;
@ -182,7 +182,7 @@ section.pages.add().graphics.drawString(
brush: PdfBrushes.black, bounds: const Rect.fromLTWH(20, 20, 0, 0));
//Add section to the document
section = document.sections.add();
section = document.sections!.add();
//Create page settings to the section
section.pageSettings.rotate = PdfPageRotateAngle.rotateAngle270;

Просмотреть файл

@ -26,11 +26,11 @@ PdfDocument document = PdfDocument();
PdfTemplate template = PdfTemplate(100, 50);
//Draw a rectangle on the template graphics
template.graphics.drawRectangle(
template.graphics!.drawRectangle(
brush: PdfBrushes.burlyWood, bounds: Rect.fromLTWH(0, 0, 100, 50));
//Draw a string using the graphics of the template.
template.graphics.drawString(
template.graphics!.drawString(
'Hello World', PdfStandardFont(PdfFontFamily.helvetica, 14),
brush: PdfBrushes.black, bounds: Rect.fromLTWH(5, 5, 0, 0));

Просмотреть файл

@ -429,7 +429,8 @@ row2.cells[2].value = 'Rs: 1200';
//Draw grid on the page of PDF document and store the grid position in PdfLayoutResult
PdfLayoutResult result = grid.draw(
page: document.pages.add(), bounds: const Rect.fromLTWH(0, 0, 400, 300));
page: document.pages.add(),
bounds: const Rect.fromLTWH(0, 0, 400, 300)) as PdfLayoutResult;
//Create a second PdfGrid in the same page
PdfGrid grid2 = PdfGrid();

Просмотреть файл

@ -78,7 +78,7 @@ PdfDocument document =
//Extracts the text line collection from the document
final List<TextLine> textLine =
PdfTextExtractor(document).extractTextWithLine();
PdfTextExtractor(document).extractTextLines();
//Gets specific line from the collection
TextLine line = textLine[0];
@ -118,7 +118,7 @@ PdfDocument document =
//Extracts the text line collection from the page 2
final List<TextLine> textLine =
PdfTextExtractor(document).extractTextWithLine(startPageIndex: 1);
PdfTextExtractor(document).extractTextLines(startPageIndex: 1);
//Gets the specific line from the collection
TextLine line = textLine[0];
@ -164,7 +164,7 @@ PdfDocument document =
//Extracts the text line collection from the pages 2 to 3
final List<TextLine> textLine = PdfTextExtractor(document)
.extractTextWithLine(startPageIndex: 1, endPageIndex: 2);
.extractTextLines(startPageIndex: 1, endPageIndex: 2);
//Gets the specific line from the collection
TextLine line = textLine[0];

Просмотреть файл

@ -267,9 +267,9 @@ PdfLayoutFormat layoutFormat = PdfLayoutFormat(
//Draw the first paragraph
PdfLayoutResult result = textElement.draw(
page: page,
bounds: Rect.fromLTWH(
0, 0, page.getClientSize().width / 2, page.getClientSize().height),
format: layoutFormat);
bounds: Rect.fromLTWH(0, 0, page.getClientSize().width / 2,
page.getClientSize().height),
format: layoutFormat)!;
//Draw the second paragraph from the first paragraph end position
textElement.draw(

Просмотреть файл

@ -64,7 +64,7 @@ PdfGraphics graphics = document.pages.add().graphics;
PdfGraphicsState state = graphics.save();
graphics.setTransparency(0.25);
graphics.drawImage(
PdfBitmap.fromBase64String(alphaPng),
PdfBitmap.fromBase64String(imageData),
Rect.fromLTWH(
0, 0, graphics.clientSize.width, graphics.clientSize.height));
graphics.restore(state);

Просмотреть файл

@ -26,6 +26,10 @@ Data label can be added to a chart series by enabling the [`isVisible`](https://
* [`labelAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelAlignment.html) - used to align the Pyramid data label positions. The available options to customize the positions are [`outer`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`auto`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`top`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`bottom`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) and [`middle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html).
* [`borderRadius`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/borderRadius.html) - used to add the rounded corners to the data label shape.
* [`angle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/angle.html) - used to rotate the labels.
* [`offset`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/offset.html) - used to movethedata label vertically or horizontally from its position.
* [`showCumulativeValues`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/showCumulativeValues.html) - to show the cumulative values in stacked type series charts.
* [`labelIntersectAction`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelIntersectAction.html) - action on data labels intersection. The intersecting data labels can be hidden.
{% highlight dart %}
@ -55,6 +59,47 @@ Data label can be added to a chart series by enabling the [`isVisible`](https://
![DataLabel](images/datalabel/default_datalabel.png)
### Connector line
This feature is used to connect label and data point using a line. It can be enabled for [`PyramidSeries`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/PyramidSeries-class.html) chart type. The [`connectorLineSettings`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/connectorLineSettings.html) property used to customize the connector line.
* [`color`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorLineSettings/color.html) - used to change the color of the line
* [`width`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorLineSettings/width.html) - used to change the stroke thickness of the line
* [`length`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorLineSettings/length.html) - specifies the length of the connector line.
* [`type`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorLineSettings/type.html) - specifies the shape of connector line either [`curve`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorType-class.html) or [`line`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ConnectorType-class.html).
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: SfPyramidChart(
series: <PyramidSeries>[
PyramidSeries<ChartData, double>(
enableSmartLabels: true,
dataSource: chartData,
xValueMapper: (ChartData data, _) => data.x,
yValueMapper: (ChartData data, _) => data.y,
dataLabelSettings: DataLabelSettings(
isVisible: true,
labelPosition: ChartDataLabelPosition.outside,
connectorLineSettings: ConnectorLineSettings(
// Type of the connector line
type: ConnectorType.curve
)
)
)
]
)
)
)
);
}
{% endhighlight %}
### Label position
The [`labelAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) property is used to position the Pyramid chart type data labels at [`top`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`bottom`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`auto`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html), [`outer`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) and [`middle`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) position of the actual data point position. By default, labels are [`auto`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment-class.html) positioned. You can move the labels horizontally and vertically using OffsetX and OffsetY properties respectively.

Просмотреть файл

@ -48,6 +48,10 @@ The [`name`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/char
* [`borderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/borderWidth.html) - used to change the stroke width of the legend icon shape.
* [`iconBorderColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/iconBorderColor.html) - used to change the stroke color of the legend icon shape.
* [`itemPadding`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/itemPadding.html) - used to add padding between the first legend text and the second legend icon shape.
* [`height`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/height.html) - the height of the legend.
* [`width`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/width.html) - the width of the legend.
* [`isResponsive`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/isResponsive.html) - toggles the visibility of the legend. If the width or height of the legend is greater than the plot area bounds.
* [`iconBorderWidth`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/iconBorderWidth.html) - border width of the icon in the legend items. Used to change the stroke width of the legend icon shape.
{% highlight dart %}

Просмотреть файл

@ -58,6 +58,11 @@ You can use the following properties to customize the tooltip appearance.
* [`header`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/header.html) - specifies the header for tooltip. By default, the series name will be displayed in the header.
* [`format`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/format.html) - formats the tooltip text. By default, the tooltip will be rendered with x and y-values. You can add prefix or suffix to x, y, and series name values in the tooltip by formatting them.
* [`shadowColor`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shadowColor.html) - specifies the color of the tooltip shadow.
* [`shouldAlwaysShow`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shouldAlwaysShow.html) - used to shows or hides the tooltip.
* [`textAlignment`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/textAlignment.html) - alignment of the text in the tooltip.
* [`decimalPlaces`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/decimalPlaces.html) - used to specifies the number decimals to be displayed in tooltip text.
* [`shared`](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/shared.html) - used to share the tooltip with same index points.
{% highlight dart %}
TooltipBehavior _tooltipBehavior;

Двоичные данные
Flutter/radial-gauge/images/marker-pointers/marker_elevation.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
Flutter/radial-gauge/images/marker-pointers/marker_overlay.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 67 KiB

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Просмотреть файл

@ -7,7 +7,7 @@ control: SfRadialGauge
documentation: ug
---
# Marker pointer
# Marker pointer customization
Different types of markers are used to mark the pointer values in a scale. You can change the marker type using the [`markerType`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/markerType.html) property.
@ -127,6 +127,100 @@ Widget build(BuildContext context) {
![marker pointer customization](images/marker-pointers/marker_customization.jpg)
**Marker elevation**
The marker pointer can be elevated by rendering its shadow behind it and the z- coordinate position at which the shadow can be positioned relative to the marker can be controlled by the [`elevation`] property.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(pointers: <GaugePointer>[
MarkerPointer(
value: 60, markerHeight: 20, markerWidth: 20, elevation: 4)
])
],
)),
);
}
{% endhighlight %}
![marker elevation](images/marker-pointers/marker_elevation.png)
The shadow color of the pointer is black by default and the default value of [`elevation`] is 0.
N> The [`elevation`] property applies to all the marker types except [`MarkerType.image`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerType-class.html) and [`MarkerType.text`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerType-class.html).
**Marker overlay**
The marker overlay rendered around the marker when the marker is dragged. When [`enableDragging`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/GaugePointer/enableDragging.html) property of marker is set as true and while dragging the marker, the overlay will come around the marker pointer.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(pointers: <GaugePointer>[
MarkerPointer(
value: 60,
markerHeight: 20,
markerWidth: 20,
enableDragging: true,
markerType: MarkerType.circle)
])
],
)),
);
}
{% endhighlight %}
![marker overlay](images/marker-pointers/marker_overlay.png)
By default, the [`overlayRadius`] is calculated based on the provided [`markerHeight`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/markerHeight.html) and [`markerWidth`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/markerWidth.html) property and [`overlayColor`] is considered based on [`marker color`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/color.html). The properties are used to customize the overlay color and its radius,
* [`overlayColor`] – Allows customizing the overlay color.
* [`overlayRadius`] – Allows customizing the overlay radius.
{% highlight dart %}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(pointers: <GaugePointer>[
MarkerPointer(
value: 60,
markerHeight: 20,
markerWidth: 20,
enableDragging: true,
overlayRadius: 15,
overlayColor: Colors.red.withOpacity(0.12),
markerType: MarkerType.circle)
])
],
)),
);
}
{% endhighlight %}
![overlay customization](images/marker-pointers/marker_overlay_customization.png)
N> The marker overlay applies to all the marker types except [`MarkerType.image`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerType-class.html) and [`MarkerType.text`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerType-class.html).
## Position customization
The marker pointer can be moved near or far from its actual position using the [`markerOffset`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/markerOffset.html) and [`offsetUnit`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/MarkerPointer/offsetUnit.html) properties.

Просмотреть файл

@ -14,6 +14,7 @@ documentation: ug
[`Marker pointer`](https://help.syncfusion.com/flutter/radial-gauge/marker-pointer)
[`Needle pointer`](https://help.syncfusion.com/flutter/radial-gauge/needle-pointer)
[`Range pointer`](https://help.syncfusion.com/flutter/radial-gauge/range-pointer)
[`Widget pointer`]
All the pointers can be customized as needed. You can add multiple pointers to the gauge to point multiple values on the same scale. The value of the pointer is set using the [`value`](https://pub.dev/documentation/syncfusion_flutter_gauges/latest/gauges/GaugePointer/value.html) property.

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше