I am trying to implement a design that looks like this:
In the example the currentItem in the middle is of size 19
and its opacity
is at 100%. The 2nd item below/above it is of size 13
with an opacity
of 50% and the third items are of size 9
and with anopacity
of 25%.
How could I implement something like this with Flutter? I've tried multiple things, for example ListWheelScrollView
but I couldn't get the desired design.
One more requirement: The currentItem should be tappable
.
Any idea how I could get this done?
CodePudding user response:
A solution could be to use a CupertinoPicker
to achieve the design you're looking for.
For example, using a StatefulWidget
to update and retrieve the currentIndex
:
static const double _containerHeight = 500;
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return SizedBox(
height: _containerHeight,
child: CupertinoPicker.builder(
itemExtent: _containerHeight / 3,
diameterRatio: 20,
useMagnifier: false,
selectionOverlay: null,
onSelectedItemChanged: (value) => setState(() => currentIndex = value),
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200),
style: TextStyle(fontSize: getFontSizeFromIndex(index)),
child: Text(
'Das ist ein Text',
style: TextStyle(
color:
Colors.white.withOpacity(getOpacityFromIndex(index))),
),
),
],
);
},
),
);
}
double getFontSizeFromIndex(int index) => index == currentIndex
? 19
: index == currentIndex - 1 || index == currentIndex 1
? 13
: 9;
double getOpacityFromIndex(int index) => index == currentIndex
? 1
: index == currentIndex - 1 || index == currentIndex 1
? .5
: .25;
To go further, you should considerate :
debouncing
theonSelectedItemChanged
in order to prevent abusive rebuilds ;- using a custom
ScrollController
and do some linear interpolations in order to make the animation smoother.
Here is the result :