Flutter draggable scrollable sheet - flutter

does anyone know why my draggable scrollable sheet doesn't work or why I can't see it?
I tried it in another way it worked, but I didn't use the SafeArea-Widget,
import 'package:flutter/material.dart';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
//AppBar
),
body: SafeArea(
child: ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
dateday,
style: TextStyle(
color: Color(0xff2C8E5D),
fontSize: 150,
),
),
),
SizedBox.expand(
child: DraggableScrollableSheet(builder:
(BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.red,
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("Item $index"));
}),
);
}),
),
],
),
),
);
}
}
Thanks for your help!

Replace the ListView with a Stack:
body: SafeArea(
child: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
dateday,
style: TextStyle(
color: Color(0xff2C8E5D),
fontSize: 150,
),
),
),
SizedBox.expand(
child: DraggableScrollableSheet(
builder:
(BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.red,
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("Item $index"));
}),
);
}),
),
],
),
),

You can use LayoutBuilder and BoxConstraints to provide height and use Expanded flex to control DraggableScrollableSheet's scroll area
code snippet
SafeArea(
child: LayoutBuilder(builder: (context, constraints) {
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: constraints.maxWidth),
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
"dateday",
...
Expanded(
flex: 3,
child: SizedBox.expand(
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SafeArea(
child: LayoutBuilder(builder: (context, constraints) {
print(constraints.maxWidth);
print(constraints.minWidth);
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: constraints.maxWidth),
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(left: 20),
child: Text(
"dateday",
style: TextStyle(
color: Color(0xff2C8E5D),
fontSize: 150,
),
),
),
),
Expanded(
flex: 3,
child: SizedBox.expand(
child: DraggableScrollableSheet(builder:
(BuildContext context,
ScrollController scrollController) {
return Container(
color: Colors.red,
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("Item $index"));
}),
);
}),
),
),
],
),
);
}),
));
}
}

Related

Use ListView horizontal like Tabview with flutter

I'm looking for a tutorial on using a horizontal ListView that behaves like a Tabview, ie displaying the link on the same screen.
Some links to propose?
thanks
Tab child can others widget too, use height on Tab and isScrollable:true on TabBar
class TabBarDemo extends StatelessWidget {
const TabBarDemo({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
isScrollable: true,
tabs: [
Tab(
height: 100, // height
icon: Card(
child: Container(
height: 100,
width: 100,
color: Colors.red,
),
)),
Tab(
icon: Icon(Icons.directions_transit),
),
Tab(
icon: Icon(Icons.directions_bike),
),
],
),
title: const Text('Tabs Demo'),
),
body: const TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
),
);
}
}
more about tabs
And using PageView & ListView, it will be
class TabBarDemo extends StatelessWidget {
const TabBarDemo({super.key});
#override
Widget build(BuildContext context) {
final PageController controller = PageController();
return Scaffold(
body: Column(
children: [
SizedBox(
height: 100, //tab item height
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => GestureDetector(
onTap: () {
controller.animateToPage(index,
duration: Duration(milliseconds: 100),
curve: Curves.bounceIn);
},
child: Container(
height: 100,
width: 100,
color: Colors.red,
child: Card(
child: Text("tab $index"),
),
),
),
),
),
Expanded(
child: PageView.builder(
controller: controller,
itemBuilder: (context, index) {
return Center(
child: Text("$index"),
);
},
),
),
],
),
);
}
}
Also you can check CustomScrollView.
run this example and you will get the whole idea :
class ListTapPage extends StatefulWidget {
const ListTapPage({Key? key}) : super(key: key);
#override
State<ListTapPage> createState() => _ListTapPageState();
}
class _ListTapPageState extends State<ListTapPage> {
List<Widget> pages = [const Center(child: Text("one")),const Center(child: Text("two")),const Center(child: Text("three"),)];
List<String> names = ["one","two","three"];
List<Color> colors = [Colors.red,Colors.blue,Colors.yellow];
int _index = 0 ;
void changeIndex({required int num}){
setState((){
_index = num;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Positioned(top: 0,right: 0,left: 0,bottom: MediaQuery.of(context).size.height * 0.75,
child: SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return GestureDetector(
onTap:()=>changeIndex(num: index) ,
child: Container(alignment: Alignment.center,width: 200,height: 50,color: colors[index],child: Text(names[index])),
);
},
),
)
),
Positioned(
left: 0,
right: 0,
bottom: 0,
height: MediaQuery.of(context).size.height * 0.30,
child: pages[_index]
),
]
),
),
);
}
}
just return this widget in the material app ,see the result and look at the code , you will understand , it's a simple demo.

Why "SingleChildScrollView" Doesn't work around "AspectRatio" widget on Flutter?

This is my simple code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyMobileBody(),
);
}
}
class MyMobileBody extends StatelessWidget {
const MyMobileBody({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Scaffold(
backgroundColor: Colors.deepPurple[200],
appBar: AppBar(
title: Text('M O B I L E'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
// video section
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.deepPurple[400],
),
),
),
// comment section & recommended videos
Expanded(
child: ListView.builder(
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
),
)
],
),
),
),
);
}
}
It gets the bottom overflow yellow/black error. I want to make the AspectRatio widget scrollable but using SingleChildScrollView didn't work. I also tried ConstrainedBox like below but it didn't work too:
// comment section & recommended videos
ConstrainedBox(
constraints: BoxConstraints(maxHeight: constraints.maxHeight),
child: Expanded(
child: ListView.builder(
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
),
),
)
Add shrinkWrap : true to the ListView, then remove the Expanded widget that's wrapping the list view. Also add mainAxisSize : MainAxisSize.min. Then add SingleChildScrollView to the body of scaffold and the column inside it.
class MyMobileBody extends StatelessWidget {
const MyMobileBody({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Scaffold(
backgroundColor: Colors.deepPurple[200],
appBar: AppBar(
title: Text('M O B I L E'),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize : MainAxisSize.min,//<--here
children: [
// video section
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.deepPurple[400],
),
),
),
// comment section & recommended videos
//<--here removed expanded
ListView.builder(
shrinkWrap:true,//<--here
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.deepPurple[300],
height: 120,
),
);
},
)
],
),
),
),
),
);
}
}

There are multiple heroes that share the same tag within a subtree without using FAB

I am trying to navigate to a route and this exception happen. Have look at my code and I don't think I have a FAB and Hero inside this route. Is it because when you tap on each List item, it will show a dialog with Gridview on it? Someone care to explain to me how can this exception happened? It doesn't produce any error on user thought, just throw an exception.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Daftar Dokter")),
body: ListView.separated(
separatorBuilder: (BuildContext context, int i) => Divider(color: Colors.grey[400]),
itemCount: widget.data.length,
itemBuilder: (context, index) {
Doctor doctor = widget.data[index];
return InkWell(
onTap: (){
_buildDialog(context, scheduleService, doctor.doctorId);
},
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 50,
height: 50,
child: Placeholder(),
),
),
Flexible(
child: SizedBox(
child: ListTile(
title: Text(doctor.name),
subtitle: Text(doctor.specializationName),
),
)
)
],
),
);
}
)
);
}
}
Hope it will solve your issue:
onItem Builder:
itemBuilder: (context, index) {
return Hero(
tag: "itemTag $index",
child: Material(
child: InkWell(
onTap: () {
// _buildDialog(context, scheduleService, doctor.doctorId);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Wisgets(
tag: "itemTag $index",
)));
},
child: Row(
children: <Widget>[
Text("Item $index"),
],
),
),
),
);
},
Child Widget for row
class Wisgets extends StatelessWidget {
final String tag;
const Wisgets({Key? key, required this.tag}) : super(key: key);
#override
Widget build(BuildContext context) {
return Hero(
tag: tag,
child: Scaffold(
appBar: AppBar(
title: Text("Child"),
),
body: Column(
children: [
Text("got $tag"),
],
),
),
);
}
}

How to prevent widget from beeing scrolled?

How to prevent the first widget (ListView) from beeing scrolled?
The idea is to scroll SomeList, but the most top ListView widget should remain unscrollable.
body: ListView(
children: <Widget>[
ListView(
shrinkWrap: true,
children: <Widget>[
ListTile( // how to prevet this widget from beeing scrolled?
title: Container(
height: 30,
child: Row(...),
),
),
],
),
SomeList(), // builds ListView.separated( ...
],
),
updated:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(title: 'Flutter Demo', home: MyListView());
}
}
class MyListView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AppBar'),
),
body: ListView(
children: <Widget>[
ListView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: <Widget>[
ListTile(
title: Container(
height: 30,
color: Colors.black45,
child: Row(
children: const <Widget>[
Expanded(child: Text('Some header')),
],
),
),
),
],
),
RapportList(),
],
),
);
}
}
class RapportList extends StatefulWidget {
#override
_RapportListState createState() => _RapportListState();
}
class _RapportListState extends State<RapportList> {
#override
Widget build(BuildContext context) {
return ListView.separated(
physics: const ScrollPhysics(),
shrinkWrap: true,
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Row(
children: <Widget>[
Expanded(child: Text('$index')),
],
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
);
}
}
Solution is with Expended Widget,
use physics: NeverScrollableScrollPhysics(), too. here is full code:
class MyListView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AppBar'),
),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
Expanded(
flex:1,
child: ListView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: <Widget>[
ListTile(
title: Container(
height: 30,
color: Colors.black45,
child: Row(
children: const <Widget>[
Expanded(child: Text('Some header')),
],
),
),
),
],
),
),
Expanded(flex:9,child: RapportList()),
],
),
),
);
}
}
Use physics: const NeverScrollableScrollPhysics() in Listview Then you can prevent your widget from beeing scrolled.

implementing nested ListView inside SingleChildScrollView

in this sample code i want to put nested ListView inside SingleChildScrollView, but i get this error:
RenderBox was not laid out: RenderRepaintBoundary#8de00 relayoutBoundary=up1 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
my code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: Scaffold(
appBar: AppBar(
title: Text("Scrollview Demo"),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
),
Expanded(
child: ListView.builder(
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
),
),
],
),
),
),
);
}
}
In ListView you can set
shrinkWrap: true
so that ListView only occupies the space it needed.
To disable the scrolling on ListView so it uses that of SingleChildScrollView you can set the
physics: NeverScrollableScrollPhysics().
You need to remove the Expanded which set the child to take the available screen in case of here is infinite.
Here:
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
),
Flexible(
child: ListView.builder(
itemCount: 30,
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
),
),
],
),
)
Instead of using SingleChildScrollView then use Column as the child just use ListView.
return Scaffold(
body: ListView(
children: <Widget>[
Container(
height: 104,
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[],
),
),
),
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
),
],
),
);
Ones I was in the same situation and did like that:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: Scaffold(
appBar: AppBar(
title: Text("Scrollview Demo"),
),
body: ListView.builder(
itemCount: 30 + 1,
itemBuilder: (context, index) {
if (index == 0) {
return Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
);
}
return ListTile(title: Text('Index : ${index -1}'));
},
),
),
);
}
}