Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions lib/src/numberpicker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:infinite_listview/infinite_listview.dart';

typedef TextMapper = String Function(String numberText);
typedef ItemMapper = Widget Function(String numberText, TextStyle? style);

class NumberPicker extends StatefulWidget {
/// Min value user can pick
Expand Down Expand Up @@ -49,6 +50,9 @@ class NumberPicker extends StatefulWidget {
/// Build the text of each item on the picker
final TextMapper? textMapper;

/// Build the widget of each item on the picker
final ItemMapper? itemMapper;

/// Pads displayed integer values up to the length of maxValue
final bool zeroPad;

Expand All @@ -74,6 +78,7 @@ class NumberPicker extends StatefulWidget {
this.decoration,
this.zeroPad = false,
this.textMapper,
this.itemMapper,
this.infiniteLoop = false,
}) : assert(minValue <= value),
assert(value <= maxValue),
Expand Down Expand Up @@ -205,12 +210,8 @@ class _NumberPickerState extends State<NumberPicker> {
index >= listItemsCount - additionalItemsOnEachSide);
final itemStyle = value == widget.value ? selectedStyle : defaultStyle;

final child = isExtra
? SizedBox.shrink()
: Text(
_getDisplayedValue(value),
style: itemStyle,
);
final child =
isExtra ? SizedBox.shrink() : _getDisplayedValue(value, itemStyle);

return Container(
width: widget.itemWidth,
Expand All @@ -220,14 +221,16 @@ class _NumberPickerState extends State<NumberPicker> {
);
}

String _getDisplayedValue(int value) {
Widget _getDisplayedValue(int value, TextStyle? style) {
final text = widget.zeroPad
? value.toString().padLeft(widget.maxValue.toString().length, '0')
: value.toString();
if (widget.textMapper != null) {
return widget.textMapper!(text);
if (widget.itemMapper != null) {
return widget.itemMapper!(text, style);
} else if (widget.textMapper != null) {
return Text(widget.textMapper!(text), style: style);
} else {
return text;
return Text(text, style: style);
}
}

Expand Down
12 changes: 12 additions & 0 deletions test/integer_numberpicker_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';

import 'test_utils.dart';

Expand Down Expand Up @@ -100,4 +101,15 @@ void main() {
textMapper: (text) => '$text days',
expectedDisplayValues: ['2 days', '3 days', '4 days']);
});

testWidgets('Item mapper works', (WidgetTester tester) async {
await testMultipleValuesInPicker(
tester: tester,
minValue: 0,
maxValue: 10,
initialValue: 2,
scrollBy: 1,
itemMapper: (text, style) => Text('$text days', style: style),
expectedDisplayValues: ['2 days', '3 days', '4 days']);
});
}
3 changes: 3 additions & 0 deletions test/test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ Future<NumberPicker> testMultipleValuesInPicker({
required int scrollBy,
int step = 1,
TextMapper? textMapper,
ItemMapper? itemMapper,
bool animateToItself = false,
Axis axis = Axis.vertical,
bool zeroPad = false,
Expand All @@ -94,6 +95,7 @@ Future<NumberPicker> testMultipleValuesInPicker({
maxValue: maxValue,
step: step,
textMapper: textMapper,
itemMapper: itemMapper,
onChanged: (newValue) => setState(() => value = newValue),
zeroPad: zeroPad,
)
Expand All @@ -103,6 +105,7 @@ Future<NumberPicker> testMultipleValuesInPicker({
maxValue: maxValue,
step: step,
textMapper: textMapper,
itemMapper: itemMapper,
zeroPad: zeroPad,
onChanged: (newValue) => setState(() => value = newValue),
);
Expand Down