Related
How I can control the tabs , so it can shows up like this design
I try but I can't control the space before and after tabs in TabBar.
I do not understand what you mean by controlling tabs but check the below code for tab bar implementation, along with drawers and appbar action icons.
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3, //this is the number of tabs you need -- for your case it is 3
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.brown[500],
actions: [
IconButton(onPressed: () {
//This is to show a snackbar message when search button is pressed. Remove it and put your own onpressed action code
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text("Search Button Pressed"),
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.all(20),
shape: const StadiumBorder(),
action: SnackBarAction(
label: 'Dismiss',
disabledTextColor: Colors.white,
textColor: Colors.blue,
onPressed: () {
//Do whatever you want
},
),
),
);
}, icon: const Icon(Icons.search)),
],
bottom: const TabBar(
//customise your tabs here
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
indicatorWeight: 5,
labelStyle: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
tabs: [
//add your tabs here. if you add more tabs make sure you increase the length above
Tab(text: 'Doctor', iconMargin: EdgeInsets.zero,),
Tab(text: 'Community',),
Tab(text: 'Calls',),
],
),
),
//This is your app drawer
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {},
),
ListTile(
title: const Text('Item 2'),
onTap: () {},
),
],
),
),
body: const TabBarView(
//This is the view of all the tabs. The first children in the list is the first item in tabs.
children: [
Center(child: Text('Doctor Page', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),)),
Center(child: Text('Community Page', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),)),
Center(child: Text('Calls Page', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),)),
],
),
),
);
}
}
Output:
I'm creating a flutter app that requires a user to complete certain tasks in order to stop an alarm clock. It's a more immersive alarm clock app that could help stimulate the brain in order to aid in the process of waking up.
The tasks are simple questions the user has to answer. I'm utilizing TextFeild() to allow the user to input their answer. However, when I go to debug my code is redirected to a file called box.dart this is where the error is stated.
Here is the box.dart file error:
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Cannot hit test a render box with no size.'),
describeForError('The hitTest() method was called on this RenderBox'),
ErrorDescription(
'Although this node is not marked as needing layout, '
'its size is not set.',
),
ErrorHint(
'A RenderBox object must have an '
'explicit size before it can be hit-tested. Make sure '
'that the RenderBox in question sets its size during layout.',
),
]);
}
Here is my full code:
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
//import 'package:audioplayers/audio_cache.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Time Attack',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Time Attack'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
// ignore: avoid_print
print("alarm is playing");
final player = AudioCache();
//bool isPLaying = false;
await player.load('musicForapp.mp3');
AudioPlayer p = AudioPlayer();
p.audioCache = player;
await p.play(AssetSource('musicForapp.mp3'));
},
backgroundColor: Colors.red,
child: const Icon(Icons.punch_clock),
),
body: Padding(
padding: const EdgeInsets.all(170),
child: Column(
children: [
const Text(
"Click the Icon in the bottem right to simulate alarm",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const TasksPage(),
),
);
}, //on pressed
child: const Text(
"Tasks page",
style: TextStyle(color: Colors.white),
),
)
],
),
),
),
);
} //widget build
}
class TasksPage extends StatefulWidget {
const TasksPage({super.key});
#override
State<TasksPage> createState() => _TasksPageState();
}
class _TasksPageState extends State<TasksPage> {
final _textcontroller = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Tasks'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const SecondTask(),
),
);
},
backgroundColor: Colors.red,
child: const Text("Next"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"How many states are there in the United States of America?",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
Expanded(
child: TextField(
controller: _textcontroller,
decoration: InputDecoration(
hintText: "Type your answer here!",
border: const OutlineInputBorder(),
suffixIcon: IconButton(
onPressed: () {
_textcontroller.clear();
},
icon: const Icon(Icons.clear),
),
),
),
),
],
),
),
),
),
);
} //widget build
}
class SecondTask extends StatefulWidget {
const SecondTask({super.key});
#override
State<SecondTask> createState() => _SecondTask();
}
class _SecondTask extends State<SecondTask> {
final _textcontroller2 = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Tasks'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const Thirdtask(),
),
);
},
backgroundColor: Colors.red,
child: const Text("Next"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"how many oceans are there?",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
Expanded(
child: TextField(
controller: _textcontroller2,
decoration: InputDecoration(
hintText: "Type your answer here!",
border: const OutlineInputBorder(),
suffixIcon: IconButton(
onPressed: () {
_textcontroller2.clear();
},
icon: const Icon(Icons.clear),
),
),
),
),
],
),
),
),
),
);
} //widget build
}
class Thirdtask extends StatefulWidget {
const Thirdtask({super.key});
#override
State<Thirdtask> createState() => _Thirdtask();
}
class _Thirdtask extends State<Thirdtask> {
final _textcontroller3 = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Tasks'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const Finaltask(),
),
);
},
backgroundColor: Colors.red,
child: const Text("Next"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"What is 8 x 7?",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
Expanded(
child: TextField(
controller: _textcontroller3,
decoration: InputDecoration(
hintText: "Type your answer here!",
border: const OutlineInputBorder(),
suffixIcon: IconButton(
onPressed: () {
_textcontroller3.clear();
},
icon: const Icon(Icons.clear),
),
),
),
),
],
),
),
),
),
);
} //widget build
}
class Finaltask extends StatefulWidget {
const Finaltask({super.key});
#override
State<Finaltask> createState() => _Finaltask();
}
class _Finaltask extends State<Finaltask> {
final _textcontroller4 = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Tasks'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const Congrats(),
),
);
},
backgroundColor: Colors.red,
child: const Text("Submit"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Riddle: What goes up but never comes back down?",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
Expanded(
child: TextField(
controller: _textcontroller4,
decoration: InputDecoration(
hintText: "Type your answer here!",
border: const OutlineInputBorder(),
suffixIcon: IconButton(
onPressed: () {
_textcontroller4.clear();
},
icon: const Icon(Icons.clear),
),
),
),
),
],
),
),
),
),
);
} //widget build
}
class Congrats extends StatefulWidget {
const Congrats({super.key});
#override
State<Congrats> createState() => _Congrats();
}
class _Congrats extends State<Congrats> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Good Job!'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const MyHomePage(),
),
);
//player.clear('explosion.mp3'); (to stop alarm)
// ignore: avoid_print
print("Alarm has stoped");
},
backgroundColor: Colors.red,
child: const Text("Home"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const [
Expanded(
child: Text(
"Congratulations you completed your tasks, Click the home button to return home and stop the timer!",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
),
],
),
),
),
),
);
} //widget build
}
Firstly, please delete all MaterialApp (except the first on the top). Because in Flutter app there must be only one MaterialApp throughout the code.
Secondly, juste change your padding 170 to 17 for exemple. 170 is extremely big.
Use single MaterialApp on top widget as #Antonin Liehn said. Now for the TextFormField border. You need to use enabledBorder, also try others border property , Find more about OutlineInputBorder.
decoration: InputDecoration(
hintText: "Type your answer here!",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 22,
),
),
errorBorder: ,
focusedBorder: ,
disabledBorder: ,
focusedErrorBorder: ,
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 22,
),
),
Also wrap text with Flexible/Expanded widget. You cal follow this widget
class TasksPage extends StatefulWidget {
const TasksPage({super.key});
#override
State<TasksPage> createState() => _TasksPageState();
}
class _TasksPageState extends State<TasksPage> {
final _textcontroller = TextEditingController();
final border = const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 22,
));
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Taskssssssss'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const SecondTask(),
),
);
},
backgroundColor: Colors.red,
child: const Text("Next"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
child: const Text(
"How many states are there in the United States of America?",
style: TextStyle(
backgroundColor: Colors.white,
color: Colors.black,
fontSize: 30.0,
),
),
),
Expanded(
child: TextFormField(
controller: _textcontroller,
decoration: InputDecoration(
hintText: "Type your answer here!",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
),
),
errorBorder: border,
focusedBorder: border,
disabledBorder: border,
focusedErrorBorder: border,
border: border,
suffixIcon: IconButton(
onPressed: () {
_textcontroller.clear();
},
icon: const Icon(Icons.clear),
),
),
),
),
],
),
),
),
);
} //widget build
}
How do i modify leading and the action with IconButton margin/position in appbar? and what is the default margin for leading and IconButton
i can just pust the leading and the action in title with row but i want more cleaner code so i try with leading: title: actions: but the leading & actions is not in the line with the content in the body, the body has margin: 24 left and right. I'm having a hard time using leading: title: actions: from the start writing code in flutter
what i mean is to make the leading and action in the line with the body
this is my appbar code
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: Colors.white,
elevation: 1,
titleSpacing: 0,
automaticallyImplyLeading: false,
leading: IconButton(
onPressed: () {},
icon: Icon(Icons.chevron_left),
),
title: Text(
'City Guide',
style: Constants.textAppBar3,
),
actions: [
IconButton(
onPressed: () {},
icon: Image.asset(
'assets/images/icon/icon_search.png',
width: 24,
height: 24,
),
),
IconButton(
onPressed: () {},
icon: Image.asset(
'assets/images/icon/icon_save.png',
width: 24,
height: 24,
),
),
IconButton(
onPressed: () {},
icon: Image.asset(
'assets/images/icon/icon_ticket.png',
width: 24,
height: 24,
),
),
],
),
IconButton have size of icon(default 24) and have padding(constrains-min) itself to create a gesture space. With the size of Button is 48, it mean padding of IconButton is 12, your body padding is 24 so we need more 12, try wrap your leading by Padding with left: 12
Example
Try this
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
iconTheme: const IconThemeData(color: Colors.black),
backgroundColor: Colors.white,
elevation: 1,
titleSpacing: 0,
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.chevron_left),
),
title: const Text(
'City Guide',
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.favorite,
color: Colors.pink,
size: 24.0,
semanticLabel: 'Text to announce in accessibility modes',
),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.local_activity,
color: Colors.black,
size: 24.0,
semanticLabel: 'Text to announce in accessibility modes',
),
),
Container(
margin: const EdgeInsets.only(right: 15),
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.radar,
color: Colors.black,
size: 24.0,
semanticLabel: 'Text to announce in accessibility modes',
),
),
),
],
),
body: Container(
margin: const EdgeInsets.only(left: 24, right: 24),
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
I have a convex bottom bar and the last tab is a Menu that opens a drawer when clicked. But I'm having troubles when the drawer is closed. As the tab Menu only opens a drawer I wish it could return to previous tab when drawer closes, but the Menu tab keeps active. The tab only changes when it is clicked. So how can I call the onTab property of convex_tab_bar when the drawer is closed?
...
return Scaffold(
key: _scaffoldKey,
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {},
),
],
),
),
onDrawerChanged: (isOpen) {
if (!isOpen) {
setState(() {
_currentOption = _previousOption;
});
changeTab(context, _previousOption);
}
},
body: Container(
child: _currentPage,
),
bottomNavigationBar: StyleProvider(
style: Style(),
child: ConvexAppBar(
style: TabStyle.fixedCircle,
backgroundColor: Colors.white,
color: Colors.grey,
activeColor: _currentOption == 1
? const Color(0xffa98e47)
: const Color(0xff00c9ff),
items: [
TabItem(
icon: const Icon(
ReceivedIcon.receivedIcon,
color: Colors.grey,
size: 12,
),
title: AppLocalizations.of(context)!.received,
activeIcon: const Icon(
ReceivedIcon.receivedIcon,
color: Color(0xff00c9ff),
size: 12,
),
),
TabItem(
icon: const Icon(SentIcon.sentIcon, color: Colors.grey),
title: AppLocalizations.of(context)!.sent,
activeIcon: const Icon(SentIcon.sentIcon, color: Color(0xffa98e47)),
),
const TabItem(
icon: Icon(
Icons.add_rounded,
size: 48,
color: Colors.white,
)
),
TabItem(
icon: Icons.notifications,
title: AppLocalizations.of(context)!.notifications
),
TabItem(
icon: Icons.menu,
title: AppLocalizations.of(context)!.menu
),
],
onTap: (int i) {
changeTab(context, i);
},
),
),
);
try this https://github.com/hacktons/convex_bottom_bar/blob/master/doc/issue-change-active-tab-index.md (Change active tab index programmaticlly)
create a function onTapHandler in your class ... put the referece on your ConvexAppBar(onTap:onTapHandler ...) and now you are able to call the onTapHandler in your onDrawerChanged handler
I am able to create popup dialogs using Get.defaultDialog() function. I could not find a method in GetX for creating custom alert dialogs.
I am using the function below to achieve that which uses native flutter showDialog api.
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: categoryNameController,
keyboardType: TextInputType.text,
maxLines: 1,
decoration: InputDecoration(
labelText: 'Category Name',
hintMaxLines: 1,
border: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 4.0))),
),
SizedBox(
height: 30.0,
),
RaisedButton(
onPressed: () {
if (categoryNameController.text.isNotEmpty) {
var expenseCategory = ExpenseCategory(
categoryNameController.text,
id: _addExpenseController.expenseCategories.length);
_expenseController.addExpenseCategory(expenseCategory);
_addExpenseController.expenseCategories
.add(expenseCategory);
Get.back();
}
},
child: Text(
'ADD CATEGORY',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
color: Colors.redAccent,
)
],
),
elevation: 12.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)));
});
I am able to achieve that using below function
Get.defaultDialog(
title: '',
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: settingsScreenController.categoryNameController,
keyboardType: TextInputType.text,
maxLines: 1,
decoration: InputDecoration(
labelText: 'Category Name',
hintMaxLines: 1,
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green, width: 4.0))),
),
SizedBox(
height: 30.0,
),
RaisedButton(
onPressed: () {
if (settingsScreenController
.categoryNameController.text.isNotEmpty) {
var expenseCategory = ExpenseCategory(
settingsScreenController.categoryNameController.text,
id: _addExpenseController.expenseCategories.length);
settingsScreenController.addExpenseCategory(expenseCategory);
_addExpenseController.expenseCategories.add(expenseCategory);
Get.back();
} else {
Utils.showSnackBar("Enter category name");
}
},
child: Text(
'ADD CATEGORY',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
color: Colors.redAccent,
)
],
),
radius: 10.0);
But i could not remove the title area in the dialog.
Native API dialog without title
GetX dialog api with title
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main(List<String> args) {
runApp(GetMaterialApp(
title: 'My App',
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Show Dialog'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Get.defaultDialog(
);
},
child: Text('Click GetX')),
],
),
),
);
}
}