Reputation: 727
I am new to Flutter development
The horizontal list stops scrolling but is able To Scroll while using Axis.vertical.
What is expected is Once All the content of List Scrolls then only go to the next Slider.
Problem = only displays the list of items that we can visible on a screen unable to scroll horizontally
lib-link https://pub.dev/packages/overlapping_panels
body: OverlappingPanels(
right: Builder(
builder: (context) {
return Text("right");
}
),
main: Builder(
builder: (context) {
var items = ["item1","Item2", "Item3", "Item4", "Item5", "Item6", "Item7"];
return Container(
width: double.infinity,
height: 200,
color: Colors.blue,
child: Scrollbar(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: items.length,
itemBuilder: (BuildContext context , int index) {
return Container(
width: 150,
margin: const EdgeInsets.all(8),
child: Center(
child: Text(
items[index],
style: const TextStyle(
color: Colors.black,
fontSize: 18
),
),
),
);
})
)
);
},
),
onSideChange: (side) {
setState(() {
if (side == RevealSide.main) {
// hide something
} else if (side == RevealSide.left) {
// show something
}
});
},
)
Upvotes: 0
Views: 37
Reputation: 1124
I Looked at your code. And also looked at the Library of OverlappingPanels. The thing is, if you wrap you page with Overlapping Panels, It wrap you whole Screen with a Gesture Detector and it listens to a gesture to swipe from right to left.
If you are new, I would try something else. Otherwise you can copy their library and make it to your own class 'my_overlapoing_panels.dart like:
library overlapping_panels;
import 'package:flutter/material.dart';
import 'dart:core';
const double bleedWidth = 20;
/// Display sections
enum RevealSide { left, right, main }
/// Widget to display three view panels with the [MyOverlappingPanels.main] being
/// in the center, [MyOverlappingPanels.left] and [MyOverlappingPanels.right] also
/// revealing from their respective sides. Just like you will see in the
/// Discord mobile app's navigation.
class MyOverlappingPanels extends StatefulWidget {
/// The left panel
final Widget? left;
/// The main panel
final Widget main;
/// The right panel
final Widget? right;
/// The offset to use to keep the main panel visible when the left or right
/// panel is revealed.
final double restWidth;
final bool allowSidePanel;
/// A callback to notify when a panel reveal has completed.
final ValueChanged<RevealSide>? onSideChange;
const MyOverlappingPanels({
this.left,
required this.main,
this.right,
this.restWidth = 40,
this.onSideChange,
this.allowSidePanel = true,
Key? key,
}) : super(key: key);
static MyOverlappingPanelsState? of(BuildContext context) {
return context.findAncestorStateOfType<MyOverlappingPanelsState>();
}
@override
State<StatefulWidget> createState() {
return MyOverlappingPanelsState();
}
}
class MyOverlappingPanelsState extends State<MyOverlappingPanels> with TickerProviderStateMixin {
AnimationController? controller;
double translate = 0;
double _calculateGoal(double width, int multiplier) {
return (multiplier * width) + (-multiplier * widget.restWidth);
}
void _onApplyTranslation() {
final mediaWidth = MediaQuery.of(context).size.width;
final animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
if (widget.onSideChange != null) {
widget.onSideChange!(translate == 0 ? RevealSide.main : (translate > 0 ? RevealSide.left : RevealSide.right));
}
animationController.dispose();
}
});
if (translate.abs() >= mediaWidth / 2) {
final multiplier = (translate > 0 ? 1 : -1);
final goal = _calculateGoal(mediaWidth, multiplier);
final Tween<double> tween = Tween(begin: translate, end: goal);
final animation = tween.animate(animationController);
animation.addListener(() {
setState(() {
translate = animation.value;
});
});
} else {
final animation = Tween<double>(begin: translate, end: 0).animate(animationController);
animation.addListener(() {
setState(() {
translate = animation.value;
});
});
}
animationController.forward();
}
void reveal(RevealSide direction) {
// can only reveal when showing main
if (translate != 0) {
return;
}
final mediaWidth = MediaQuery.of(context).size.width;
final multiplier = (direction == RevealSide.left ? 1 : -1);
final goal = _calculateGoal(mediaWidth, multiplier);
final animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_onApplyTranslation();
animationController.dispose();
}
});
final animation = Tween<double>(begin: translate, end: goal).animate(animationController);
animation.addListener(() {
setState(() {
translate = animation.value;
});
});
animationController.forward();
}
void onTranslate(double delta) {
setState(() {
final translate = this.translate + delta;
if (translate < 0 && widget.right != null || translate > 0 && widget.left != null) {
this.translate = translate;
}
});
}
@override
Widget build(BuildContext context) {
return Stack(children: [
Offstage(
offstage: translate < 0,
child: widget.left,
),
Offstage(
offstage: translate > 0,
child: widget.right,
),
Transform.translate(
offset: Offset(translate, 0),
child: widget.main,
),
widget.allowSidePanel
? GestureDetector(
behavior: HitTestBehavior.translucent,
onHorizontalDragUpdate: (details) {
onTranslate(details.delta.dx);
},
onHorizontalDragEnd: (details) {
_onApplyTranslation();
},
)
: SizedBox(),
]);
}
}
Now you can use also the variable 'allowSidePanel' in your code. And If you update your code to:
class TestScreen extends StatefulWidget {
const TestScreen({super.key});
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
ScrollController controller = ScrollController();
bool allowScroll = false;
@override
void initState() {
super.initState();
// Setup the listener.
controller.addListener(() {
if (controller.position.atEdge) {
bool atBegin = controller.position.pixels == 0;
if (atBegin) {
/// here you can later allow left panel later
} else {
/// here allow sidepannel
setState(() {
allowScroll = true;
});
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: MyOverlappingPanels(
allowSidePanel: allowScroll,
right: Builder(builder: (context) {
return Text("right");
}),
main: Builder(
builder: (context) {
var items = ["item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7"];
return Container(
width: double.infinity,
height: 200,
color: Colors.blue,
child: ListView.builder(
controller: controller,
scrollDirection: Axis.horizontal,
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
return Container(
width: 150,
margin: const EdgeInsets.all(8),
child: Container(
padding: EdgeInsets.all(8),
color: Colors.red,
child: Center(
child: Text(
items[index],
style: const TextStyle(color: Colors.black, fontSize: 18),
),
),
),
);
}));
},
),
onSideChange: (side) {
setState(() {
if (side == RevealSide.main) {
/// here deaktivate ssidepannel again
allowScroll = false;
} else if (side == RevealSide.left) {
// show something
}
});
},
),
);
}
}
this will work.
Upvotes: 1