How can I make a scaffold scrollable in Flutter? - flutter

I've tried a lot to make a list scrollable, but it never worked.
Everytime I wrapped it in a SingleChildScrollView my list just disappeared.
Can someone help pls
Here is my code:
return Scaffold(
body:
SingleChildScrollView(
child: ListView.builder(
itemCount: subjects.length,
itemBuilder: (context, i) {
return singleSubject(
subjects[i],
() => deleteItem(i),
);
},
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: const Color(0xFF383838),
onPressed: newSubject,
child: const Icon(Icons.add),
),
backgroundColor: const Color(0xFFB94844),
);
}
}

You dont need to use SingleChildScrollView while ListView is the only child on body.
Do
body: ListView.builder(
Find more about widgets/scrolling

Related

How to make clickable widget behind stack in flutter

I have two scaffold widget in the stack for some purposes .. And every scaffold has its own contents .
the second scaffold has transparent background colors so the first scaffold is visible.
Stack(
children: [
Scaffold(
body: GestureDetector(
onTap: () {},
child: myBody(),
),
),
Scaffold(
backgroundColor: Colors.transparent,
body: ListView.builder(
itemBuilder: (context, index) => ...,
),
)
],
),
the GestureDetector in first Scaffolddoes not work and that's because of the Scaffold stack
Note : I can't wrap the second Scaffold with IgnorePointer because it has clickable ListView.bulder which gonna be ignoring any pointer too
How could I solve this ×_O
You can get callback method from second scaffold list item tap. And create a function on level that will be provided on first scaffold GestureDetector.
void main(List<String> args) {
Widget myBody() {
return Container(
color: Colors.cyanAccent.withOpacity(.3),
);
}
void topLevelGesture() {
debugPrint("got hit on GestureDetector");
}
runApp(
MaterialApp(
home: Stack(
children: [
Scaffold(
body: GestureDetector(
onTap: topLevelGesture,
child: myBody(),
),
),
Scaffold(
backgroundColor: Colors.transparent,
body: ListView.builder(
itemBuilder: (context, index) => ListTile(
title: Text("item $index"),
onTap: () {
topLevelGesture();
print("tapped $index");
},
),
),
),
],
),
),
);
}
You can set Gesture as outside of the stack and with this inner list click also works but when you put the first Scaffold body as a clickable it's not working because the second Scaffold overlay that.
GestureDetector(
onTap(){}
child:Stack(
children[
Scaffold(
body: myBody()
)
Scaffold(
backGroundColor: Colors.transparent
body: ListView.bulder(){....}
)
]
))
You need to add clickable widget at the end in your stack widget as below:
Stack(
children[
firstWidget(),
GestureDetector(
onTap(){},
child: secondWidget()
)
]
)

How to clear objects in a listviewbuilder in flutter?

How to control listviewbuilder from outside the listview in flutter?
In a textfield I can use a controller like so: controller: Textcontroller. Can I do something similar in listviewbuilder to clear all the objects in it?
So to be exact. My code looks something like this
Expanded(
child: new ListView.builder(
itemCount: List.length,
itemBuilder: (context,index){
return new Card(
//all stuff with data
),
),
);
},
....
How would I do so that when called from another function it removes all the items in the listview?
You need a Store class that holds this list along with list manipulation methods, then you can use provider for example to access that class and render that list.
You can define a variable in the state of your widget:
var _clear = false;
When this variable is true, the list will be cleared and when it's false, the list will be displayed. You can use setState to toggle this variable. Setting the itemCount of the ListView.builder to 0 clears the list.
Full code:
var _clear = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(30.0),
child: FlatButton(
child: Text('clear'),
color: Colors.pinkAccent,
onPressed: () {
setState(() {
_clear = true;
});
},
),
),
FlatButton(
child: Text('add'),
color: Colors.greenAccent,
onPressed: () {
setState(() {
_clear = false;
});
},
),
Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: _clear ? 0 : 100,
itemBuilder: (context, index) {
return Container(
height: 300,
child: Card(
child: Center(
child: Text('$index'),
),
),
);
},
),
),
],
),
);
}

How do I get my page to scroll using Flutter?

So I'm working on a tarot app and I can't figure out how to make this page scrollable.
I'm currently using the element SingleChildScrollView to wrap my elements.
Right now it scrolls down part way and then gets stuck, and it bounces back up and I can't see the rest of my screen down below.
I'm thinking I should probably use a multi child scroll view widget but not sure how to get that to work.
What I'm looking for is to be able to display a list of elements and have them scroll on the page.
I'm sure I'm doing this wrong if someone could me out that would be awesome! :) Thanks in advance for your help and advice
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: getSpread(widget.selected),
),
ListView.builder(
itemCount: widget.selected.length,
itemBuilder: (context, index) {
final int cardNumber = widget.selected[index];
final TarotCard tarotCard = tarotMaster.tarotDeck[cardNumber];
return TarotCardDetails(tarotCard: tarotCard);
},
scrollDirection: Axis.vertical,
shrinkWrap: true,
),
BottomButton(
onTap: () {
Navigator.pushNamed(context, '/home');
print(widget.selected);
},
buttonTitle: 'BACK TO HOME',
),
],
),
),
),
);
}
}
Use physics in ListView.builder() this issue happens because flutter does not know what to scroll because it found two scrollable widget. You can specify a empty ScrollPhysics so flutter will know ListView will not need to be scrolled instead the entire page which is SingleChildScrollView widget items to be scroll
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: getSpread(widget.selected),
),
ListView.builder(
physics: ScrollPhysics(),
itemCount: widget.selected.length,
itemBuilder: (context, index) {
final int cardNumber = widget.selected[index];
final TarotCard tarotCard = tarotMaster.tarotDeck[cardNumber];
return TarotCardDetails(tarotCard: tarotCard);
},
scrollDirection: Axis.vertical,
shrinkWrap: true,
),
BottomButton(
onTap: () {
Navigator.pushNamed(context, '/home');
print(widget.selected);
},
buttonTitle: 'BACK TO HOME',
),
],
),
),
),
);
}
}
Hope this will help you.

Creating a new widget on User Click(Flat Button)

I have a Post class that creates a Post model. And I want to create this model every time a user clicks the flat button. What's the best way to go about this using the onPressed function?
It's going to be a post that holds the text the user adds to the text field and when they submit it will show on a new post.
u can try use listview.builder, this the simple example how to use it. i just edit default code when we created new project.
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: _counter,
reverse: true,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
color: Colors.red,
child: Center(child: Text('data $index')),
),
);
},
)
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
Basically you want to add items to a list, and then render the contents of that list.
List<String> messages = [];
...
onPressed: ()=> setState(()=>messages.add("SomeText"))
Then render the list:
//Can use the map() api, to convert the list of Strings into a list of widgets:
List<Widget> children = messages.map((m) => Text(m));
return ListView(children: children);
//Or, use ListView.builder() to create the widgets on demand:
return ListView.builder(
itemBuilder: (context, index)=>Text(messages[index]),
itemCount: messages.length
)
The builder method is better optimized for large lists.
here is simple demo
List<String> posts = [];
#override
Widget build(BuildContext context) {
return Scaffold(body: Column(
children: <Widget>[
ListView.builder(
itemCount: posts.length,
itemBuilder: (BuildContext ctxt, int index) {
return new Text(posts[index]);//use any widget
}
),
FloatingActionButton(
backgroundColor: Colors.white,
child: Icon(
Icons.close,
color: Colors.red,
),
onPressed: () {
setState(() {
posts.add(newpost);//add what you want
});
},
),
]),
);
}
i hope it helps..

Wrapping Gesture detector around a card

Right now i have a button on the body of the page but cannot implement this button (that routes to a different page) to just encapsulate just the card that is
child: new Text(data["data"][index]["title"]),
it is inside of an itemBuilder so i thought i had to do a GestureDetector. Ive tried to put that child into the GestureDetector method but cannot get it to work unless its the whole body.
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Listviews"),
),
body: new GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => StandardsControlPage()),
);
},
child: Container(
padding: EdgeInsets.all(16.0),
child: new ListView.builder(
itemCount: data == null ? 0 : data["data"].length,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: new Text(data["data"][index]["title"]),
);},
),
),
),
);
}}
This example wont work if i have multiple buttons to press with different routes, and was wondering If there is anyway to implement a button with that route to just that child, how would i do it?
return new Scaffold(
appBar: new AppBar(
title: new Text("Listviews"),
),
body: Container(
padding: EdgeInsets.all(16.0),
child: new ListView.builder(
itemCount: data == null ? 0 : data["data"].length,
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
child: new Card(
child: new Text(data["data"][index]["title"]),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StandardsControlPage()),
);
},
);
},
),
));
I think this will work.