Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Why is this code not working and the bottom sheet is not getting displayed. I've also retried running the code and still it doesn't work. I want to show a modal bottom sheet in flutter on a button click.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void startInputAction(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (_) {
return Container(
height: 200,
padding: EdgeInsets.all(10),
child: Text("Something"),
);
},
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Error Practice Bottom Sheet"),
backgroundColor: Colors.purple,
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.purple,
padding: EdgeInsets.all(20),
child: Text("Click here"),
onPressed: () => startInputAction(context),
)
],
),
),
),
);
}
}
MateriaApp is at same level that's why you are getting this error.
Following code will solve your issue.
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void startInputAction(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (_) {
return Container(
height: 200,
padding: EdgeInsets.all(10),
child: Text("Something"),
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Error Practice Bottom Sheet"),
backgroundColor: Colors.purple,
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.purple,
padding: EdgeInsets.all(20),
child: Text("Click here"),
onPressed: () => startInputAction(context))
],
),
),
);
}
}
Check out this example in the Flutter docs.
https://api.flutter.dev/flutter/material/showModalBottomSheet.html
Your issue might have to do with you passing the same BuildContext from the Scaffold. You should at least add a Builder widget in the body parameter of Scaffold to get the appropriate context required for this widget.
Here's the code:
class _MyAppState extends State<MyApp> {
void startInputAction(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (_) {
return Container(
height: 200,
padding: EdgeInsets.all(10),
child: Text("Something"),
);
},
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Error Practice Bottom Sheet"),
backgroundColor: Colors.purple,
),
body: Builder(
builder: (context) {
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.purple,
padding: EdgeInsets.all(20),
child: Text("Click here"),
onPressed: () => startInputAction(context),
)
],
),
);
},
),
),
);
}
}
As #Viren suggested, you need to have a MaterialApp in your code.
Check the code below:
import 'package:flutter/material.dart';
void main() => runApp(
// add your material app here
MaterialApp(
home: MyApp(),
),
);
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void startInputAction(BuildContext context){
showModalBottomSheet(
context: context,
builder: (_){
return Container(
height: 200,
padding: EdgeInsets.all(10),
child: Text("Something"),
);
}
)
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Error Practice Bottom Sheet"),
backgroundColor: Colors.purple,
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.purple,
padding: EdgeInsets.all(20),
child: Text("Click here"),
onPressed: () => startInputAction(context)
)
],
),
),
),
);
}
}
Related
I am currently working in a page where I have to show a list of apps in the device which should be half a screen only, for that i have a used a bottom drawer widget to display that ,
the main problem is every time i open the app it needs to get pulled, i don't want to do it so can some help me to display the apps without pulling the bottom drawer widget ? or else is there any other widget to do that ?
You can try bottom modal sheet or draggableScrollableSheet which has a min size
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatelessWidget(),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet'),
ElevatedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
)
],
),
),
);
},
);
},
),
);
}
}
draggableScrollableSheet
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
You can use DraggableScrollableSheet with minChildSize: .5, on this case.
return Scaffold(
bottomNavigationBar: DraggableScrollableSheet(
minChildSize: .5,
maxChildSize: 1,
builder: (context, scrollController) {
return Column(
children: [
Center(
child: Text("Title"),
),
Expanded(
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
),
],
);
},
));
More about DraggableScrollableSheet
ive been using flutter for past few months and now ive stuck in a problem where i get a list of tag names and i have to design a ui to show the tags to user as the image given below.
,
when i use ListViewBuilder and Row to display the tags as it renders all the widgets in the stragint line i get renderfelx overflow error as shown in the image below..
This is how my code looks-
Container(
height: 40,
child: ListView.builder(
shrinkWrap: true,
itemCount: brandmodels[index].tags.length,
itemBuilder: (context, index0) {
return Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
radius: 05,
backgroundColor: Color(0xffC4C4C4)),
),
Padding(
padding:
const EdgeInsets.only(right: 8.0),
child: Expanded(
child: Text(
brandmodels[index].tags[index0],
),
),
),
],
);
},
),
)
So how to bring the widgets to next line when it hits the maximum width of the screen?.
I just changed ListView to Wrap widget.
(To check whether there is overflow issue, I set Container's width to 300.
And give a background color for checking Container area.)
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> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
List data = ['biscuits', 'cakes', 'drinks', 'snacks', 'food'];
return Container(
color: Colors.yellow[100],
height: 60,
width: 300,
child: Wrap(
direction: Axis.horizontal,
children: data.map((item) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
radius: 05, backgroundColor: Color(0xffC4C4C4)),
),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Expanded(
child: Text(
item,
),
),
),
],
);
}).toList(),
),
);
}
}
I have an app with a page that has a ListView.builder().
Each row of the list is a stateful widget (match_chat_row.dart).
When you click on that stateful widget, it's navigating to another stateful widget (chat_screen.dart).
chat_screen.dart has a TextField.
The problem is that last few widgets(match_chat_row.dart) of the ListView are being disposed when the keyboard pops up on one of the first match_chat_row's chat_screen.dart.
I made this simple app to demonstrate it:
main.dart
import 'package:flutter/material.dart';
import 'match_chat_row.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final String _pageName = "Screen";
List<String> _chats = ["A","B","C","D","E","F","G","H","I","J"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _body()
);
}
_body(){
return ListView.builder(
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
);
}
Widget _buildRow(String chat) {
return
Column(
key: ValueKey<String>('chat-$chat'),
children: [
Center(
child:
MatchChatRow(
content: chat,
),
),
Divider(color: Colors.grey.withOpacity(0.20), thickness: 0.8, height: 0.0,)
],
);
}
}
match_chat_row.dart
import 'package:flutter/material.dart';
import 'chat_screen.dart';
class MatchChatRow extends StatefulWidget {
final String content;
const MatchChatRow({required this.content});
#override
_MatchChatRowState createState() => _MatchChatRowState();
}
class _MatchChatRowState extends State<MatchChatRow> {
#override
void dispose(){
print("Disposed ROW! ${widget.content}");
super.dispose();
}
#override
Widget build(BuildContext context) {
final rowHeight = 100.0;
final rowPadding = 10.0;
return
InkWell(
onTap: () =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
key: ValueKey(widget.content),
),
),
),
child:
Container(
height: rowHeight,
padding: EdgeInsets.all(rowPadding),
child: Row(
children: <Widget>[
SizedBox(
width: 20.0,
),
Expanded(
child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.content),
Text("_buildSubtitle()"),
],
)
),
],
),
)
);
}
}
chat_screen.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({required Key key,}): super(key: key);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final TextEditingController _messageController = TextEditingController();
bool _isComposingMessage = false;
bool _isChatExist = false;
bool _isLoading = false;
bool _isSending = false;
#override
void initState() {
super.initState();
}
#override
void dispose(){
print("disposed chat! ${widget.key}");
super.dispose();
}
Container _buildMessageTF() {
return Container(
margin: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
decoration: BoxDecoration(
border:
Border.all(color: Theme.of(context).accentColor.withOpacity(0.3)),
borderRadius: BorderRadius.circular(30)),
child: Row(
children: <Widget>[
Expanded(
child:
TextField(
minLines: 1,
maxLines: 4,
controller: _messageController,
textCapitalization: TextCapitalization.sentences,
onChanged: (messageText) {
setState(() => _isComposingMessage = messageText.isNotEmpty);
},
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
hintText: 'Message...'),
),
),
],
),
);
}
#override
Widget build(BuildContext context) {
return
WillPopScope(
onWillPop: () {
return Future.value(true);
},
child:
SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Hi")
),
body:
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (!_isChatExist && !_isLoading) SizedBox.shrink(),
_buildMessageTF(),
],
),
),
),
)
);
}
}
And whenever I click on the TextField and the Keyboard pops up the below widgets are being disposed (this is my debug console):
I/flutter (23372): Disposed ROW! I
I/flutter (23372): Disposed ROW! J
I/flutter (23372): Disposed ROW! H
update your _body from main
_body(){
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
),
);
}
I have the image shown using network to local file
Hero(
tag: "customWidget",
child: Container(
width: context.screenWidth / 2,
height: context.screenHeight / 4,
child: NetworkToLocal(
mediaURL: element.payload.uri,
mediaType: 'image',
),
),
),
I want to add functionality that after tapping on the image I can present this image in fullscreen mode. How it can be done with the hero widget?
In the above screenshot, an error occurs highlighting elements when adding
child: NetworkToLocal(
mediaURL: element.payload.uri,
mediaType: 'image',
),
You use the Hero Animation
import 'package:flutter/material.dart';
void main() => runApp(HeroApp());
class HeroApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Transition Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
),
body: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return DetailScreen();
}));
},
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png',
),
),
),
);
}
}
class DetailScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png',
),
),
),
),
);
}
}
I have an app which has two tabs. One of the which is the "SAVED ITEMS" tab. When I save the items (from a different screen of ALL ITEMS LIST) it gets saved and on even switching the tabs works fine. But when I close the app and reopen it, the "SAVED ITEMS" list is empty and I've to select the items again. I've used the AutomaticKeepAliveClientMixin but its not helping. Any idea on how to solve this folks?
My code:
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.white,
),
home: DefaultTabController(
length: 2,
child: Scaffold(
drawer: Drawer(),
backgroundColor: Colors.blueAccent,
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Text('AIO'),
bottom: TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.favorite)),
],
),
),
body: TabBarView(
children: <Widget>[
gridView,
SecondPage(),
],
),
),
),
);
}
#override
bool get wantKeepAlive => true;
}
SecondTab code:
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage>
with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) {
if (updatedFavorites != null)
// setState(() {
favorites = updatedFavorites;
// });
});
},
),
),
)
],
);
}
Add shared_preferences dependency in pubspec.yaml
Update your main()
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences pref = await SharedPreferences.getInstance();
pref.getStringList("favorites")?.forEach((fav){
favorites.add(int.tryParse(fav));
});
runApp(MyApp());
}
then update your SecondPage
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
Future<void> _upDateFavorites(Set<int> updatedFavorites) async {
print("secong: u$updatedFavorites");
SharedPreferences pref = await SharedPreferences.getInstance();
List<String> favoritesAsString =
updatedFavorites.map((fav) => fav.toString()).toList(); //TODO: Change `favorites` to `updatedFavorites`
print(favoritesAsString);
await pref.setStringList("favorites", favoritesAsString); //TODO: await here to store it completely
favorites = updatedFavorites;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) async {
if (updatedFavorites != null)
// setState(() {
_upDateFavorites(updatedFavorites);
// });
});
},
),
),
)
],
);
}
Widget _getFavoriteList() {
if (favorites?.isNotEmpty == true)
return _FavoriteList();
else
return _EmptyFavoriteList();
}
}
Don't forget to import 'package:shared_preferences/shared_preferences.dart'; where you use SharedPreferences
Avoid storing widget in a vaiable, if it needs to be rebuild.
So delete var favGridView = GridView.builder( ....
class _FavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: favorites.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
print("kkkkkkkkkkk: ${favorites.elementAt(index)}");
return InkWell(
child: Card(
elevation: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10),
child: Container(
child: Image.asset(
'lib/images/${images[favorites.elementAt(index)]}'), //TODO: Change this
// child: SizedBox(child: Text('yashjha'),),
// decoration: BoxDecoration(
// image: DecorationImage(
// image: AssetImage('lib/images/${images[index]}'),
// fit: BoxFit.fitWidth,
// alignment: Alignment.topCenter,
// ),
// ),
),
),
Text(nameOfSite[favorites.elementAt(index)]), //TODO: Change This
],
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Text("dsadsa")),
);
},
);
},
);
}
}
I also recommend using actions instead of FloatingButton in _EditFavoritesState. Because the floating button hides last item. which makes it unable to add to favorites
AutomaticKeepAliveClientMixin is used to retain the data when the app is running and you need to retain data while switching between tabs, pages etc.
I would suggest you use SharedPreferences to easily save data to your memory that can be retrieved when the app is started again.
SharedPreferences: https://pub.dev/packages/shared_preferences