Open MarcusWichelmann opened 3 years ago
Does anyone have an idea? If something is unclear with my issue description, please let me know.
The package prevents the list view from scrolling when the panel is not expended and scrolled already. I think it requires a change in the code for it to scroll programmatically before the user interaction with the panel.
Hi, I just looked over the code and the problem is the use of buildPanel(ScrollController sc)
. This ScrollController
is not the one that is responsible for any ListView
inside of the panel.
Nonetheless, in the code above the ScrollController
of the panel is given to the ListView
inside the panel. Hence, the ListView
Widget does not automatically keep the focused item in view because it doesn't know how with the panel's ScrollController
.
The better way of achieving what you are trying to do would probably to just give the ListView
widget to the panel via the panel
parameter. Then the above example works as expected (look at the code below). If you need to access the ScrollController
of the ListView
inside the panel you can just give it a new one and do it the "normal" way.
Here's the above example (working as intended):
import 'package:flutter/material.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final PanelController _panelController = PanelController();
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: SlidingUpPanel(
controller: _panelController,
panel: _buildListView(), // Use panel instead of panelBuilder
),
),
);
}
Widget _buildListView() {
return ListView.builder(
// controller: scrollController, // Don't give the scrollController of the panel to the ListView
itemCount: 100,
itemBuilder: (context, index) {
return Builder(
builder: (context) {
return Focus(
onFocusChange: (value) {
if (value) {
if (!_panelController.isPanelOpen) {
_panelController.open();
}
// Experimented with programmatic scrolling:
//
// // Scroll, so the focused widget is always vertically centered
// scrollController.position.ensureVisible(
// context.findRenderObject()!,
// alignmentPolicy: ScrollPositionAlignmentPolicy.explicit,
// alignment: 0.5,
// curve: Curves.ease,
// duration: const Duration(milliseconds: 300),
// );
//
}
},
child: Container(
margin: const EdgeInsets.all(10),
child: Builder(
builder: (context) {
return Text(
(Focus.of(context).hasFocus ? 'Focused' : 'Unfocused') +
' - $index',
);
},
),
),
);
},
);
},
);
}
}
@hauketoenjes Thank you very much, this solved my issue and keyboard scrolling works fine now. Only the the touch input is a bit broken now because scrolling doesn't open the panel anymore. But this is easily fixable by opening the panel programmatically as soon as scrolling begins.
I'll leave this bug report open, because a fix that doesn't require breaking touch input would still be useful.
@MarcusWichelmann Ok this particular problem can be solved for "only" keyboard scrolling like you said with my example above.
I looked a bit deeper in this package and the main problem is, that the SlidingUpPanel
works in a way, that it automatically scrolls / jumps to the top of the ScrollView
attached to the ScrollController
given by panelBuilder(ScrollController sc)
. This functionality is used to prevent the ScrollView
inside from scrolling while the panel itself is being slid up. This mechanism is then disabled when the user scrolls via touch input:
The "jumping" can be found here:
And the disabling / enabling here:
Since the boolean is only set on touch / pointer input, the panel is not scrollable (or at least is prevented from scrolling through the jumpTo(0)
) when opened programmatically.
Nonetheless to enable the functionality of scrolling when opening the panel programmatically we could just set _scrollingEnabled = true;
on open.
I will make a pull request adding this feature. I think it does not break anything else when setting the boolean in the open()
function here:
This would still allow the normal behavior for touch input, but also allow navigating via keyboard only.
Also this is in a way related to #236 and should be added together.
Describe the bug I have used
panelBuilder
to add aListView
to the panel as described in the readme. Because this is a TV app, I'm now trying to scroll this list only with the up/down keys of the keyboard. Normally, theListView
widget automatically ensures, that the focused item is always visible by implicitly scrolling to it. But this mechanism doesn't seem to work when the ListView is inside aSlidingUpPanel
. Instead, the scrollable list is stuck at the top and can only be scrolled with the keyboard after once moving it with the mouse (emulator). After having it once scrolled, the implicit scrolling does work flawlessly until I close and re-open the panel, then it's stuck again.I also experimented with
scrollController.position.ensureVisible()
andscrollController.position.animateTo()
, but these methods don't have any effect until having the list once scrolled manually, too.To Reproduce
Expected behavior When moving the focus far enough down so that the focused item is no longer visible, the list inside the opened
SlidingUpPanel
should automatically scroll down a bit to make the focused item visible. Also, theensureVisible
andanimateTo
methods should always work (at least when the panel is open).Screenshots If applicable, add screenshots to help explain your problem.
Device
dev/null-safety
branchSample
main.dart
Thanks for building this great package!