Skip to content

Commit

Permalink
Merge pull request #48 from moniaS/master
Browse files Browse the repository at this point in the history
Aligned middle element when user stops scrolling
  • Loading branch information
MarcinusX committed Aug 7, 2019
2 parents 6eebc00 + ca7e463 commit 5f3290c
Showing 1 changed file with 153 additions and 110 deletions.
263 changes: 153 additions & 110 deletions lib/numberpicker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -242,48 +242,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 +303,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 +358,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 +524,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

0 comments on commit 5f3290c

Please sign in to comment.