I want to put a custom toolbar on the keypad like the image above. Is it possible in flutter? or should I write code on the iOS or Android side?
You can copy paste run full code below
Please see working demo below
You can use package https://pub.dev/packages/keyboard_overlay
Step 1: Use with HandleFocusNodesOverlayMixin
Step 2: Use FocusNodeOverlay for focusNode
Step 3: Use GetFocusNodeOverlay and set _focusNodeOverlay = GetFocusNodeOverlay(
Step 4: TextField use TextField(focusNode: _focusNodeOverlay,
code snippet
class _MyHomePageState extends State<MyHomePage>
with HandleFocusNodesOverlayMixin {
FocusNodeOverlay _focusNodeOverlay;
#override
void initState() {
_focusNodeOverlay = GetFocusNodeOverlay(
child: TopKeyboardUtil(
Container(
color: Colors.white,
height: 45,
width: MediaQueryData.fromWindow(ui.window).size.width,
child: Row(
children: [
GestureDetector(
child: Icon(Icons.save),
onTap: () => print("click"),
),
...
Spacer(),
Container(
width: 60,
child: Center(
child: DoneButtonIos(
backgroundColor: Colors.white,
textColor: Colors.green,
label: 'Post',
onSubmitted: () {
print("submit");
},
platforms: ['android', 'ios'],
),
),
),
],
),
),
),
);
working demo
full code
import 'package:flutter/material.dart';
import 'package:keyboard_overlay/keyboard_overlay.dart';
import 'dart:ui' as ui;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#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, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with HandleFocusNodesOverlayMixin {
FocusNodeOverlay _focusNodeOverlay;
#override
void initState() {
_focusNodeOverlay = GetFocusNodeOverlay(
child: TopKeyboardUtil(
Container(
color: Colors.white,
height: 45,
width: MediaQueryData.fromWindow(ui.window).size.width,
child: Row(
children: [
GestureDetector(
child: Icon(Icons.save),
onTap: () => print("click"),
),
GestureDetector(
child: Icon(Icons.computer),
onTap: () => print("click"),
),
GestureDetector(
child: Icon(Icons.home),
onTap: () => print("click"),
),
Spacer(),
Container(
width: 60,
child: Center(
child: DoneButtonIos(
backgroundColor: Colors.white,
textColor: Colors.green,
label: 'Post',
onSubmitted: () {
print("submit");
},
platforms: ['android', 'ios'],
),
),
),
],
),
),
),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
focusNode: _focusNodeOverlay,
style: TextStyle(color: Colors.grey),
decoration: InputDecoration(
labelText: 'Type Something',
labelStyle: TextStyle(color: Colors.black),
fillColor: Colors.orange,
hintStyle: TextStyle(
color: Colors.grey,
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 1.0),
),
),
),
],
),
),
);
}
}
Yes there is a way around in the flutter to achieve this.
Create a widget of the toolbar you want to add.
Set it visible on input focus.
For reference I am sharing the code how I achieve that.
class InputDoneView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: Style.lightGrey,
child: Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.only(top: 1.0, bottom: 1.0),
child: CupertinoButton(
padding: EdgeInsets.only(right: 24.0, top: 2.0, bottom: 2.0),
onPressed: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Text(
"Done",
style: TextStyle(color: Style.primaryColor,fontWeight: FontWeight.normal)
),
),
),
),
);
}
}
To call this in your main view when input field is focused in and out.
showOverlay(BuildContext context) {
if (overlayEntry != null) return;
OverlayState overlayState = Overlay.of(context);
overlayEntry = OverlayEntry(builder: (context) {
return Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom, right: 0.0, left: 0.0, child: InputDoneView());
});
overlayState.insert(overlayEntry);
}
removeOverlay() {
if (overlayEntry != null) {
overlayEntry.remove();
overlayEntry = null;
}
}
Related
I am using ShowModalBottomSheet . I want to open it from left side not from bottom in flutter..
To achieve you desire UI requirements , you should create a custom modal sheet.
It is very simple , you just have to make a container and use tween animation to make it visible and it works like a modal sheet,You can change the direction of the container from its start animating and many more.
I will try to add a code for it later.
This package help you to achieve side modal sheet.
https://pub.dev/packages/side_sheet
Or there is one more way, you should visit this link,I hope it will fullfill your requirements.
https://pub.dev/packages/modal_side_sheet
I think the first package can be more helpfull for you because it has some customization options like you can choose the side etc.
in case someone still needs help. You can use a combination of overlay and Tween to create a custom side sheet.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Custom Sidesheet',
theme: ThemeData(useMaterial3: true),
home: const MyHomePage(title: 'Custom Sidesheet'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
OverlayEntry? sideSheetOverlayEntry;
final sideSheetOverlayLayerLink = LayerLink();
bool isSidebarShown = false;
#override
void initState() {
super.initState();
}
void showSideSheet() {
final sideSheetOverlay = Overlay.of(context)!;
sideSheetOverlayEntry = OverlayEntry(
builder: (context) => Positioned(
height: MediaQuery.of(context).size.height,
child: isSidebarShown
? CompositedTransformFollower(
link: sideSheetOverlayLayerLink,
child: TweenAnimationBuilder(
tween: Tween<double>(begin: 150, end: 300),
duration: const Duration(milliseconds: 300),
builder: (BuildContext context, double size, Widget? child) {
return Material(
child: SafeArea(
child: Container(
width: size,
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
setState(() {
isSidebarShown = false;
showSideSheet();
});
},
onHover: (value) {},
child: const Icon(
Icons.close,
color: Colors.redAccent,
size: 25.0,
),
)
],
),
Column(
children: [
Container(
child: Text(
"Custom Side Sheet",
overflow: TextOverflow.ellipsis,
style: const TextStyle(color: Colors.blueGrey),
),
),
const Divider(
height: 5.0,
color: Colors.black,
),
Container(
child: Row(children: [
Icon(
Icons.dashboard,
size: 25.0,
color: Colors.blueGrey,
),
Text(
"Home",
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.blueGrey, fontSize: 25.0, fontWeight: FontWeight.w300),
)
]),
)
],
)
],
)),
),
);
},
))
: SizedBox.shrink(),
),
);
sideSheetOverlay.insert(sideSheetOverlayEntry!);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
leading: GestureDetector(
onTap: () {
setState(() {
isSidebarShown = true;
showSideSheet();
});
},
child: Icon(
Icons.menu_sharp,
size: 30.0,
),
),
),
body: Container(
color: Color.fromRGBO(223, 230, 233, 1.0),
)),
);
}
}
side sheet not active image
side sheet active image
I want a flutter counting button on the right side, as shown in the picture
In future while posting a question, please always show what you have done and how you want others to improve your code. Do not ask someone to do your work.
Check out the following code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.red,
body: Center(
child: Home(),
),
),
);
}
}
class Home extends StatefulWidget {
int counter = 0;
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.green,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () => setState(() {
widget.counter == 0 ? print('counter at 0') : widget.counter--;
}),
child: Icon(Icons.remove)),
Text('${widget.counter}'),
GestureDetector(
onTap: () {setState(() {
print('set');
widget.counter++;
});},
child: Icon(Icons.add)),
],
),);
}
}
Change the width or add padding of the parent container according to your own need.
Container( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(35),
color: Colors.green, ), child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
Text('1', style: TextStyle(color: Colors.white),),
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.add,
color: Colors.white,
),
),
], ), )
Please try this..
I hope it will help you :)
Immediately after my app start it will show a button.
As soon as this button is pressed I want to build a slider within the same button to control the volume for this sound.
All I need is to make this slider appear and not the mechanics to control the volume.
what i want to acheive is here..
my button code
void main() => runApp(Home());
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "RelaX",
home: Container(
child: Scaffold(
appBar: AppBar(
elevation: 20.0,
backgroundColor: Color(0xFF001E3D),
title: Text(
'Relax',
style: GoogleFonts.raleway(
fontSize: 30.0,
color: Color(0xFF55b9f3),
),
),
centerTitle: true,
),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("View Slider"),
onPressed: () => print("view slider")),
],
),
),
),
);
}
}
You may use the Visibility widget to set the visibility of the slider. Please see the code below. I'm using Container along with Inkwell to achieve the same effect as RaisedButton.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double _currentSliderValue = 0;
bool _sliderVisible = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Raised Button"),
),
body: Center(
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
child: Container(
decoration: BoxDecoration(
color: Colors.blue[200],
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
),
child: Material(
elevation: 2,
child: InkWell(
onTap: () {
setState(() {
_sliderVisible = !_sliderVisible;
});
},
child: Container(
width: 125.0,
height: 125.0,
child: Column(
children: [
const SizedBox(
height: 15,
),
Icon(
Icons.nightlight_round,
color: Colors.indigo[900],
size: 48,
),
const SizedBox(
height: 5,
),
Visibility(
visible: _sliderVisible,
child: Slider(
value: _currentSliderValue,
min: 0,
max: 10,
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
});
},
activeColor: Colors.indigo[900],
inactiveColor: Colors.indigo[900],
),
)
],
),
),
),
color: Colors.transparent,
),
),
),
),
);
}
}
I am new to flutter and I have created a menu button to open a side menu but however, I need some help to make it happen.
Can anyone help me implemented or guide me in my code of how to make it work. please and thank you very much!
Here is my code:
Widget _icon(IconData icon, {Color color = LightColor.iconColor}) {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(13)),
color: Theme.of(context).backgroundColor,
boxShadow: AppTheme.shadow),
child: Icon(
icon,
color: color,
),
);
}
Main:
class _MainPageState extends State<MainPage> {
bool isHomePageSelected = true;
Widget _appBar() {
return Container(
padding: AppTheme.padding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RotatedBox(
quarterTurns: 4,
child: _icon(Icons.menu, color: Colors.black54),
),
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(13)),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
boxShadow: <BoxShadow>[
BoxShadow(
color: Color(0xfff8f8f8),
blurRadius: 10,
spreadRadius: 10),
],
),
),
)
],
),
);
}
You can copy paste run full code below
You can use GlobalKey() and call _key.currentState.openDrawer();
code snippet
GlobalKey<ScaffoldState> _key = GlobalKey();
...
child: InkWell(
onTap: () {
_key.currentState.openDrawer();
},
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,
),
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;
GlobalKey<ScaffoldState> _key = GlobalKey();
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget _icon(IconData icon, {Color color = Colors.blue}) {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(13)),
color: Theme.of(context).backgroundColor,
//boxShadow: AppTheme.shadow
),
child: InkWell(
onTap: () {
_key.currentState.openDrawer();
},
child: Icon(
icon,
color: color,
),
),
);
}
bool isHomePageSelected = true;
Widget _appBar() {
return Container(
//padding: AppTheme.padding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RotatedBox(
quarterTurns: 4,
child: _icon(Icons.menu, color: Colors.black54),
),
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(13)),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
boxShadow: <BoxShadow>[
BoxShadow(
color: Color(0xfff8f8f8),
blurRadius: 10,
spreadRadius: 10),
],
),
),
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
appBar: AppBar(leading: _appBar()),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Use this code:
Scaffold.of(context).openDrawer();
Reference: https://api.flutter.dev/flutter/material/ScaffoldState/openDrawer.html
The recommended way is to call Scaffold.of(context).openDrawer();
Sample Code:
drawer: const NavBar(), // Your nav bar here
appBar: AppBar(
title: "Home".appBarText(),
leading: Builder(builder: (context) {
return IconButton(
icon: const Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer();
},
);
I have noticed creating forms with flutter. That if there is Scaffold with a text field focused i.e the key pad visible if one presses the back button.
Navigator.pop();
This results in an render flex error.
I have tried wrapping the child in the single child scroll view components also tried setting the resize to avoid bottom padding property to true.
I still get the error.
Has anyone else experienced this ?
if so what is the solution and cause of the error ?
EDIT:
import 'package:flutter/material.dart';
class SettingsScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text(
"Settings",
style: TextStyle(
color: primaryColor,
fontFamily: titleFontStyle
),
),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: primaryColor),
onPressed: () {
Navigator.of(context).pop();
},
),
centerTitle: true,
backgroundColor: Colors.white,
elevation: 0.0,
),
backgroundColor: Colors.white,
body: Container(
// width: MediaQuery.of(context).size.width - 10.0,
// height: MediaQuery.of(context).size.height,
// padding: EdgeInsets.fromLTRB(20.0, 60.0, 20.0, 0.0),
child: SettingsForm(),
),
);
}
}
class SettingsForm extends StatefulWidget {
#override
_SettingsFormState createState() => _SettingsFormState();
}
class _SettingsFormState extends State<SettingsForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
TextField(
autofocus: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
),
SizedBox(height: 8.0),
RaisedButton(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 40.0),
textColor: Colors.white,
color: primaryColor,
child: Text(
'Update',
style: TextStyle(
color: Colors.white
),
),
onPressed: () {},
),
],
),
),
);
}
}
I have tried that, and it works fine. The keyboard layout will close when you press back button and navigate you to previous page.
Here is my 2 dart files below:
main.dart (From which I navigating through)
import 'settings.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: new HomeScreen()
);
}
}
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Title"),
),
body: new Center(child: new Text("Click Mee")),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
backgroundColor: Colors.orange,
onPressed: () {
print("Clicked");
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new SettingsForm()),
);
},
),
);
}
}
settings.dart (your provided code on next screen)
class SettingsForm extends StatefulWidget {
SettingsForm();
#override
_SettingsFormState createState() => _SettingsFormState();
}
class _SettingsFormState extends State<SettingsForm> {
final _formKey = GlobalKey<FormState>();
Color primaryColor = const Color.fromRGBO(3, 155, 226, 1);
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text(
"Settings",
style: TextStyle(
color: primaryColor
),
),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: primaryColor),
onPressed: () {
FocusScope.of(context).unfocus();
Navigator.of(context).pop();
print("yes");
},
),
centerTitle: true,
backgroundColor: Colors.white,
elevation: 0.0,
),
backgroundColor: Colors.white,
body: Container(
// width: MediaQuery.of(context).size.width - 10.0,
// height: MediaQuery.of(context).size.height,
// padding: EdgeInsets.fromLTRB(20.0, 60.0, 20.0, 0.0),
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.0, right: 24.0),
children: <Widget>[
TextField(
autofocus: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
),
SizedBox(height: 8.0),
RaisedButton(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 40.0),
textColor: Colors.white,
color: primaryColor,
child: Text(
'Update',
style: TextStyle(
color: Colors.white
),
),
onPressed: () {},
),
],
),
),
),
),
);
}
}
The issue was that when I navigate back to the previous component. It was the previous component that overflowed.
I had used Column in the said component.
Converting it into ListView solved the error.