Dynamically adjust text size in buttons inside Row - flutter

I am using localization to support multiple languages in my app. This results in having text in buttons with different length. So I need to have it being responsive.
I have two buttons in a Row(). I want to adjust the textsize inside these buttons so they never produce any overflow. Currently it looks like this in some languages:
I tried using auto_size_text with no success.
This is my code for the dialog:
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: kIsWeb ? 40.w : 100.w,
color: Theme.of(context).dialogBackgroundColor,
padding: EdgeInsets.all(15.sp),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
side: BorderSide(width: 2, color: Theme.of(context).primaryColor),
primary: Colors.black54),
onPressed: () {
Navigator.of(context).pop();
},
child: Text(AppLocalizations.of(context)!.joinGameDialogCancelButton,
style: TextStyle(fontSize: kIsWeb ? 4.sp : 12.sp)),
),
ElevatedButton(
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
backgroundColor: Theme.of(context).primaryColor,
primary: Colors.white),
onPressed: () async {
if (formKey.currentState!.validate()) {
Navigator.of(context).pop();
widget.onFinished(nameController.text.trim());
}
},
child: AutoSizeText(
AppLocalizations.of(context)!.joinGameDialogJoinButton,
style: TextStyle(fontSize: kIsWeb ? 4.sp : 14.sp),
overflow: TextOverflow.clip,
stepGranularity: 1,
maxLines: 1,
)
),
],
),
Padding(padding: EdgeInsets.only(top: 15.sp)),
Text("some eula text"),
]))
],
),
)));

You can use FittedBox Widget
FittedBox(
fit: BoxFit.scaleDown,
child: Text(
"Your Text Here",
maxLines: 1,
),
),

You can use TextPainter combined without layoutBuilder to determine if the text has overflowed or not, then dynamically resize the text to fit.
Wrapping in a layoutBuilder will determine how much space is available. The textPainter will simulate the rendering of the text and tell you if it has overflowed.
You can save your text size in a variable within the widget state, then decrement the textSize and call setState until the text fits.
See this similar question: How to check if Flutter Text widget was overflowed

Ok, here's what I used: I do not have a mobile device to test it, so I used Windows (but I guess this should not be a problem). In this way, the text gets cut off instead of getting an overflow when it can't get smaller:
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
//width: 100,
color: Theme.of(context).dialogBackgroundColor,
padding: const EdgeInsets.all(15),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
side: BorderSide(width: 2, color: Theme.of(context).primaryColor),
primary: Colors.black54),
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("weerwerewrweee", style: TextStyle(fontSize: 12)),
),
Expanded(
child: ElevatedButton(
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
backgroundColor: Theme.of(context).primaryColor,
primary: Colors.white),
onPressed: () async {
// if (formKey.currentState!.validate()) {
// Navigator.of(context).pop();
// widget.onFinished(nameController.text.trim());
// }
},
child: const AutoSizeText(
"AppLocalizations.of(context)!.joinGameDialogJoinButton,",
style: TextStyle(fontSize: 14),
overflow: TextOverflow.clip,
stepGranularity: 1,
minFontSize: 1,
maxLines: 1,
)),
),
],
),
const Padding(padding: EdgeInsets.only(top: 15)),
const Text("some eula text"),
]))
],
),
)));
The difference with the original code should be only these:
I removed the container width because on Windows it was really too small to test
I wrapped the ElevatedButton in an Expanded following some auto_size_text suggestion
I changed the minFontSize to 1 (obviously too low, but useful for testing)
I put some random texts in the buttons, leaving the second one very long
I removed the onPressed argument just for testing
This is what I got:
big window
small window
The minimum font size must be adjusted, but I think that there's no way to have a readable text AND having maxLines: 1. You probably must choose one of them, or settle for a very small text.
EDIT:
here's how it looks with maxLines: 2:
EDIT 2:
The trick using an empty Expanded to keep the button separated and avoiding a full-width second button:
[...]
const Expanded(child: Text('')),
Expanded(
child: ElevatedButton(
[...]
Result, with short text in the second button:

Please look into the answer i have added spacer() for in between space
Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
//width: 100,
color: Theme.of(context).dialogBackgroundColor,
padding: const EdgeInsets.all(15),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
side: BorderSide(width: 2, color: Theme.of(context).primaryColor),
primary: Colors.black54),
onPressed: () {
Navigator.of(context).pop();
},
child: const Text("weerwerewrweee", style: TextStyle(fontSize: 12)),
),
Spacer(),
Expanded(
flex: 3,
child: ElevatedButton(
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
backgroundColor: Theme.of(context).primaryColor,
primary: Colors.white),
onPressed: () async {
// if (formKey.currentState!.validate()) {
// Navigator.of(context).pop();
// widget.onFinished(nameController.text.trim());
// }
},
child: const Text(
"TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest",
style: TextStyle(fontSize: 14),
overflow: TextOverflow.clip,
)),
),
],
),
const Padding(padding: EdgeInsets.only(top: 15)),
const Text("some eula text"),
]))
],
),
)))

SizedBox is used for this condition only.
You can use sizedbox to size any of the Widget.
In your case,
Try with this code -
class CustomButton extends StatelessWidget {
CustomButton();
#override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
elevation: 0,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 200,
color: Theme.of(context).dialogBackgroundColor,
padding: EdgeInsets.all(5),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 80,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20.0)),
side: BorderSide(
width: 2,
color: Theme.of(context).primaryColor),
primary: Colors.black54),
onPressed: () {
Navigator.of(context).pop();
},
child: Text("Raushan is flutter developer",
style: TextStyle(fontSize: 12)),
),
),
SizedBox(
width: 80,
child: ElevatedButton(
style: TextButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20.0)),
backgroundColor:
Theme.of(context).primaryColor,
primary: Colors.white),
onPressed: () async {},
child: Text("Raushan is flutter developer",
style: TextStyle(fontSize: 12)),
),
)
],
),
Padding(padding: EdgeInsets.only(top: 15)),
Text("some eula text"),
]))
],
),
)));
}
}
I think this will fix your issue.

No need of using any dependency
Use custom class AdaptableText in your project.
adaptable_text.dart
import 'package:flutter/cupertino.dart';
class AdaptableText extends StatelessWidget {
final String text;
final TextStyle? style;
final TextAlign textAlign;
final TextDirection textDirection;
final double minimumFontScale;
final TextOverflow textOverflow;
const AdaptableText(this.text,
{this.style,
this.textAlign = TextAlign.left,
this.textDirection = TextDirection.ltr,
this.minimumFontScale = 0.5,
this.textOverflow = TextOverflow.ellipsis,
Key? key})
: super(key: key);
#override
Widget build(BuildContext context) {
TextPainter _painter = TextPainter(
text: TextSpan(text: this.text, style: this.style),
textAlign: this.textAlign,
textScaleFactor: 1,
maxLines: 100,
textDirection: this.textDirection);
return LayoutBuilder(
builder: (context, constraints) {
_painter.layout(maxWidth: constraints.maxWidth);
double textScaleFactor = 1;
if (_painter.height > constraints.maxHeight) { //
print('${_painter.size}');
_painter.textScaleFactor = minimumFontScale;
_painter.layout(maxWidth: constraints.maxWidth);
print('${_painter.size}');
if (_painter.height > constraints.maxHeight) { //
//even minimum does not fit render it with minimum size
print("Using minimum set font");
textScaleFactor = minimumFontScale;
} else if (minimumFontScale < 1) {
//binary search for valid Scale factor
int h = 100;
int l = (minimumFontScale * 100).toInt();
while (h > l) {
int mid = (l + (h - l) / 2).toInt();
double newScale = mid.toDouble()/100.0;
_painter.textScaleFactor = newScale;
_painter.layout(maxWidth: constraints.maxWidth);
if (_painter.height > constraints.maxHeight) { //
h = mid - 1;
} else {
l = mid + 1;
}
if (h <= l) {
print('${_painter.size}');
textScaleFactor = newScale - 0.01;
_painter.textScaleFactor = newScale;
_painter.layout(maxWidth: constraints.maxWidth);
break;
}
}
}
}
return Text(
this.text,
style: this.style,
textAlign: this.textAlign,
textDirection: this.textDirection,
textScaleFactor: textScaleFactor,
maxLines: 100,
overflow: textOverflow,
);
},
);
}
}
Now use this class
Container(
width: 250,
height: 20,
color: Colors.green,
child: AdaptableText(mediumSizeText, style: const TextStyle()),
),
Here i am also showing the difference between normal text, text inside size box and adaptive text
return Scaffold(
appBar: AppBar(
title: const Text('ExpandableText'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text('Normal Text'),
Text(mediumSizeText),
const SizedBox(
height: 20,
),
const Text('Container(250*20) Normal Text:'),
Container(
width: 250,
height: 20,
color: Colors.green,
child: Text(
mediumSizeText,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(
height: 20,
),
const Text('Container(250*20) => sizebox => Text:'),
Container(
width: 250,
height: 20,
color: Colors.green,
child: FittedBox(
fit: BoxFit.fitWidth,
child: Text(
mediumSizeText,
maxLines: 100,
),
),
),
const Text('Container(250*20) => AdaptableText => Text:'),
Container(
width: 250,
height: 20,
color: Colors.green,
child: AdaptableText(mediumSizeText, style: const TextStyle()),
),
],
),
);
Here is the result:

Related

Text overflow flutter

I have the next widget, which is rendered with overflow. I have tried to solve, but i don't know. Can anyone help me? The aim is to do a custom card inside listview.
I have tried to wrap with expanded buth then, the error is referenced with constraints.
import 'package:flutter/material.dart';
import '../../shared/AppTheme.dart';
class ComandaScreen extends StatefulWidget {
const ComandaScreen({Key? key}) : super(key: key);
#override
State<ComandaScreen> createState() => _ComandaScreenState();
}
class _ComandaScreenState extends State<ComandaScreen> {
bool expanded = false;
int unidades = 0;
final List<Map<String, dynamic>> _items = List.generate(
10, (index) => {'id': index, 'Nombre': 'Nuggets $index',
'isExpanded': false, "unidades": 8});
#override
Widget build(BuildContext context) {
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
);
return Scaffold(
appBar: AppBar(
title: const Text('Comanda'),
backgroundColor: AppTheme.backgroundColor,
foregroundColor: AppTheme.primaryTextColor,
elevation: 0,
),
body: SingleChildScrollView(
child: ExpansionPanelList(
elevation: 3,
// expandedHeaderPadding: const EdgeInsets.all(10),
expansionCallback: (index, isExpanded) {
setState(() {
_items[index]['isExpanded'] = !isExpanded;
});
},
animationDuration: const Duration(milliseconds: 200),
children: _items
.map(
(item) => ExpansionPanel(
canTapOnHeader: true,
// backgroundColor: item['isExpanded'] == true ? Colors.cyan[100] : Colors.white,
headerBuilder: (context, isExpanded) {
return Container(
margin: const EdgeInsets.all(10),
child: Row(children: [
const CircleAvatar(
child: Text(
'1',
textAlign: TextAlign.center,
)),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Nuggets',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text(
'Unidades: ${7}',
style: TextStyle(color: Colors.black),
),
Text(
'Pendientes: 400',
style: TextStyle(color: Colors.black),
),
],
),
const SizedBox(
width: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Precio: 10 €',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
),
Text(
'Total: 70 €',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
),
],
),
],
),
],
),
),
]),
);
},
body: ButtonBar(
alignment: MainAxisAlignment.spaceAround,
buttonHeight: 52.0,
buttonMinWidth: 90.0,
children: <Widget>[
TextButton(
style: flatButtonStyle,
onPressed: () {
setState(() {
item['unidades'] += 1;
});
},
child: Column(
children: const <Widget>[
Icon(
Icons.add,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Más'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
setState(() {
item['unidades'] -= 1;
});
},
child: Column(
children: const <Widget>[
Icon(
Icons.remove,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Menos'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.edit_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Editar'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.delete_outline_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Eliminar'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.card_giftcard_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Invitar'),
],
),
)
],
),
isExpanded: item['isExpanded'],
),
)
.toList(),
// Card_lineaComanda(flatButtonStyle),
),
),
);
}
}
I 've edited the code to show all screen widget.
Image of result of code before:
For desktop applications, you can prevent the resize with breakpoint, so the error won't happen. In the pubsec.yaml file, add the following dependency.
window_size:
git:
url: https://github.com/google/flutter-desktop-embedding.git
path: plugins/window_size
And in your main method before runapp add this code with min-width and min-height below which the app won't resize.
const double desktopMinWidth = 800.0;
const double desktopMinHeight = 600.0;
if (Platform.isMacOS || Platform.isWindows) {
setWindowMinSize(const Size(desktopMinWidth, desktopMinHeight));
setWindowMaxSize(Size.infinite);
}
Note: Once done restart your app.
For mobile, it is entirely a different case. You might need to restructure the design

Error: The method 'raisedButton' isn't defined for the class '_PomodoroState'

I'm currently doing a flutter tutorial in android studio and I have this issue,
I tried to create a class, tried to become it a variable, but no luck, also I named a file “raised_button.dart” and use the stful widget to see if it works but it doesn't work
This is my code:
import 'package:flutter/material.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'dart:async';
void main() => runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: Pomodoro(),
));
class Pomodoro extends StatefulWidget {
const Pomodoro({Key? key}) : super(key: key);
#override
State<Pomodoro> createState() => _PomodoroState();
}
class _PomodoroState extends State<Pomodoro> {
double percent = 0;
static int TimeInMinut = 240;
int TimeInSec = TimeInMinut * 60;
late Timer timer;
_StartTimer(){
TimeInMinut = 240;
int Time = TimeInMinut *60;
double SecPercent = (Time/100);
timer = Timer.periodic(Duration(seconds:1), (timer) {
setState((){
if(Time > 0){
Time--;
if(Time % 60 ==0){
TimeInMinut --;
}if(Time % SecPercent == 0){
if(percent <1){
percent += 0.01;
}else{
percent = 1;
}
}
}else{
percent = 0;
TimeInMinut = 240;
timer.cancel();
}
});
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.orangeAccent, Colors.redAccent],
begin: FractionalOffset(0.5,1)
)
),
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 25.0),
child: Text(
"Pomodoro Clock",
style: TextStyle(
color: Colors.white,
fontSize: 40.0
),
),
),
Expanded(
child: CircularPercentIndicator(
percent: percent,
animation: true,
animateFromLastPercent: true,
radius: 150.0,
lineWidth: 20.0,
progressColor: Colors.white,
center: Text(
"$TimeInMinut",
style: TextStyle(
color: Colors.white,
fontSize: 80.0
),
),
),
),
SizedBox(height: 10.0,),
Expanded(
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(30.0),topLeft: Radius.circular(30.0))
),
child: Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 20.0),
child: Column(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Text(
"Focus Time",
style: TextStyle(
fontSize: 20.0,
),
),
SizedBox(height: 10.0,),
Text(
"240",
style: TextStyle(
fontSize: 50.0
),
),
]
),
),
Expanded(
child: Column(
children: <Widget>[
Text(
"Pause Time",
style: TextStyle(
fontSize: 20.0,
),
),
SizedBox(height: 10.0,),
Text(
"20",
style: TextStyle(
fontSize: 50.0
),
),
]
),
)
],
)
),
Padding(
padding: EdgeInsets.symmetric(vertical: 28.0),
child: raisedButton(
onPressed: _StartTimer,
color: Colors.redAccent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100.0),
),
child: Padding(
padding: EdgeInsets.all(20.0),
child: Text("Start focusing",
style: TextStyle(
color: Colors.white,
fontSize: 22.0
),
),
)
),
)
],
)
),
),
),
],
),
),
),
);
}
}
and this what is shows on terminal
lib/main.dart:151:38: Error: The method 'raisedButton' isn't defined for the class '_PomodoroState'.
- '_PomodoroState' is from 'package:pomodoris/main.dart' ('lib/main.dart').
Try correcting the name to the name of an existing method, or defining a method named 'raisedButton'.
child: raisedButton(
What should I do in that particular case?
Thank you in advance.
Capitalize the R. It's RaisedButton, not raisedButton.
However, RaisedButton is depricated. Instead of
raisedButton(
onPressed: _StartTimer,
color: Colors.redAccent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100.0),
),
child: Padding(
you want to use ElevatedButton. You also need to move your styling to the new style property, where you pass the color etc. into ElevatedButton.styleFrom() constructor.
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100.0),
),
),
onPressed: _StartTimer,
child: Padding(
However...
This look is also depricated according to the Material Guidelines that Flutter follows. See how to make buttons look nice and modern here: https://material.io/components/buttons
All of the names are also the names of the widgets in Flutter. If you get stuck there, feel free to ask again!
**RaisedButton is deprecated on the Latest flutter version. You can replace RaisedButton with ElevatedButton **
ElevatedButton(
child: Text('ElevatedButton'))
RaisedButton is no longer use by Flutter new versions
instead you can use an Elevated button
ElevatedButton(
onPressed: () {
print('login clicked');
},
child: Text(
'Login',
style: TextStyle(fontSize: 18.0, fontFamily: "Brand Bold"),
))

How to change the Flutter TextButton height?

This is the output:
I try to make an app but when I use the TextButton, I get the space between two Buttons
I need one by one without space
If I use the Expanded Widget, ScrollChildView doesn't work
I try but I can't clear this stuff.
I try to make this type of TextButton.
Anyone know or have any idea about this?
import "package:flutter/material.dart";
import 'package:audioplayers/audio_cache.dart';
class Account extends StatefulWidget {
Account({Key key}) : super(key: key);
#override
_AccountState createState() => _AccountState();
}
class _AccountState extends State<Account> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Stack(
children: [
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextButton(
child: Container(
child: Text(
'One',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.red),
),
onPressed: () {
final player = AudioCache();
player.play('note1.wav');
},
),
SizedBox(
height: 1,
),
TextButton(
child: Container(
child: Text(
'Two',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.green),
),
onPressed: () {
final player = AudioCache();
player.play('note2.wav');
},
),
TextButton(
child: Container(
child: Text(
'Three',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.blue),
),
onPressed: () {
final player = AudioCache();
player.play('note3.wav');
},
),
TextButton(
child: Container(
child: Text(
'Four',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.grey),
),
onPressed: () {
final player = AudioCache();
player.play('note4.wav');
},
),
TextButton(
child: Container(
child: Text(
'Five',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.purple),
),
onPressed: () {
final player = AudioCache();
player.play('note5.wav');
},
),
],
),
),
],
),
),
),
);
}
}
You just wrap your text button with the SizedBox and set height and width as follows:
SizedBox(
height: 30,
width: 150,
child: TextButton(...),
)
Full available height:
SizedBox(
height: double.infinity, // <-- match_parent
child: TextButton(...)
)
Specific height:
SizedBox(
height: 100, // <-- Your height
child: TextButton(...)
)
In Flutter 2.0, you can set the height of the TextButton directly without depending on other widgets by changing the ButtonStyle.fixedSize:
TextButton(
child: Text('Text Button'),
style: TextButton.styleFrom(fixedSize: Size.fromHeight(150)),
),
If you want to modify all TextButtons, put it in the ThemeData like below:
return MaterialApp(
theme: ThemeData(
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(fixedSize: Size.fromHeight(150)),
),
),
Live Demo
use the following to even add your preferred size as well
N/B: child sized box is the main child widget inside Padding widget
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(30.0),
child: SizedBox(
height: 60,
width: 200,
child: ElevatedButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegistrationMenu()));
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red.shade800),
),
icon: Icon(Icons.person_add_alt_1_rounded, size: 18),
label: Text("Register Users"),
),
),
),
],
),
Wrap the TextButton in an "Expanded" Widget.
Expanded(
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.red,
padding: EdgeInsets.zero,
),
child: const Text(''),
onPressed: () {
playSound(1);
},
),
),
Another solution would be wrapping with ConstrainedBox and using minWidth & minHeight
properties.
ConstrainedBox(
constraints:BoxConstraints(
minHeight:80,
minWidth:200
),
child:TextButton(..)
)
You need to do two things
Determine text button height using
Sizedbox
Remove padding around text button using
TextStyle.StyleFrom()
SizedBox(
height: 24.0,
child: TextButton(
onPressed: () {},
child: Text('See more'),
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
),
),
),
TextButton(
 onPressed: _submitOrder,
 child: Padding(
     padding: EdgeInsets.only(left: 20, right: 20),
     child: Text("Raise")),
 style: ButtonStyle(
   shape: MaterialStateProperty.all(
   const RoundedRectangleBorder(
   borderRadius: BorderRadius.all(Radius.circular(50)),
   side: BorderSide(color: Colors.green)))),
)
TextButton(
style: ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap
),
child: Text(''),
);

Rounded AppBar in Flutter with Back button

I created a custom rounded AppBar using a code found here, but with just a title in the center.
I wanted to add a backbutton in the top left corner inside AppBar and I tried nesting a button and the text in a Row, but the result is that neither the button or the text are shown. Any help?
Here the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class RoundedAppBar extends StatelessWidget implements PreferredSizeWidget {
String title;
RoundedAppBar(this.title);
#override
Widget build(BuildContext context) {
return PreferredSize(
child: LayoutBuilder(builder: (context, constraints) {
final width =
constraints.maxWidth * 16; //per modificare "rotondità" app Bar
return OverflowBox(
maxHeight: double.infinity,
maxWidth: double.infinity,
child: SizedBox(
height: width,
width: width,
child: Padding(
padding: EdgeInsets.only(
bottom: width / 2 - preferredSize.height / 2),
child: Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
color: const Color(0xff000350),
shape: BoxShape.circle,
),
child: Row(
children: [
Align(
alignment: Alignment.centerLeft,
child: IconButton(
color: Colors.black,
icon: Icon(Icons.chevron_left),
onPressed: () => Navigator.pop(context),
),
),
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
],
)),
),
),
);
}),
preferredSize: preferredSize);
}
#override
Size get preferredSize => Size.fromHeight(80);
EDIT:
Tried using ListTile as suggested, something happened but didn't work properly.
Here the result.
child: ListTile(
title: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
leading: IconButton(
color: Colors.white,
icon: Icon(Icons.chevron_left),
onPressed: () => Navigator.pop(context),
),
),
EDIT:
I inserted your code as shown. With trial and error, using 35 as height I was able to see the title, but still no button.
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildBack(true, context),
Container(
height: 35,
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Conformity',
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.normal),
),
),
_buildBack(false, context),
],
and
Widget _buildBack(bool isPlaceHolder, BuildContext context) {
return Visibility(
child: InkWell(
child: Icon(
Icons.close,
size: 35,
),
onTap: () => Navigator.of(context, rootNavigator: true).pop('dialog'),
),
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: !isPlaceHolder,
);
}
and here the result
You can use a ListTile and use a IconButton as leading.
ListTile(
leading: IconButton(
icon: Icon(Icons.back),
title: '',
onPressed => Navigator.pop(context),
),
),
Another possibility I see:
As the child from the AppBar
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildBack(true, context),
Container(
height: height,
child: Text(
'$_title',
style: Theme.of(context).textTheme.headline2,
),
),
_buildBack(false, context),
],
),
In another place outside the builder.
Widget _buildBack(bool isPlaceHolder, Buildcontext context) {
return Visibility(
child: InkWell(
child: Icon(
Icons.close,
size: widget.height,
),
onTap: () => Navigator.of(context, rootNavigator: true).pop('dialog'),
),
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: !isPlaceHolder,
);
}}
Here there is again a row as you have tried it yourself, but this one is set up a little differently and an iconButton is built before and after the text, but so that the text remains in the center, the second one is made invisible,

adding ListView.builder

I'm trying to make the displayAccoutList() scrollable.
I've tried to use ListView but it didn't work. I'm thinking to use ListView.builder but I don't know how to create data for accountItems()
enter code here`import 'package:flutter/material.dart';
import 'app_drawer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Accounts',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Account(),
);
}
}
class Account extends StatefulWidget {
#override
_AccountState createState() => _AccountState();
}
class _AccountState extends State<Account> {
Card topArea() =>
Card(
margin: EdgeInsets.all(10.0),
elevation: 1.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(50.0))),
child: Container(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [Color(0xFFFF5722), Color(0xFFFF5722)])),
padding: EdgeInsets.all(5.0),
// color: Color(0xFF015FFF),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {},
),
Text("Savings",
style: TextStyle(color: Colors.white, fontSize: 20.0)),
IconButton(
icon: Icon(
Icons.arrow_forward,
color: Colors.white,
),
onPressed: () {},
)
],
),
Center(
child: Padding(
padding: EdgeInsets.all(5.0),
child: Text(r"£ " "100,943.33",
style: TextStyle(color: Colors.white, fontSize: 24.0)),
),
),
SizedBox(height: 35.0),
],
)),
);
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: AppDrawer(),
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.grey, //change your color here
),
backgroundColor: Colors.white,
elevation: 0.0,
title: Text(
"Accounts",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: Colors.grey,
),
onPressed: () {},
)
],
),
body: Container(
color: Colors.white,
child: Column(
children: <Widget>[
topArea(),
SizedBox(
height: 40.0,
child: Icon(Icons.refresh,
size: 35.0,
color: Color(0xFFFF5722),
),
),
displayAccoutList()
],
),
),
bottomNavigationBar: BottomAppBar(
elevation: 0.0,
child: Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
color: Color(0xFFFF5722),
// borderSide: BorderSide(color: Color(0xFF015FFF), width: 1.0),
onPressed: () {},
child: Text("ACTIVITY"),
),
OutlineButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 28.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
borderSide: BorderSide(color: Color(0xFFFF5722), width: 1.0),
onPressed: () {},
child: Text("STATEMENTS"),
),
OutlineButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 28.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
borderSide: BorderSide(color: Color(0xFFFF5722), width: 1.0),
onPressed: () {},
child: Text("DETAILS"),
)
],
),
),
)
);
}
}
Container accountItems(String item, String charge, String dateString,
String type,
{Color oddColour = Colors.white}) =>
Container(
decoration: BoxDecoration(color: oddColour),
padding:
EdgeInsets.only(top: 20.0, bottom: 20.0, left: 5.0, right: 5.0),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(item, style: TextStyle(fontSize: 16.0)),
Text(charge, style: TextStyle(fontSize: 16.0))
],
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(dateString,
style: TextStyle(color: Colors.grey, fontSize: 14.0)),
Text(type, style: TextStyle(color: Colors.grey, fontSize: 14.0))
],
),
],
),
);
displayAccoutList() {
return Container(
margin: EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
accountItems("M KING", r"+ £ 4,946.00", "15-07-19", "Credit",
oddColour: const Color(0xFFF7F7F9)),
accountItems(
"Gordon Street Tenants", r"+ £ 5,428.00", "15-07-19", "Credit"),
accountItems("Amazon EU", r"+ £ 746.00", "15-07-19", "Credit",
oddColour: const Color(0xFFF7F7F9)),
accountItems(
"Floww LTD", r"+ £ 5,526.00", "15-07-19", "Credit"),
accountItems(
"KLM", r"- £ 2,500.00", "10-07-19", "Payment",
oddColour: const Color(0xFFF7F7F9)),
],
),
);
`
The other page app_drawer.dart
`
import 'package:flutter/material.dart';
class AppDrawer extends StatefulWidget {
#override
_AppDrawerState createState() => _AppDrawerState();
}
class _AppDrawerState extends State<AppDrawer> {
#override
Widget build(BuildContext context) {
return SizedBox(
width: 160.0,
child: Drawer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50.0),
child: FlatButton.icon(
icon: Icon(
Icons.arrow_back,
color: Colors.grey,
),
onPressed: null,
label: Text("Back",
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 16.0,
color: Colors.black)),
color: Colors.black,
),
),
buildMenuItem(Icons.account_balance, "ACCOUNTS",
opacity: 1.0, color: Color(0xFFFF6E40)),
Divider(),
buildMenuItem(Icons.compare_arrows, "TRANSFER"),
Divider(),
buildMenuItem(Icons.receipt, "STATEMENTS"),
Divider(),
buildMenuItem(Icons.attach_money, "PAYMENTS"),
Divider(),
buildMenuItem(Icons.sentiment_satisfied, "INVESTMENTS"),
Divider(),
buildMenuItem(Icons.phone, "SUPPORT"),
Divider()
],
),
),
);
}
Opacity buildMenuItem(IconData icon, String title,
{double opacity = 0.3, Color color = Colors.black}) {
return Opacity(
opacity: opacity,
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 20.0,
),
Icon(
icon,
size: 50.0,
color: color,
),
SizedBox(
height: 10.0,
),
Text(title,
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0, color: color)),
SizedBox(
height: 10.0,
),
],
),
),
);
}
}
`
To able to scroll through the section and have unlimited amount of transaction
I think this is what you are going for.
In this snippet, I defined Language as a class with attributes language and rating.
Then I created a list of languages in the stateless widget TheList.
Finally, I used the listView.builder to map the list for its length and display text that shows the attributes of the languages.
Let me know if you have any questions!
import 'package:flutter/material.dart';
class Language {
const Language({this.language,this.rating});
final String language;
final String rating;
}
class TheList extends StatelessWidget {
// Builder methods rely on a set of data, such as a list.
final List<Language> _languages = [
const Language(language: "flutter", rating: "amazing"),
const Language(language: "javascript", rating: "stellar"),
const Language(language: "java", rating: "sucks"),
];
// First, make your build method like normal.
// Instead of returning Widgets, return a method that returns widgets.
// Don't forget to pass in the context!
#override
Widget build(BuildContext context) {
return _buildList(context);
}
// A builder method almost always returns a ListView.
// A ListView is a widget similar to Column or Row.
// It knows whether it needs to be scrollable or not.
// It has a constructor called builder, which it knows will
// work with a List.
ListView _buildList(context) {
return ListView.builder(
// Must have an item count equal to the number of items!
itemCount: _languages.length,
// A callback that will return a widget.
itemBuilder: (context, index) {
// In our case, a Language and its rating for each language in the list.
return Text(_languages[index].language + ": " + _languages[index].rating);
},
);
}
}