How to customize numberpicker in Flutter? - dart

I implemented numberpicker in my app.
I would like to modify the size of the numbers and the color of both highlighted value and those who are not. I managed to modify the highlighted ones wrapping it in the Theme widget and modifing the accentcolor, but don't know how I can do the other customizations?
Theme(
data: Theme.of(context).copyWith(
accentColor: Colors.red,
),
child: NumberPicker.integer(
initialValue: _currentPickerValue,
minValue: 0,
maxValue: 100,
onChanged: (newValue) =>
setState(() => _currentPickerValue = newValue)))

I digged into the code and here is something that I found
selectedStyle = themeData.textTheme.headline.copyWith(color: themeData.accentColor);
defaultStyle = themeData.textTheme.body1; This is ones which are not highlighted
to change the size or color or any other style attribute modifiy those style.
here is an example code:
final theme = Theme.of(context);
Theme(
data: theme.copyWith(
accentColor: Colors.black,// highlted color
textTheme: theme.textTheme.copyWith(
headline5: theme.textTheme.headline5.copyWith(..), //other highlighted style
bodyText2: theme.textTheme.headline5.copyWith(...), //not highlighted styles
)),
child: NumberPicker.integer(...),
);

Update your number picker package to the latest version.
new NumberPicker.integer(
...,
selectedTextStyle: TextStyle(...),
textStyle: TextStyle(...), //styles of the default text
)
Visit NumberPickec class for study properties.

Related

Changing the color and styling of the Button in Flutter

I have migrated to Flutter 2.0 which is just the new release now. In my project I have used Flat Buttons but it got deprecated now in Flutter 2.0 and the suggestion pop up to use Text Button instead of Flat Buttons.
Now the problem is in Flat Buttons there are option directly to set the properties of button such as color, padding etc. but when I replaced it with Text Button there is error in using this properties. I have checked the documentation and found that there is the property of style: ButtonStyle(backgroundcolor: ____________). But when I have put Colors.blue in the backgroundcolor property it gives me error.
So I want to know that how is the behaviour of Buttons in Flutter 2.0 and how we can style the Buttons?
My snippet of code is here in which I want to style the button.
Container(
width: 200.0,
child: TextButton(
style: ButtonStyle(), // I want to style this.
onPressed: () => Navigator.pushNamed(context, SignupPage.id),
/*color: Colors.blue,
padding: const EdgeInsets.all(10.0),*/ //Commented code is deprecated in Flutter 2.0
child: Text(
'Create Account',
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
The style argument with a backgroundcolor is the way to do it, but does not take a Color object, its type is MaterialStateProperty<Color?>? so you should provide an object of that type.
documentation is here https://api.flutter.dev/flutter/material/TextButton-class.html
and here https://api.flutter.dev/flutter/material/ButtonStyle-class.html
Buttons now have a state, so you have to define the colors for each state:
you can define one color for all the states.
ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green),
you can define a different color for each state.
ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(
(Set states) {
if (states.contains(MaterialState.pressed))
return Theme.of(context).colorScheme.primary.withOpacity(0.5);
return null; // Use the component's default.
},
),
),

how to add Circular shape to a DropdownButton in flutter?

I want to know how to customize DropdownButton by adding circular shape border like below in the picture .
It's not possible to do that in a simple way. You have to edit the classes _DropdownMenuPainter and _DropdownMenuState from dropdrown.dart, which is part of the Flutter's material package.
In _DropdownMenuPainter, change the BoxDecoration radius set in constructor:
_DropdownMenuPainter({
...
this.resize,
}) : _painter = BoxDecoration(
...
borderRadius: BorderRadius.circular(16.0), // Set the radius you want here
boxShadow: kElevationToShadow[elevation],
).createBoxPainter(),
super(repaint: resize);
In _DropdownMenuState, inside the method build(), wrap the Material widget with a ClipRRect and set its borderRadius the same as you set for _DropdownMenuPainter:
return FadeTransition(
opacity: _fadeOpacity,
child: CustomPaint(
...
child: Semantics(
...
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0), // This must be identical to the one set before
child: Material(
...
),
),
),
),
);
Notice that you'll lose those changes when you update Flutter.
Update:
I was going to make a PR to Flutter, but spent 1 hour trying to run the tests and had no success, so I'm not going to waste my time on this. Instead, I made a gist, so you can copy the whole file with the changes I made to your local Flutter copy.
https://gist.github.com/hugocbpassos/2a63594a21d7f231e97dd7dc1f18ee68
To use it, just set the radius property:
DropdownButton(
radius: 16,
items: [
...
],
);

Flutter: How to avoid flutter to automatically change text color

If I use a lighter color as primary color in flutter all text automatically goes black. If I choose an dark primary color all text in the app goes white.
I'm aware they chose a color that fits good because the color might be to dark or to light for the text color which might be annoying for the eye, but I would stil like to avoid this behavior.
I know that I can go thru all the textthemes and try to set them all but I would like to avoid that to if possible since it's hard to find all and set them correctly.
child: MaterialApp(
title: 'Test App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.teal[200], // All text is black
primaryColor: Colors.teal[800], // ALL text is white
),
Question: How do I avoid this automatic color change depending on my primary color and can I just chose one or another text color at one place?
try to add
primaryTextTheme: Typography().black, // or white
to the ThemeData
Try adding a primaryTextTheme:
ThemeData(
primaryColor: Colors.teal[200],
primaryTextTheme: TextTheme(
title: TextStyle(color: Colors.white),
subHead: TextStyle(color: Colors.white),
body1: TextStyle(color: Colors.white),
// etc...
),
),

Flutter, How to make my raw material buttons large and more tightly packed together.

I have some code that creates 7 Raw Material Buttons in the shape of a circle. However I cannot seem to change the size of the circle, or position them closer together.
Page.dart
Row(
children: <Widget>[
new ThemeButton(Colors.red, () => print("red")),
new ThemeButton(Colors.orange, () => print("orange")),
new ThemeButton(Colors.yellow, () => print("yellow")),
new ThemeButton(Colors.green, () => print("green")),
new ThemeButton(Colors.blue, () => print("blue")),
new ThemeButton(Colors.indigo, () => print("pink")),
new ThemeButton(Colors.purple, () => print("purple")),
],
),
ThemeButton.dart
#override
Widget build(BuildContext context) {
return RawMaterialButton (
shape: CircleBorder(),
fillColor: _themeColour,
elevation: 0.0,
highlightElevation: 0.0,
onPressed: () => _onPressed(),
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
);
}
Display:
So the three issue I am facing are all around the size and positioning on the element.
The Circles are too small for my liking.
The space around the circles are too wide.
I can click outside the circle and it will still register the click.
I have looked at the arguments for the Raw Material Button and cannot see what I can change. Adding a padding widget and setting it to 0 doesn't help.
Changing the padding property, unfortunately, did not work for me. However, changing the constraints parameter like in this example turned out to be quite effective:
RawMaterialButton(
constraints: BoxConstraints.tight(Size(36, 36)),
onPressed: null,
child: Icon(Icons.trending_up, size: 18),
shape: new CircleBorder(),
elevation: 0.0,
fillColor: Color.fromARGB(255, 240, 240, 240),
),
Hope it helps!
According to the docs for RawMaterialButton, there should be a padding property that you can set in the constructor, which is typical for this type of component. Try updating the padding value in the constructor of the button instead of adding a new Widget. To be clear, trying setting padding to EdgeInsets.all(0.0).
For further sizing, you can start to look at the Row class properties, specifically MainAxisSize, or wrapping them in variations of the Flexible Widget family.

How do I auto scale down a font in a Text widget to fit the max number of lines?

I'm trying to use BoxFit.scaleDown in a FittedBox's fit property to scale the font down in a Text widget to accommodate strings of varying length.
However, the below code will scale down the entire string and make it fit on one line, For the below example, I would like the font scaled down so that the string can fit on two lines (per maxLines property of the Text widget).
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Multi-Line Label Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Multi-Line Label Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final textStyle = const TextStyle(fontSize: 28.0);
final text =
'Lorem Ipsum is simply dummy text of the printing and typesetting'
'industry. Lorem Ipsum has been the industry\'s standard dummy text'
'ever since the 1500s, when an unknown printer took a galley of type'
'and scrambled it to make a type specimen book.';
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FittedBox(
fit: BoxFit.scaleDown,
child: new Text(
text,
maxLines: 2,
style: textStyle,
textAlign: TextAlign.center,
),
),
],
),
),
);
}
}
An easy drop-in solution is to use FittedBox with fit: BoxFit.scaleDown:
Container(
width: 100.0,
child: FittedBox(
fit: BoxFit.scaleDown,
// Optionally apply `alignment` to position the text inside the box:
//alignment: Alignment.topRight,
child: SizedBox(
child: Text('\$1,299.99'),
)
)
you can use the auto text package
https://pub.dartlang.org/packages/auto_size_text
after install it, just replace all of 'Text' to 'AutoSizeText' and you will find every things will be good :)
We got 2 ready-to-use solutions to this depending on the constraints you want to have.
1. Scale only
This solution works if you like how the layout looks on some reference screen size, want to treat the text area as a box and just scale up or down the entire box given other sized screens.
Take a reference screen. Lay everything out as intended. Find out the size of the box containing the text (by showing the render tree by pressing 't' during debug for instance). Then wrap the text containing box with a SizedBox of the same size as measured. Then wrap that with your FittedBox.
The restriction is basically that your text is laid out exactly the same way on all screens and you'll have the same aspect ratio for the text box.
2. Multiple references
Given a parent with variable size, first use a LayoutBuilder to get the parent's size during runtime, and then manually adjust the font size in the child text widget to make sure it fits.
The text layout is more fluid and the containing box can have different aspect ratios, but you'd have to check on as many screens sizes as the font size switches you have. Though it's easy to make sure that the text doesn't overflow at any screen size using widget tests
We can also create more complex but automatic means if there are more concrete examples of generalized use cases involving dependent font scaling
This happened in my app:
I solved by calculating the maximum number of chars shown in one line and reducing dynamically the Text FontSize if its string length is greater.
Get the char width of your text
First of all, I calculated the width of every char shown.
For doing that I needed the effective container width and the number of chars shown.
To get the screen width (that actually is the container width), I put my Text widget inside a LayoutBuilder:
new LayoutBuilder(builder: (context, constraint) {
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//I'm going to change this dinamically
double fontSize = 33.0;
//return my widget
return new Text(
_brand.name,
maxLines: 1,
style: new TextStyle(fontSize: fontSize),
);
}
To get the chars shown before a new line, I put a big string in the Text and I manually counted how many chars were shown in one line. I put this value in a const (maxCharInOneLine) and then I was able to calculate the single char width: I divided the maximum witdh by maxCharInOneLine:
new LayoutBuilder(builder: (context, constraint) {
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//chars shown manually counted
const int maxCharInOneLine = 17;
//single char width
int charWidth = (maxWidth / maxCharInOneLine).toInt();
//TO RUN IN DEBUG MODE
print("Char size with this screen and Text's TextStyle: " + charWidth.toString());
...
}
I runned the code above in the debug mode in order to get the charSize value, then I put is in a const and I removed that code that is useless at runtime.
Change dynamically the font
Now, with a constant char width and a variable container width (got from the LayoutBuilder) you can have every time the maximum number of chars that fits in one line.
new LayoutBuilder(builder: (context, constraint) {
const int charWidth=16;
//screen width got from the LayoutBuilder
double maxWidth = constraint.biggest.width;
//dinamically get the char number that fits in one line with this screen
int charsPerLine = (maxWidth / charWidth).toInt();
//if it doesn't fit in a line, reduce the fontSize
double fontSize = (_brand.name.length <= charsPerLine) ? 33.0 : 23.0;
return new Text(
_brand.name,
maxLines: 1,
style: new TextStyle(fontSize: fontSize),
);
}
The result:
My solution is not the best, but it works well in my case.
I'd like to get feedbacks. :)
EDIT Aug 2020: You can now simply use the library AutoSizeText
Just wrap your Text inside a FittedBox widget without setting any fit value.
SizedBox(
width: 10,
child: FittedBox(
child: Text('Your Text'),
),
)
Did you try using the Flexible widget
new Flexible(
child: new Text(
text,
style: textStyle,
textAlign: TextAlign.center,
),
),

Resources