Skip to content

Commit

Permalink
Merge ea4292f into 6eebc00
Browse files Browse the repository at this point in the history
  • Loading branch information
moniaS committed Aug 7, 2019
2 parents 6eebc00 + ea4292f commit 2596c52
Showing 1 changed file with 163 additions and 115 deletions.
278 changes: 163 additions & 115 deletions lib/numberpicker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class NumberPicker extends StatelessWidget {
/// if min=0, max=5, step=3, then items will be 0 and 3.
final int step;

/// Direction of scrolling
final Axis scrollDirection;

///Repeat values infinitely
Expand All @@ -189,21 +190,25 @@ class NumberPicker extends StatelessWidget {
//----------------------------- PUBLIC ------------------------------
//

animateInt(int valueToSelect) {
/// Used to animate integer number picker to new selected value
void animateInt(int valueToSelect) {
int diff = valueToSelect - minValue;
int index = diff ~/ step;
animateIntToIndex(index);
}

animateIntToIndex(int index) {
/// Used to animate integer number picker to new selected index
void animateIntToIndex(int index) {
_animate(intScrollController, index * itemExtent);
}

animateDecimal(int decimalValue) {
/// Used to animate decimal part of double value to new selected value
void animateDecimal(int decimalValue) {
_animate(decimalScrollController, decimalValue * itemExtent);
}

animateDecimalAndInteger(double valueToSelect) {
/// Used to animate decimal number picker to selected value
void animateDecimalAndInteger(double valueToSelect) {
animateInt(valueToSelect.floor());
animateDecimal(((valueToSelect - valueToSelect.floorToDouble()) *
math.pow(10, decimalPlaces))
Expand Down Expand Up @@ -242,48 +247,56 @@ class NumberPicker extends StatelessWidget {

var listItemCount = integerItemCount + 2;

return new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
new ListView.builder(
scrollDirection: scrollDirection,
controller: intScrollController,
itemExtent: itemExtent,
itemCount: listItemCount,
cacheExtent: _calculateCacheExtent(listItemCount),
itemBuilder: (BuildContext context, int index) {
final int value = _intValueFromIndex(index);

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedIntValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

bool isExtra = index == 0 || index == listItemCount - 1;

return isExtra
? new Container() //empty first and last element
: new Center(
child: new Text(
getDisplayedValue(value),
style: itemStyle,
),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
return Listener(
onPointerUp: (ev) {
///used to detect that user stopped scrolling
if (intScrollController.position.activity is HoldScrollActivity) {
animateInt(selectedIntValue);
}
},
child: new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
new ListView.builder(
scrollDirection: scrollDirection,
controller: intScrollController,
itemExtent: itemExtent,
itemCount: listItemCount,
cacheExtent: _calculateCacheExtent(listItemCount),
itemBuilder: (BuildContext context, int index) {
final int value = _intValueFromIndex(index);

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedIntValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

bool isExtra = index == 0 || index == listItemCount - 1;

return isExtra
? new Container() //empty first and last element
: new Center(
child: new Text(
getDisplayedValue(value),
style: itemStyle,
),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
),
),
onNotification: _onIntegerNotification,
),
onNotification: _onIntegerNotification,
);
}

Expand All @@ -295,45 +308,53 @@ class NumberPicker extends StatelessWidget {
int decimalItemCount =
selectedIntValue == maxValue ? 3 : math.pow(10, decimalPlaces) + 2;

return new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
new ListView.builder(
controller: decimalScrollController,
itemExtent: itemExtent,
itemCount: decimalItemCount,
itemBuilder: (BuildContext context, int index) {
final int value = index - 1;

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedDecimalValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

bool isExtra = index == 0 || index == decimalItemCount - 1;

return isExtra
? new Container() //empty first and last element
: new Center(
child: new Text(
value.toString().padLeft(decimalPlaces, '0'),
style: itemStyle),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
return Listener(
onPointerUp: (ev) {
///used to detect that user stopped scrolling
if (decimalScrollController.position.activity is HoldScrollActivity) {
animateDecimal(selectedDecimalValue);
}
},
child: new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
new ListView.builder(
controller: decimalScrollController,
itemExtent: itemExtent,
itemCount: decimalItemCount,
itemBuilder: (BuildContext context, int index) {
final int value = index - 1;

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedDecimalValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

bool isExtra = index == 0 || index == decimalItemCount - 1;

return isExtra
? new Container() //empty first and last element
: new Center(
child: new Text(
value.toString().padLeft(decimalPlaces, '0'),
style: itemStyle),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
),
),
onNotification: _onDecimalNotification,
),
onNotification: _onDecimalNotification,
);
}

Expand All @@ -342,41 +363,49 @@ class NumberPicker extends StatelessWidget {
TextStyle selectedStyle =
themeData.textTheme.headline.copyWith(color: themeData.accentColor);

return new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
InfiniteListView.builder(
controller: intScrollController,
itemExtent: itemExtent,
itemBuilder: (BuildContext context, int index) {
final int value = _intValueFromIndex(index);

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedIntValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

return new Center(
child: new Text(
getDisplayedValue(value),
style: itemStyle,
),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
return Listener(
onPointerUp: (ev) {
///used to detect that user stopped scrolling
if (intScrollController.position.activity is HoldScrollActivity) {
_animateIntWhenUserStoppedScrolling(selectedIntValue);
}
},
child: new NotificationListener(
child: new Container(
height: listViewHeight,
width: listViewWidth,
child: Stack(
children: <Widget>[
InfiniteListView.builder(
controller: intScrollController,
itemExtent: itemExtent,
itemBuilder: (BuildContext context, int index) {
final int value = _intValueFromIndex(index);

//define special style for selected (middle) element
final TextStyle itemStyle =
value == selectedIntValue && highlightSelectedValue
? selectedStyle
: defaultStyle;

return new Center(
child: new Text(
getDisplayedValue(value),
style: itemStyle,
),
);
},
),
_NumberPickerSelectedItemDecoration(
axis: scrollDirection,
itemExtent: itemExtent,
decoration: decoration,
),
],
),
),
onNotification: _onIntegerNotification,
),
onNotification: _onIntegerNotification,
);
}

Expand Down Expand Up @@ -500,6 +529,25 @@ class NumberPicker extends StatelessWidget {
scrollController.position.activity is! HoldScrollActivity;
}

/// Allows to find currently selected element index and animate this element
/// Use it only when user manually stops scrolling in infinite loop
void _animateIntWhenUserStoppedScrolling(int valueToSelect) {
// estimated index of currently selected element based on offset and item extent
int currentlySelectedElementIndex = intScrollController.offset ~/ itemExtent;

// when more(less) than half of the top(bottom) element is hidden
// then we should increment(decrement) index in case of positive(negative) offset
if (intScrollController.offset > 0 &&
intScrollController.offset % itemExtent > itemExtent / 2) {
currentlySelectedElementIndex++;
} else if (intScrollController.offset < 0 &&
intScrollController.offset % itemExtent < itemExtent / 2) {
currentlySelectedElementIndex--;
}

animateIntToIndex(currentlySelectedElementIndex);
}

///converts integer indicator of decimal value to double
///e.g. decimalPlaces = 1, value = 4 >>> result = 0.4
/// decimalPlaces = 2, value = 12 >>> result = 0.12
Expand Down Expand Up @@ -611,7 +659,7 @@ class _NumberPickerDialogControllerState extends State<NumberPickerDialog> {
_NumberPickerDialogControllerState(
this.selectedIntValue, this.selectedDoubleValue);

_handleValueChanged(num value) {
void _handleValueChanged(num value) {
if (value is int) {
setState(() => selectedIntValue = value);
} else {
Expand Down

0 comments on commit 2596c52

Please sign in to comment.