Latest source merged from Syncfusion
|
@ -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 |
После Ширина: | Высота: | Размер: 24 KiB |
Двоичные данные
Flutter/cartesian-charts/images/axis-types/datetimecategory_dateFormat.jpg
Normal file
После Ширина: | Высота: | Размер: 24 KiB |
Двоичные данные
Flutter/cartesian-charts/images/axis-types/datetimecategory_interval.jpg
Normal file
После Ширина: | Высота: | Размер: 23 KiB |
После Ширина: | Высота: | Размер: 28 KiB |
Двоичные данные
Flutter/cartesian-charts/images/trackball-crosshair/trackball_tooltip_marker.png
Normal file
После Ширина: | Высота: | Размер: 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 move the data 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 chart’s 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 move the data 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 %}
|
||||
|
||||
|
|
Двоичные данные
Flutter/circular-charts/images/circular-customization/doughnut_radial.jpg
Normal file
После Ширина: | Высота: | Размер: 15 KiB |
Двоичные данные
Flutter/circular-charts/images/circular-customization/pie_imageshader.jpg
Normal file
После Ширина: | Высота: | Размер: 28 KiB |
После Ширина: | Высота: | Размер: 13 KiB |
Двоичные данные
Flutter/circular-charts/images/circular-customization/pie_pointshadermapper.jpg
Normal file
После Ширина: | Высота: | Размер: 30 KiB |
Двоичные данные
Flutter/circular-charts/images/circular-customization/pie_rendermode.jpg
Normal file
После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
Flutter/circular-charts/images/circular-customization/radialbar_sweep.jpg
Normal file
После Ширина: | Высота: | Размер: 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 cell’s 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`.
|
||||
|
|
Двоичные данные
Flutter/datagrid/images/frozen-pane/flutter-datagrid-customized-frozen-elevation.png
Normal file
После Ширина: | Высота: | Размер: 16 KiB |
До Ширина: | Высота: | Размер: 67 KiB После Ширина: | Высота: | Размер: 17 KiB |
До Ширина: | Высота: | Размер: 58 KiB После Ширина: | Высота: | Размер: 16 KiB |
До Ширина: | Высота: | Размер: 160 KiB После Ширина: | Высота: | Размер: 453 KiB |
До Ширина: | Высота: | Размер: 63 KiB После Ширина: | Высота: | Размер: 42 KiB |
До Ширина: | Высота: | Размер: 207 KiB После Ширина: | Высота: | Размер: 481 KiB |
Двоичные данные
Flutter/datagrid/images/frozen-pane/flutter-datagrid-hide-frozen-elevation.png
Normal file
После Ширина: | Высота: | Размер: 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 text’s 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 text’s 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),
|
||||
|
|
|
@ -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 widget’s 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 widget’s 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>
|
||||
|
|
После Ширина: | Высота: | Размер: 64 KiB |
После Ширина: | Высота: | Размер: 65 KiB |
После Ширина: | Высота: | Размер: 60 KiB |
После Ширина: | Высота: | Размер: 44 KiB |
После Ширина: | Высота: | Размер: 54 KiB |
После Ширина: | Высота: | Размер: 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 move the data 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;
|
||||
|
|
После Ширина: | Высота: | Размер: 14 KiB |
После Ширина: | Высота: | Размер: 14 KiB |
Двоичные данные
Flutter/radial-gauge/images/marker-pointers/marker_overlay_customization.png
Normal file
После Ширина: | Высота: | Размер: 14 KiB |
Двоичные данные
Flutter/radial-gauge/images/pointers/pointers.png
До Ширина: | Высота: | Размер: 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.
|
||||
|
||||
|
|