Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onChanged allows NULL. This disables scrolling if no onChanged provided. #127

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
9 changes: 4 additions & 5 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class __IntegerExampleState extends State<_IntegerExample> {
return Column(
children: <Widget>[
SizedBox(height: 16),
Text('Default', style: Theme.of(context).textTheme.headline6),
Text('Default', style: Theme.of(context).textTheme.titleLarge),
NumberPicker(
value: _currentIntValue,
minValue: 0,
Expand Down Expand Up @@ -95,16 +95,15 @@ class __IntegerExampleState extends State<_IntegerExample> {
),
Divider(color: Colors.grey, height: 32),
SizedBox(height: 16),
Text('Horizontal', style: Theme.of(context).textTheme.headline6),
Text('Horizontal', style: Theme.of(context).textTheme.titleLarge),
NumberPicker(
value: _currentHorizontalIntValue,
minValue: 0,
maxValue: 100,
step: 10,
itemHeight: 100,
axis: Axis.horizontal,
onChanged: (value) =>
setState(() => _currentHorizontalIntValue = value),
onChanged: (value) => setState(() => _currentHorizontalIntValue = value),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.black26),
Expand Down Expand Up @@ -148,7 +147,7 @@ class __DecimalExampleState extends State<_DecimalExample> {
return Column(
children: <Widget>[
SizedBox(height: 16),
Text('Decimal', style: Theme.of(context).textTheme.headline6),
Text('Decimal', style: Theme.of(context).textTheme.titleLarge),
DecimalNumberPicker(
value: _currentDoubleValue,
minValue: 0,
Expand Down
56 changes: 25 additions & 31 deletions lib/src/numberpicker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class NumberPicker extends StatefulWidget {
final int value;

/// Called when selected value changes
final ValueChanged<int> onChanged;
final ValueChanged<int>? onChanged;

/// Specifies how many items should be shown - defaults to 3
final int itemCount;
Expand Down Expand Up @@ -61,7 +61,7 @@ class NumberPicker extends StatefulWidget {
required this.minValue,
required this.maxValue,
required this.value,
required this.onChanged,
this.onChanged,
this.itemCount = 3,
this.step = 1,
this.itemHeight = 50,
Expand All @@ -88,11 +88,9 @@ class _NumberPickerState extends State<NumberPicker> {
@override
void initState() {
super.initState();
final initialOffset =
(widget.value - widget.minValue) ~/ widget.step * itemExtent;
final initialOffset = (widget.value - widget.minValue) ~/ widget.step * itemExtent;
if (widget.infiniteLoop) {
_scrollController =
InfiniteScrollController(initialScrollOffset: initialOffset);
_scrollController = InfiniteScrollController(initialScrollOffset: initialOffset);
} else {
_scrollController = ScrollController(initialScrollOffset: initialOffset);
}
Expand All @@ -106,19 +104,22 @@ class _NumberPickerState extends State<NumberPicker> {
} else {
indexOfMiddleElement = indexOfMiddleElement.clamp(0, itemCount - 1);
}
final intValueInTheMiddle =
_intValueFromIndex(indexOfMiddleElement + additionalItemsOnEachSide);
final intValueInTheMiddle = _intValueFromIndex(indexOfMiddleElement + additionalItemsOnEachSide);

if (widget.value != intValueInTheMiddle) {
widget.onChanged(intValueInTheMiddle);
if (widget.haptics) {
HapticFeedback.selectionClick();
if (widget.onChanged != null) {
widget.onChanged!(intValueInTheMiddle);
if (widget.haptics) {
HapticFeedback.selectionClick();
}
}
}
Future.delayed(
Duration(milliseconds: 100),
() => _maybeCenterValue(),
);
if (!isScrolling) {
Future.delayed(
Duration(milliseconds: 100),
() => _maybeCenterValue(),
);
}
}

@override
Expand All @@ -137,8 +138,7 @@ class _NumberPickerState extends State<NumberPicker> {

bool get isScrolling => _scrollController.position.isScrollingNotifier.value;

double get itemExtent =>
widget.axis == Axis.vertical ? widget.itemHeight : widget.itemWidth;
double get itemExtent => widget.axis == Axis.vertical ? widget.itemHeight : widget.itemWidth;

int get itemCount => (widget.maxValue - widget.minValue) ~/ widget.step + 1;

Expand All @@ -149,12 +149,8 @@ class _NumberPickerState extends State<NumberPicker> {
@override
Widget build(BuildContext context) {
return SizedBox(
width: widget.axis == Axis.vertical
? widget.itemWidth
: widget.itemCount * widget.itemWidth,
height: widget.axis == Axis.vertical
? widget.itemCount * widget.itemHeight
: widget.itemHeight,
width: widget.axis == Axis.vertical ? widget.itemWidth : widget.itemCount * widget.itemWidth,
height: widget.axis == Axis.vertical ? widget.itemCount * widget.itemHeight : widget.itemHeight,
child: NotificationListener<ScrollEndNotification>(
onNotification: (not) {
if (not.dragDetails?.primaryVelocity == 0) {
Expand All @@ -166,6 +162,7 @@ class _NumberPickerState extends State<NumberPicker> {
children: [
if (widget.infiniteLoop)
InfiniteListView.builder(
physics: widget.onChanged == null ? NeverScrollableScrollPhysics() : BouncingScrollPhysics(),
scrollDirection: widget.axis,
controller: _scrollController as InfiniteScrollController,
itemExtent: itemExtent,
Expand All @@ -174,6 +171,7 @@ class _NumberPickerState extends State<NumberPicker> {
)
else
ListView.builder(
physics: widget.onChanged == null ? NeverScrollableScrollPhysics() : BouncingScrollPhysics(),
itemCount: listItemsCount,
scrollDirection: widget.axis,
controller: _scrollController,
Expand All @@ -195,14 +193,12 @@ class _NumberPickerState extends State<NumberPicker> {
Widget _itemBuilder(BuildContext context, int index) {
final themeData = Theme.of(context);
final defaultStyle = widget.textStyle ?? themeData.textTheme.bodyMedium;
final selectedStyle = widget.selectedTextStyle ??
themeData.textTheme.headlineSmall
?.copyWith(color: themeData.colorScheme.secondary);
final selectedStyle =
widget.selectedTextStyle ?? themeData.textTheme.headlineSmall?.copyWith(color: themeData.colorScheme.secondary);

final value = _intValueFromIndex(index % itemCount);
final isExtra = !widget.infiniteLoop &&
(index < additionalItemsOnEachSide ||
index >= listItemsCount - additionalItemsOnEachSide);
(index < additionalItemsOnEachSide || index >= listItemsCount - additionalItemsOnEachSide);
final itemStyle = value == widget.value ? selectedStyle : defaultStyle;

final child = isExtra
Expand All @@ -221,9 +217,7 @@ class _NumberPickerState extends State<NumberPicker> {
}

String _getDisplayedValue(int value) {
final text = widget.zeroPad
? value.toString().padLeft(widget.maxValue.toString().length, '0')
: value.toString();
final text = widget.zeroPad ? value.toString().padLeft(widget.maxValue.toString().length, '0') : value.toString();
if (widget.textMapper != null) {
return widget.textMapper!(text);
} else {
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: NumberPicker is a widget allowing user to choose numbers by scrolli
homepage: https://github.com/MarcinusX/NumberPicker

environment:
sdk: ">=2.12.0 <3.0.0"
sdk: ">=2.12.0 <4.0.0"

dependencies:
flutter:
Expand Down