Modal with centered title and right aligned close/X button - flutter

I recently picked up Flutter and Dart and am attempting to create an app that has a modal with three parts: a header, actual content, and a footer.
For the header I am looking to add a title (Text) center aligned and a close button right aligned.
I have the following code:
Column(
children: [
Row(
children: [
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),
],
),
)
Visually, this looks like so:
At a glance this looks fine but if you stare at it for a bit it doesn't. The "Filters" title isn't actually centered because (I assume) of the width of the X-button. I am struggling to figure out how to deal with this.
What is the proper way to solve this?

You can add empty SizedBox with width as much as IconButton takes, try this:
Row(
children: [
SizedBox(
width: width: 24 +
8 +
8, // the default size of icon + two default horizontal padding for IconButton
),
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),
or you can add on other IconButton with opacity 0 to hide the button and make title center, like this:
Row(
children: [
Opacity(
opacity: 0,
child: IconButton(
icon: const Icon(Icons.close),
onPressed: () {},
),
),
Expanded(
child: Text(
"Filters",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
},
),
],
),

Related

Place buttons tabs inside panel in SlidingUpPanel package flutter

How can I place some buttons to separate between tabs in a sliding up panel? Currently what I am trying to do is place them only when the slider is opened up, ohterwise the button tabs should dissapear. I am trying to controll this behavior with ternary operator and the variable:
PanelState == PanelState.OPEN ?
but it does not work for me. The row dissapear when I close the panel.
SlidingUpPanel(
body: Body()
backdropEnabled: true,
panelSnapping: true,
collapsed: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
_pcBreedsGrouping.open();
},
child: const Text(
'Breeds',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
InkWell(
onTap: () {
_pcBreedsGrouping.open();
},
child: const Icon(
Icons.arrow_drop_down,
color: Colors.black,
size: 30,
),
),
],
),
),
minHeight: MediaQuery.of(context).size.height * 0.08,
controller: _pcBreedsGrouping,
defaultPanelState: PanelState.CLOSED,
panel: Positioned(
child: Stack(
children: [
PanelState == PanelState.OPEN
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Breeds',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold),
),
InkWell(
onTap: () => _pcBreedsGrouping.close(),
child: const Icon(
Icons.arrow_drop_up,
color: Colors.black,
size: 30,
),
),
],
)
: Container(),
Visually, the panel is like this right now and I drawed what I am trying in red:
When I close the panel I would like it to be how it is right now, without the buttons, but I do not know how to make them dissapear when is closed:
What I am trying to accomplish:

How to break this text so it doesn't overflow? - Flutter

I have a widget that builds a list from an array. Each item in the array builds a widget with some columns and rows. I want the text to break so It doesnt overflow.
I've tried adding overflow: TextOverflow.ellipsis to the Text or wrapping the Row that wraps the icon and the text that overflow with a Expanded widget, but both didn't work.
Actually it looks like this:
This is my code:
child: Column(
verticalDirection: VerticalDirection.down,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: < Widget > [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: < Widget > [
Row(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: < Widget > [
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
setState(() {
entries[index].pilldone = !entries[index].pillDone;
});
},
tooltip:
entries[index].pillDone ? 'Tomada' : 'No tomada',
backgroundColor: entries[index].pillDone ?
Colors.green :
Theme.of(context).primaryColor,
child: const Icon(Icons.check),
),
),
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
showAdaptiveActionSheet(
context: context,
cancelAction: CancelAction(
title: const Text('Cancelar'),
),
actions: < BottomSheetAction > [
BottomSheetAction(
title: const Text('Modificar'),
onPressed: () {}),
BottomSheetAction(
title: const Text('Eliminar'),
onPressed: () {
Navigator.pop(context);
_askRemovePill(entries[index].iD);
}),
]);
},
tooltip: 'Eliminar',
backgroundColor: Colors.blue,
child: const Icon(Icons.mode_edit),
)),
],
),
],
),
In your case, all you need to do is wrap your Text inside the Row with an Expanded widget
Expanded(
child: Text(/*......your text widget........*/),
),
The Expanded widget gives your Text widget horizontal constraints
IF you don't wish to see the text go on to the next line,
use the overflow property on the text
overflow : TextOverflow.ellipsis, //inside Text
Use the Wrap widget instead of the Row widget. It will break the text to the next line should there be an overflow.
Like this,
Wrap(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),

How can I modify the size of my TextButton so that it is equal to it's child Text widget's height in Flutter?

I am creating an App Login page using Flutter framework and I want the the TextButton as well as the "Forgot password?" text to be horizontally aligned in the screen, but the following code displays the button below the "Forgot Password?" text. I tried modifying the button's height and width parameters as well as modifying the spacing in the Wrap widget but I still didn't get the expected outcome. Wrapping the TextButton with SizedBox widget too didn't worked as it hid the button from the screen. Is there any other way to get the desired outcome?
Part of the screen where the TextButton and "Forgot password?" text is displayed
Wrap(
children: [
Text(
"Forgot password?",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
),
),
TextButton(
onPressed: () {},
child: Text(
"Click here",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
decoration: TextDecoration.underline,
),
),
),
],
),
if you want to Align your two buttons horizontally, just wrap them with a Row widget, userSizedbox to adjust space between them, and if necessary wrap the Row with Padding to adjust the location of buttons like;
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Row(
children: [
Text(
"Forgot password?",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
),
),
SizedBox(height: 10,),
TextButton(
onPressed: () {},
child: Text(
"Click here",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
decoration: TextDecoration.underline,
),
),
),
],
),
),
Try to below code hope its helpful to you. Wrap your Text and TextButton widget inside Row().
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"Forgot password?",
),
TextButton(
onPressed: () {
//Write here your onPressed function call
print('Button Pressed!');
},
child: Text(
"Click here",
),
),
],
),
Your Result Screen->
There is another approach to overcome this with RichText, TextSpan and TapGestureRecognizer.
To use TapGestureRecognizer, you will have to import 'package:flutter/gestures.dart'
RichText(
text: TextSpan(
text: "Forgot password? ",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
),
children: [
TextSpan(
text: "Click here",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16.0,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () => {},
),
],
),
)
You can use this instead of using a TextButton.
Result is as below.

Flutter TextFormField different font size for first character

I'm trying to implement this view.
I got very close except the smaller dollar sign, now I'm using text mask and appending the dollar sign, but of course, it has same font size view rest of the view
Here is the code
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 8),
IconButton(
icon: Image.asset("assets/images/minus.png"),
onPressed: () => {},
),
Expanded(
child: TextFormField(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold, color: kSecondaryColor),
decoration: new InputDecoration.collapsed(hintText: ''),
),
),
IconButton(
icon: Image.asset("assets/images/plus.png"),
onPressed: () => {},
),
SizedBox(width: 8),
],
),
Would be easy to do if I can change the font size of the first character of the TextField or maybe I should use different widget for only dollar sign, but I couldn't manage it to place it inside Expanded.
leadingIcon property of TextFormField puts the sign to beginning of the field, so symbol doesn't follow the text it just stays there, so that it didn't work for me.
prefixText property is also puts the text far away from actualy numbers like this, if I can fix that, that also works.
Update
You need to get rid of Expanded as it won't push the prefix widget with your text. There are other ways to achieve the same effect. You can use Flexible instead to allow TextFormField to be only as big as it needs to be. InputDecoration has a prefix: property that is not available under the .collapsed constructor, so you can remove the border using InputBorder.none instead. Overall you need to make the following changes:
Row(
children: [
SizedBox(width: 8),
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
Spacer(), //<-- This is what I've been telling to add
Flexible( //<-- Change Expanded to Flexible
child: TextFormField(
initialValue: '234',
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
decoration: InputDecoration( //<-- Removed collapsed factory constructor
border: InputBorder.none, //<-- Use this to remove the border
prefix: Text( //<-- This is your actual prefix Widget
"\$",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
),
),
),
Spacer(), //<-- This is what I've been telling to add
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
SizedBox(width: 8),
],
),
);
This is the final output
Would wrapping the TextFormField inside a Row, along with Text widget to hold $ help?
Also take care to put MainAxisSize.min, so that both the widgets stay together.
Update
Putting up the code, do not wrap Expanded, bring the changes inside child of Expanded. I have added 4 comments, which are the changes you will need to bring in.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 8),
IconButton(
icon: Icon(Icons.remove),
onPressed: () => {},
),
Expanded(
//1. Intrinsic height is used to place so that its child ROW doesn't take // the whole height
child: IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
// 2. This alignment will align $ with the bottom of textfield.
alignment: Alignment(0.0, 0.5),
child: Text(
"\$",
style: TextStyle(
//3. dollar symbol to have a different font size.
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue),
),
),
SizedBox(
//4. You might need to change the width here, this is the width available //for TextFormField. Logic used here is
//half of the (available screen width - size of the icons at left n right)
width: ((MediaQuery.of(context).size.width - 48) / 2),
child: TextFormField(
// controller: controller,
keyboardType: TextInputType.number,
// inputFormatters: [FilteringTextInputFormatter.digitsOnly],
// textAlign: TextAlign.center,
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.blue),
decoration: new InputDecoration.collapsed(hintText: ''),
),
),
]),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
SizedBox(width: 8),
],
),

Manage multiscreen size with TextField Flutter

I want to design a page for my Flutter app that can be displayed with the same aspect on all screen devices without having to scroll to see the bottom of the page. In the left image below you can see the result of my code :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
textTheme: TextTheme(
headline: TextStyle(fontSize: 64.0),
subhead: TextStyle(fontSize: 48.0),
title: TextStyle(fontSize: 36.0),
subtitle: TextStyle(fontSize: 24.0),
button: TextStyle(fontSize: 24, color: Colors.white),
body1: TextStyle(fontSize: 18.0, color: Colors.black),
body2: TextStyle(fontSize: 14.0, color: Colors.black),
),
),
home: Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.pushNamed(context, '/settings');
},
),
),
],
),
Text(
'My Title Here',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 64.0),
),
TextField(
style: Theme.of(context).textTheme.body1,
),
TextField(
style: Theme.of(context).textTheme.body1,
),
RaisedButton(child: Text('Start'), onPressed: () {}),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(Icons.star),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.star),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.star),
onPressed: () {},
),
],
),
],
),
),
),
);
}
}
It's very simple, and it's looking fine, but when I clicked on the second TextField, I have a problem of overflow like you can see in the right image : (I made my test on an iPhone 5s).
I tested to add a SingleChildScrollView, a SafeArea but when I do that I have a big blank space at the bottom of the screen and it's not what I m looking for. How can I solve this ?
Thanks for your help
Hi this is a closed issue on Flutter repo. Replace your column with ListView and instead of using alignment property add paddings and margins to your textfield
OR
You can use SingleChildScrollView as you said in the question
Both the cases you need to add padding to textField to fill the blank space