ListView in SlidingUpPanel scroll - flutter

In slidingUpPanel, I have a ListView widget. When I try to scroll, the ListView slidingUpPanel closes. How do I scroll the ListView without closing the slidingUpPanel?
SlidingUpPanel(
controller: _panelController,
maxHeight: _panelHeightOpen,
minHeight: _panelHeightClosed,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
),
boxShadow: [
BoxShadow(
color: secondaryColor,
spreadRadius: 1,
blurRadius: 5,
offset: Offset(0, -10), // changes position of shadow
),
],
panelBuilder: (sc) => _summaryWidget(sc),
),
My _summaryWidget
ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: [
Photos(),
],
)

You need to put the sc in the ListView controller also:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlidingUpPanelExample"),
),
body: SlidingUpPanel(
panelBuilder: (ScrollController sc) => _scrollingList(sc),
body: Center(
child: Text("This is the Widget behind the sliding panel"),
),
),
);
}
Widget _scrollingList(ScrollController sc){
return ListView.builder(
controller: sc,
itemCount: 50,
itemBuilder: (BuildContext context, int i){
return Container(
padding: const EdgeInsets.all(12.0),
child: Text("$i"),
);
},
);
}

Related

Flutter - How to scroll Container over another

I'm begginning Flutter and I'm searching to scroll ListView over a Container like below
You can use DraggableScrollableSheet
DraggableScrollableSheet(
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Column(
children: [],
),
);
},
)
You can follow the doc example
A complete widget
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
openDraggable(context) {
showModalBottomSheet(
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(22),
topRight: Radius.circular(22),
)),
context: context,
builder: (context) => DraggableScrollableSheet(
maxChildSize: 1,
initialChildSize: .4,
expand: false,
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
for (int i = 0; i < 32; i++)
ListTile(
title: Text("item"),
),
],
),
);
},
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
openDraggable(context);
},
child: Text("open"),
)
],
),
),
);
}
}
Don't use DraggableScrollableSheet. instead of that widget use the sliver widget, this widget is amazing,
you can use this article and this
CustomScrollView(
slivers: <Widget>[
// appbar of search page
SliverAppBar(
// icon in top left
leading: _icon(context),
// backgroun of appbar
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
// style of app bar
pinned: true,
floating: true,
snap: true,
expandedHeight: 130,
// obtional filter for product
flexibleSpace: FlexibleSpaceBar(
background: Padding(
padding: const EdgeInsets.only(top: 80.0),
child: Container(
alignment: Alignment.center,
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.symmetric(horizontal: 10.0),
decoration: BoxDecoration(
borderRadius: borderRadius_30,
color: Theme.of(context).primaryColorLight),
child: TextField(
onChanged: (value) {
// you can sort data for user in this section
},
style: TextStyle(
color: Theme.of(context).textSelectionColor,
),
decoration: InputDecoration(
border: InputBorder.none,
// styel of labeltext in textfield
labelStyle: TextStyle(
color: Colors.cyan,
),
labelText: Strings.search,
),
),
),
),
),
),
// body
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return SearchBody(index);
},
childCount: fakeData.length,
),
// number of object
)
],
),
You can use the sliver package, something like this.

Error when listviewBuilder scrollDirection is horizontal

I got this very simple code, but somehow I get an error when I set scrollDirection to Axis.horizontal
I invoke this widget in Page that has MaterialApp and Scaffold widgets.
What I tried is wrapping ListView.builder with expanded, I removed all widgets besides Container and ListView.builder
Here is code:
class CalendarPage extends StatelessWidget {
List<String> hoursList = ['00:00', '00:30', '01:00'];
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25), topRight: Radius.circular(25))),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextLabel('Choose preferred date of meeting'),
ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: hoursList.length,
itemBuilder: (context, i) {
return Text(hoursList[i]);
})
],
),
),
);
}
}
thank you in advance
Wrap your ListView inside Expanded or Flexible widget. refer below code:
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25),
),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextLabel('Choose preferred date of meeting'),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: hoursList.length,
itemBuilder: (context, i) {
return Text(
hoursList[i],
);
}),
)
],
),
),
),
Result screen->
You must wrap with a container your Listview and define height value.
class CalendarPage extends StatelessWidget {
List<String> hoursList = ['00:00', '00:30', '01:00'];
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25), topRight: Radius.circular(25))),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextLabel('Choose preferred date of meeting'),
Container(
height: 300,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: hoursList.length,
itemBuilder: (context, i) {
return Text(hoursList[i]);
}),
)
],
),
),
);
}
}

How to make reusable modal bottom sheet

usually I use showModalBottomSheet for each view to call a ModalBottomSheet with the same content on it. I just want to make it simple as I can call the class of reusable modal bottomsheet.
_moreModalBottomSheet(context) {
Size size = MediaQuery.of(context).size;
showModalBottomSheet(
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40.0),
),
context: context,
builder: (BuildContext bc) {
return Container(
height: size.height * 0.5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(40.0),
topLeft: Radius.circular(40.0),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: ListView(
physics: ClampingScrollPhysics(),
children: [
//content of modal bottomsheet
],
),
),
);
});
}
for example, I use button to show modal bottom sheet
ElevatedButton(onPressed: _moreModalBottomSheet(context), child: Text('show modal bottom sheet'))
I want to make _moreModalBottomSheet() as a class so it reusable.
on this answer its only a reusable a layout. But, what I trying to achieve is make a custom class ModalBottomSheet. So I can call ModalBottomSheet in other class only like ModalBottomSheet() not showModalBottomSheet that return ModalBottomSheet . It's that possible?
You just need to extract it to a new class like:
class ModalBottomSheet {
static void _moreModalBottomSheet(context) {
Size size = MediaQuery.of(context).size;
showModalBottomSheet(
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40.0),
),
context: context,
builder: (BuildContext bc) {
return Container(
height: size.height * 0.5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(40.0),
topLeft: Radius.circular(40.0),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: ListView(
physics: ClampingScrollPhysics(),
children: [
//content of modal bottomsheet
],
),
),
);
});
}
}
Now you can call it everywhere like:
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () =>
ModalBottomSheet._moreModalBottomSheet(context),
child: Text('open modal'),
),
),
),
);
}
}
Open bottom sheet like this
InkWell(
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return ModalBottomSheet(
);
});
})
Stateful bottom sheet
class ModalBottomSheet extends StatefulWidget {
#override
_ModalBottomSheetState createState() => _ModalBottomSheetState();
}
class _ModalBottomSheetState extends State<ModalBottomSheet>
with SingleTickerProviderStateMixin {
#override
Widget build(BuildContext context) {
double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
// TODO: implement build
return Wrap(
children: <Widget>[
Container(
margin:
EdgeInsets.only(left: 10.0, right: 10.0, top: 15.0, bottom: 15.0),
child: Column(
children: <Widget>[
Widgets(),
]
)
)
],
);
}
}

Flutter: CupertinoTabScaffold with CupertinoTabBar creating RenderFlex overflow issue at bottom for TabBar in pushed screens

I am an iOS developer, So I have idea how TabBarController works in iOS. Now I am working on Flutter (First APP).
I have an App which uses CupertinoApp-CupertinoTabScaffold-CupertinoTabBar to persist BottomNavigationBar in every nested screens.
My App's hierarchy
- CupertinoTabScaffold
-- CupertinoTabBar
--- Home
---- CupertinoPageScaffold (HomePage)
----- CupertinoPageScaffold (DetailPage pushed from home)
--- OtherTabs
To Push from HomePage to DetailPage, used below code:
Navigator.push(
context,
Platform.isIOS
? CupertinoPageRoute(
builder: (context) => DetailPage(),
)
: MaterialPageRoute(
builder: (context) => DetailPage(),
));
Now on detail screen I need Column for some view and GridView.
So when GridView have more items, it gives error:
A RenderFlex overflowed by 56 pixels on the bottom.
Which is space of TabBar.
So how to manage such type of pages in Flutter, having TabBar and scrollable Widgets in nested screens?
I have followed this link.
DetailPage Code:
class DetailPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
heroTag: 'detail 1',
backgroundColor: Colors.white,
transitionBetweenRoutes: false,
middle: Text('Tab 1 detail',),
),
child: Container(
child: Column(
children: <Widget>[
SizedBox(
height: 100.0,
child: Center(
child: Text('Some Menus'),
),
),
Container(
child: GridView.builder(
itemCount: 30,
scrollDirection: Axis.vertical,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight(
crossAxisCount: 2,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
height: 160.0
),
itemBuilder: (context, index) {
return Container(
child: Padding(
padding: EdgeInsets.all(6.0),
child: Container(
decoration: BoxDecoration(
color: Color(0xFF3C9CD9),
borderRadius: BorderRadius.all(Radius.circular(30.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
blurRadius: 2.0,
offset: Offset(4, 3))
]),
child: Padding(
padding: EdgeInsets.all(30.0),
child: Center(
child: Text('$index'),
),
)),
),
);
}
),
)
],
),
),
);
}
}
Output:
wrap the Grid with with Expanded widget
class DetailPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
heroTag: 'detail 1',
backgroundColor: Colors.white,
transitionBetweenRoutes: false,
middle: Text('Tab 1 detail',),
),
child: Container(
child: Column(
children: <Widget>[
SizedBox(
height: 100.0,
child: Center(
child: Text('Some Menus'),
),
),
Expanded(
child: Container(
child: GridView.builder(
itemCount: 30,
scrollDirection: Axis.vertical,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight(
crossAxisCount: 2,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
height: 160.0
),
itemBuilder: (context, index) {
return Container(
child: Padding(
padding: EdgeInsets.all(6.0),
child: Container(
decoration: BoxDecoration(
color: Color(0xFF3C9CD9),
borderRadius: BorderRadius.all(Radius.circular(30.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black54,
blurRadius: 2.0,
offset: Offset(4, 3))
]),
child: Padding(
padding: EdgeInsets.all(30.0),
child: Center(
child: Text('$index'),
),
)),
),
);
}
),
),
)
],
),
),
);
}
}

DraggableScrollableSheet not working in NestedScrollView

What I would like to do
I want to make it possible for the user to drag the blue area up with their finger.
Problem
cant drag up draggable
Architecture
NestedScrollView (
headerSliver:SliverAppBar(...)
body: Stack(
childern: [
Expanded(
child: SliverGrid(),
),
Draggable(),
],
),
),
What I checked
I confirmed that the touch works on the draggable. I made an InkWell with a builder and confirmed that the onPressed function works.
I tried with CustomScrollView as well, but it still didn't work.
code
NestedScrollView
NestedScrollView(
headerSliverBuilder: (context, innerBoxScrolled) {
return [
SliverAppBar(
leading: null,
elevation: 0,
expandedHeight: 160,
pinned: false,
flexibleSpace: TopNavBar(
height: 100,
),
bottom: AppBar(
leading: null,
toolbarHeight: 100,
elevation: 0,
actions: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AdTopTabBar(),
FilterBar(),
],
),
],
),
),
];
},
body: Stack(
children: [
Expanded(
child: HomeAdCollection(),
),
MyAdDraggable(),
],
),
),
Draggable
class MyAdDraggable extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
key: key,
initialChildSize: 0.05,
minChildSize: 0.05,
maxChildSize: 0.7,
expand: true,
builder: (context, scrollcontroller) {
return InkWell(
onTap: () {
print('ff');
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
color: Colors.blue[100],
),
),
);
},
);
}
}
There must be at least one child in the DraggableScrollableSheet that uses scrolling. Otherwise, you can't drag it up.
When I put ListView as a child in DraggableScrollableSheet, it works well!