I Am trying to have a horizontal ListView
Widget that magnifies the center items. I tried using the normal ListView
but I couldn't get the center items to magnify. Then while searching the flutter docs I came across ListWheelScrollView
but unfortunately, it doesn't seem to support horizontal children layout. So basically am looking to create a horizontal ListView
with center items magnification. I'd appreciate it if anyone can at least point me in the right direction. Thanks
Edit: I have published package based on this.
pub.dev/packages/list_wheel_scroll_view_x
Here's my workaround.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class ListWheelScrollViewX extends StatelessWidget {
final Widget Function(BuildContext, int) builder;
final Axis scrollDirection;
final FixedExtentScrollController controller;
final double itemExtent;
final double diameterRatio;
final void Function(int) onSelectedItemChanged;
const ListWheelScrollViewX({
Key key,
@required this.builder,
@required this.itemExtent,
this.controller,
this.onSelectedItemChanged,
this.scrollDirection = Axis.vertical,
this.diameterRatio = 100000,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return RotatedBox(
quarterTurns: scrollDirection == Axis.horizontal ? 3 : 0,
child: ListWheelScrollView.useDelegate(
onSelectedItemChanged: onSelectedItemChanged,
controller: controller,
itemExtent: itemExtent,
diameterRatio: diameterRatio,
physics: FixedExtentScrollPhysics(),
childDelegate: ListWheelChildBuilderDelegate(
builder: (context, index) {
return RotatedBox(
quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
child: builder(context, index),
);
},
),
),
);
}
}
scrollDirection
which you can set to Axis.horizontal –
Perpetuity This is not really a solution but a naive hack, You can do this using the built-in ListWheelScrollView by pairing it with the RotatedBox
.
RotatedBox(
quarterTurns: -1,
child: ListWheelScrollView(
controller: _scrollController,
itemExtent: itemWidth,
onSelectedItemChanged: (newIndex) {
setState(() {
selectedIndex = newIndex;
});
},
children: List.generate(
itemCount,
(index) => RotatedBox(
quarterTurns: 1,
child: AnimatedContainer(
duration: Duration(milliseconds: 400),
width: index == selectedIndex ? 60 : 50,
height: index == selectedIndex ? 60 : 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: index == selectedIndex ? Colors.red : Colors.grey,
shape: BoxShape.circle,
),
child: Text('$index'),
),
),
),
),
);
I recommend using this approach until this issue is resolved
Heres the output
copy this code and used it
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class ListWheelScrollViewX extends StatelessWidget {
final Axis scrollDirection;
final List<Widget>? children;
final ScrollController? controller;
final ScrollPhysics? physics;
final double diameterRatio;
final double perspective;
final double offAxisFraction;
final bool useMagnifier;
final double magnification;
final double overAndUnderCenterOpacity;
final double itemExtent;
final double squeeze;
final ValueChanged<int>? onSelectedItemChanged;
final bool renderChildrenOutsideViewport;
final ListWheelChildDelegate? childDelegate;
final Clip clipBehavior;
const ListWheelScrollViewX({
Key? key,
this.scrollDirection = Axis.vertical,
this.controller,
this.physics,
this.diameterRatio = RenderListWheelViewport.defaultDiameterRatio,
this.perspective = RenderListWheelViewport.defaultPerspective,
this.offAxisFraction = 0.0,
this.useMagnifier = false,
this.magnification = 1.0,
this.overAndUnderCenterOpacity = 1.0,
required this.itemExtent,
this.squeeze = 1.0,
this.onSelectedItemChanged,
this.renderChildrenOutsideViewport = false,
this.clipBehavior = Clip.hardEdge,
required this.children,
}) : childDelegate = null,
super(key: key);
const ListWheelScrollViewX.useDelegate({
Key? key,
this.scrollDirection = Axis.vertical,
this.controller,
this.physics,
this.diameterRatio = RenderListWheelViewport.defaultDiameterRatio,
this.perspective = RenderListWheelViewport.defaultPerspective,
this.offAxisFraction = 0.0,
this.useMagnifier = false,
this.magnification = 1.0,
this.overAndUnderCenterOpacity = 1.0,
required this.itemExtent,
this.squeeze = 1.0,
this.onSelectedItemChanged,
this.renderChildrenOutsideViewport = false,
this.clipBehavior = Clip.hardEdge,
required this.childDelegate,
}) : children = null,
super(key: key);
@override
Widget build(BuildContext context) {
final _childDelegate = children != null
? ListWheelChildListDelegate(
children: children!.map((child) {
return RotatedBox(
quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
child: child,
);
}).toList())
: ListWheelChildBuilderDelegate(
builder: (context, index) {
return RotatedBox(
quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
child: childDelegate!.build(context, index),
);
},
);
return RotatedBox(
quarterTurns: scrollDirection == Axis.horizontal ? 3 : 0,
child: ListWheelScrollView.useDelegate(
controller: controller,
physics: FixedExtentScrollPhysics(),
diameterRatio: diameterRatio,
perspective: perspective,
offAxisFraction: offAxisFraction,
useMagnifier: useMagnifier,
magnification: magnification,
overAndUnderCenterOpacity: overAndUnderCenterOpacity,
itemExtent: itemExtent,
squeeze: squeeze,
onSelectedItemChanged: onSelectedItemChanged,
renderChildrenOutsideViewport: renderChildrenOutsideViewport,
clipBehavior: clipBehavior,
childDelegate: _childDelegate,
),
);
}
}
Example
ListWheelScrollViewX(
scrollDirection: Axis.horizontal,
itemExtent: 120,
children:...
),
Reference list_wheel_scroll_view_x
changes: convert to null safety
You can use this flutter package https://pub.dev/packages/carousel_slider. It also has a very helpful description and few samples to see how it looks. And it's compatible with dart 2.0 too.
You can make this work with the help of ListView
and PageView
along with NotificationListener
.
Below is my code for the same-
import 'dart:math';
import 'package:flutter/material.dart';
const SCALE_FRACTION = 0.9;
const FULL_SCALE = 1.0;
final PAGER_HEIGHT = SizeConfig.screenHeight*0.32;
const PAGER_WIDTH = double.infinity;
class PaymentWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PaymentState();
}
class _PaymentState extends State<PaymentWidget> {
double viewPortFraction = 0.9;
int currentPage = 1;
double page = 2.0;
PageController pageController;
final List<String> _cardsImages = ['image/path1', 'image/path2',
'image/path3', 'image/path4'];
@override
void initState() {
pageController = PageController(
initialPage: currentPage, viewportFraction: viewPortFraction);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: _creditCardsList()
);
}
Widget _creditCardsList() {
return ListView(
shrinkWrap: true,
children: <Widget>[
Container(
height: PAGER_HEIGHT,
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification is ScrollUpdateNotification) {
setState(() {
page = pageController.page;
});
}
},
child: PageView.builder(
onPageChanged: (pos) {
setState(() {
currentPage = pos;
});
},
physics: BouncingScrollPhysics(),
controller: pageController,
itemCount: _cardsImages.length,
itemBuilder: (context, index) {
final scale =
max(SCALE_FRACTION, (FULL_SCALE - (index - page).abs()) + viewPortFraction);
return CreditCardTile(
_cardsImages[index], scale);
},
),
),
),
],
);
}
Widget CreditCardTile(String image, double scale) {
return Align(
alignment: Alignment.bottomCenter,
child:Container(
height: PAGER_HEIGHT * scale,
width: PAGER_WIDTH * scale,
child: Card(
elevation: 5,
shadowColor: constColors.blueWhiteShade,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)
),
clipBehavior: Clip.antiAlias,
child: Image.asset(
image,
fit: BoxFit.cover,
),
)
) ,
);
}
Transform.rotate(
angle: -math.pi / 2,
child: ListWheelScrollView()
}
use Transform.rotate
Add 2 RotatedBox as Follows
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('Categories')
.doc('EcomCat')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.data == null) {
return Center(
child: CircularProgressIndicator(),
);
}
final DocumentSnapshot document = snapshot.data!;
final Map<String, dynamic> documentData =
document.data() as Map<String, dynamic>;
final List Category = documentData['category'];
return RotatedBox(quarterTurns: 1,
child: ListWheelScrollView.useDelegate(magnification: 200,
itemExtent: 180,
childDelegate: ListWheelChildBuilderDelegate(
childCount: Category.length,
builder: (context,index){
return Row(
children: [
RotatedBox(quarterTurns: -1,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.all(10),
shadowColor: Colors.black,
primary: Colors.teal,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(18))),
onPressed: () {
setState(() {
categoryVal =
Category[index].toString();
});
},
child: Text(
Category[index].toString(),
style: themeData.textTheme.headline4,
),
),
),
],
);
},
)),
);
},
),
© 2022 - 2024 — McMap. All rights reserved.