Don't know what I am missing here. Want to make the Container UI like the Material Filled Text Field. Just want to know whether we can use BorderSide and borderRadius together or they work separately. And using Container only How can I achieve this?
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Container(
height: 50.0,
width: 500.0,
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 2.0, color: Color(0xFFFF7F7F7F)),
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(2),
topRight: Radius.circular(2),
),
color: Color(0xFFBFBFBF),
),
child: const Text('OK',
textAlign: TextAlign.center,
style: TextStyle(color: Color(0xFF000000))),
),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4);
}
}
I think that flutter can't handle this configuration.
You are appling bottom border in the container, and also a border radius.
Read this post: A borderRadius can only be given for uniform borders
Also read this: Add border to a Container with borderRadius in Flutter
In the second post, you may find a way to achieve what you are looking for.
Related
I want to make a container border like this but don't know what should I use?
TRy following this code . You have to customize it more to suit your exact needs. Here we are using BoxDecoration properties to set every corner radius. Check at https://dartpad.dev/?id=61468d155191404e24d99404ebb297ea. This one matches the desgn consideration to a certain level but not exact. This one is simple , other wise to make exact the same as you shown you can use ClipPath.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(right: 16,left: 16,top: 16,bottom: 64),
height: MediaQuery.of(context).size.height*0.80,
width: MediaQuery.of(context).size.width-32,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(MediaQuery.of(context).size.width*.4),
bottomRight: Radius.circular(32.0),
topRight: Radius.circular(0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.withOpacity(1),
offset: Offset(2, 2),
blurRadius: 10.0),
],
),
);
}
}
I want to create a widget similar to CircleAvatar, but not rounded.
This is CircleAvatar:
And this is the avatar I want to create:
I want to know if there is a default widget to do this, as CircleAvatar for rounded avatars.
There are so many ways to achieve it but I will only make use one.
Wrap a ClipRRect() widget around a child widget(this could be an image or any other relevant widget like a Container used in my example). Then, pass BorderRadius.circular(20.0) value to borderRadiusproperty of ClipRRect(). That is the active lines of code that create the effect.
Check below for my example:
ClipRRect(
borderRadius: BorderRadius.circular(20.0),//or 15.0
child: Container(
height: 70.0,
width: 70.0,
color: Color(0xffFF0E58),
child: Icon(Icons.volume_up, color: Colors.white, size: 50.0),
),
),
see result here
You can use ClipRRect with specified BorderRadius property like this:
see image here
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10.0)),//add border radius here
child: Image.asset('assets/01.jpg'),//add image location here
),
You can use the combination of ClipRRect and Container Widget to achieve the same, use the above code given.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(15.0),//or 15.0
child: Container(
height: 70.0,
width: 70.0,
color: const Color(0xffFF0E58),
child: const Icon(Icons.volume_up, color: Colors.white, size: 50.0),
),
);
}
}
I'm using Material Icons and Font Awesome Icons in my app, trying to make them same size. I don't know if Material Icons have padding, but they don't seem to have same size to me.
Relevant issues and SO posts about it:
https://stackoverflow.com/a/54933040/9779791
https://github.com/flutter/flutter/issues/24054
https://github.com/flutter/flutter/issues/34958
https://github.com/fluttercommunity/font_awesome_flutter/issues/23
#override
Widget build(BuildContext context) {
return Container(
width: 24,
height: 24,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: blueColor,
),
child: Container(
width: 15,
height: 15,
child: Icon(
iconData,
color: Colors.white,
),
),
);
}
}
I'm using Icons.directions_run and FontAwesomeIcons.mountain with my custom widget(I needed a circular background for them, open for suggestions), but I couldn't make them same size.
Here's how they look in Debug Painting:
Also I've removed size from Icon and use another Container to resize icon. Here's the code for that:
class ChallengeDetailIcon extends StatelessWidget {
const ChallengeDetailIcon({#required this.iconData});
final IconData iconData;
#override
Widget build(BuildContext context) {
return Container(
width: 24,
height: 24,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: blueColor,
),
child: Container(
width: 15,
height: 15,
child: Icon(
iconData,
color: Colors.white,
),
),
);
}
}
But it didn't work.
EDIT: Tried FaIcon
Code:
#override
Widget build(BuildContext context) {
return Container(
width: 24,
height: 24,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: blueColor,
),
child: Center(
child: FaIcon(
iconData,
size: 12,
color: Colors.white,
),
),
);
}
}
With size 15
notice about this: [...] Why aren't the icons aligned properly or why are the icons being cut off? #
Please use the FaIcon widget provided by the library instead of the Icon widget provided by Flutter. The Icon widget assumes all icons are square, but many Font Awesome Icons are not. [...]
https://pub.dev/packages/font_awesome_flutter
try to use FaIcon instead of Icon for fontawesome
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
return IconButton(
// Use the FaIcon Widget + FontAwesomeIcons class for the IconData
icon: FaIcon(FontAwesomeIcons.gamepad),
onPressed: () { print("Pressed"); }
);
}
}
EDIT:
A second solution for this could be controlling it with iconTheme:
theme: ThemeData.light().copyWith(
iconTheme: IconThemeData(size: 36.0, color: Colors.black87),
...
https://api.flutter.dev/flutter/widgets/IconTheme-class.html
My Code:
bool _isClicked = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0),
child: Container(
decoration: BoxDecoration(
color: _isClicked ? Colors.orange[300] : Colors.white,
borderRadius: BorderRadius.circular(30.0),
),
child: FlatButton(
splashColor: Colors.orange[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
onPressed: () {
setState(() {
_isClicked = !_isClicked;
});
},
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
),
child: Text(
foodItem,
style: TextStyle(
fontSize: 20.0,
color: _isClicked ? Colors.white : Colors.grey[700],
),
),
),
),
),
),
);
Reality:
Expectation:
When I click one button, only that turns orange the rest stay white.
When I click it back again, it turns grey again just like the rest.
I believe you want to achieve some kind toggle behavior for the buttons. Though ToggleBar widget is good for this it is not flexible with it expectations about child widgets. So a ButtonBar widget would be helpful with some kind internal state about the buttons which are clicked. Here is a working solution which might help you. The same code is available as a codepen here.
Approach
Extracted your code for the button into a widget called TButton with parameters as follows
isClicked - a boolean flag to denote if the button is clicked.
foodItem - the text to be displayed on the button.
onPressed - a callback function to be called when the button is pressed.
In the parent widget MyButtons hold a list of bool indicating the status of click for each button.
MyButtons accepts a list of foodItems. Iterate this list and generate a list of TButton widget and pass it to the ButtonBar as children.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue, scaffoldBackgroundColor: darkBlue),
home: Scaffold(
body: MyButtons(foodItems: ['Pizza', 'Burger', 'Kebab']),
),
);
}
}
class MyButtons extends StatefulWidget {
MyButtons({Key key, this.foodItems}) : super(key: key);
final List<String> foodItems;
#override
_MyButtonsState createState() => _MyButtonsState();
}
class _MyButtonsState extends State<MyButtons> {
List<bool> isSelected;
#override
initState() {
super.initState();
// initialize the selected buttons
isSelected = List<bool>.generate(widget.foodItems.length, (index) => false);
}
#override
Widget build(BuildContext context) {
return Padding(
// just for aesthetics
padding: const EdgeInsets.only(top: 80.0),
child: ButtonBar(
// use the alignment to positon the buttons in the screen horizontally
alignment: MainAxisAlignment.center,
// iterate over the foodItems and generate the buttons.
children: widget.foodItems.asMap().entries.map((entry) {
return TButton(
isClicked: isSelected[entry.key],
foodItem: entry.value,
onPressed: () {
setState(() {
isSelected[entry.key] = !isSelected[entry.key];
});
});
}).toList(),
),
);
}
}
class TButton extends StatelessWidget {
final bool isClicked;
final String foodItem;
/// OnPressed is passed from the parent. This can be changed to handle it using any state management.
final Function onPressed;
TButton(
{#required this.isClicked,
#required this.foodItem,
#required this.onPressed});
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: isClicked ? Colors.orange[300] : Colors.white,
borderRadius: BorderRadius.circular(30.0),
),
child: FlatButton(
splashColor: Colors.orange[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
onPressed: onPressed,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
),
child: Text(
foodItem,
style: TextStyle(
fontSize: 20.0,
color: isClicked ? Colors.white : Colors.grey[700],
),
),
),
),
);
}
}
I want to display a "Close keyboard" button above the keyboard when it is visible.
I know that the resizeToAvoidBottomInset can impact how the keyboard interact with the rest of the application, however it doesn't do exactly what I want.
I have a background image and others widgets (not shown in the sample below) which should not be resized and not moved when the keyboards is shown. This is an ok behavior when the resizeToAvoidBottomInset attribute is set to false.
However, I would like to add a button which should appear above the keyboard.
How can I do that? I only want one widget floating above the keyboard, not all the app.
Here is a sample code :
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
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
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
Your Positioned widget has a bottom of 0, replacing with an appropriate value should do the job.
MediaQuery.of(context).viewInsets.bottom will give you the value of the height covered by the system UI(in this case the keyboard).
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
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
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
2022 Update
A PR was merged that provides platform-synchronized animations for closing/opening the keyboard. See the PR in effect here.
Detailed Answer
To achieve keyboard-visibility-based animated padding, here are a few modifications over #10101010's great answer:
If you want the bottom change when keyboard changes visibility to be animated AND you want extra padding under your floating child then:
1- Use keyboard_visibility flutter pub
To listen when keyboard is appearing/disappearing, like so:
bool isKeyboardVisible = false;
#override
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool visible) {
isKeyboardVisible = visible;
},
);
}
Optionally you can write your own native plugins, but it's already there you can check the pub's git repo.
2- Consume visibility flag in your AnimatedPostioned:
For fine-tuned animated padding, like so:
Widget _getBody() {
double bottomPadding = 0;
if (isKeyboardVisible) {
// when keyboard is shown, our floating widget is above the keyboard and its accessories by `16`
bottomPadding = MediaQuery.of(context).viewInsets.bottom + 16;
} else {
// when keyboard is hidden, we should have default spacing
bottomPadding = 48; // MediaQuery.of(context).size.height * 0.15;
}
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
AnimatedPositioned(
duration: Duration(milliseconds: 500),
bottom: bottomPadding,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
3- Keyboard-specific animation curve and duration for synchronized animation
For now this is still an known ongoing issue
You can use the bottomSheet of a Scaffold widget.
Example:
return Scaffold(
appBar: AppBar(
title: const Text("New Game"),
),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.blue,
child: const SizedBox(
width: double.infinity,
height: 20,
child: Text("Above Keyboard"),
))
...
)
You can use bottomSheet parameter of the Scaffold, which keep a persistent bottom sheet. See below code.
class InputScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Close')),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.black,
child: const SizedBox(width: double.infinity, height: 10)),
body: Column(
children: [
const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your input here',
),
),
ElevatedButton(
onPressed: () {},
child: const Text('Submit'),
),
],
),
);
}
}
check this package, it can show a dismiss button above the keyboard.