Making a scrollable flat button in Flutter application - flutter

I'm trying to embed a flat button with a variable amount of text within a scroll view, so that the user can scroll the text but also tap it in order to perform an action. I tried doing this with a flat button embedded in a ConstrainedBox, which itself is embedded in a SingleChildScrollView.
I've tried embedding the FlatButton in a SingleChildScrollView as below. Earlier, I tried wrapping the text in an expanded widget with a SingleChildScrollView ancestor but that caused runtime errors because the requirements of the scroll view and the expanded view conflict (as far as I understand).
Widget contentScreen() {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(),
child: FlatButton(
onPressed: () {
_toggleContent();
},
child:
Column(children: <Widget>[
Container(
child: Text(
"Lorem Ipsum....",
style: TextStyle(color: Colors.white, fontSize: 20))),
]
)
)
)
);
}
The text just doesn't scroll. Instead it overflows and shows the diagonal yellow bars. I don't have a list of exactly what I've tried, but where I'm at right now is that I'm using the above code but there is no scrolling behavior as expected. :\
I tried this: How to make the Scrollable text in flutter?
This: Make scrollable Text inside container in Flutter
And this: how to make text or richtext scrollable in flutter?
Is there something about the FlatButton's behavior that just precludes scrolling? If so, how can I work around that to still get the two behaviors (ability to both scroll and tap to perform action) that I want?

Have you tried this? Why do you need Expanded widget?
Container(
height: 20.0,
child: FlatButton(
onPressed: () {},
child: SingleChildScrollView(
child: Text('Lorem ipsum'),
),
),
),
Gesture Detector should also work well.

Container(
height: 20.0,
child: FlatButton(
onPressed: () {},
child: SingleChildScrollView(
child: Text('Lorem ipsum'),
),
),
),

Related

Add text underneath iconbutton in appbar actions?

I'm currently trying to add the text ('Filter'), underneath an icon inside of the actions field within an AppBar.
Without any text being added underneath it. the action aligned exactly with the text and hamburger menu icon
Example:
There are two issues I'm having:
When I add text, the filter icon moves up a little, I want the icon to be the same spot but text added understand.
I'm getting an overflow issue
How can I fix this?
Thanks!
_appbarActions = [
Column(
children: [
IconButton(icon: const Icon(Icons.filter_alt_outlined), onPressed: () {}),
Text('Filter'),
],
)
];
Try the below snippet code:
To remove the space between IconButton and Text use Icon only;
For the overflow error you can manage the icon size with text fontSize (styles);
For events wrap the column by InkWell widget
Container(
margin: const EdgeInsets.only(right: 8.0),
child: InkWell(
onTap: () {},
child: Stack(
children: [
Center(
child: Icon(Icons.filter_alt_outlined),
),
Positioned(
child: Text(
'Filter',
style: TextStyle(fontSize: 10.0),
),
bottom: 5,
),
],
),
),
)

How to make SingleChildScrollView scrollable even content hight is lower than the scroll view height?

Unlike native iOS, Scrollable could still scroll even there is only a little height of the content inside the scroll view. So the question is:
How to make SingleChildScrollView scrollable even content hight is lower than the scroll view height?
FYI, Even I expanded my content to fit the parent container. following this link, The SingleChildScrollView still couldn't scroll.
Here this is definitely a hack but it works it doesn't seem like this should be this hard to figure out. If this is unacceptable to you let me know I'll see what else I can figure out that is more legit.
Container(
height: 400,
child: ListView(
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(vertical: 500),
child: Column(
children: <Widget>[
...numbers.map(
(number) => Text(
number.toString(),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
),
],
),
),
],
),
),
I did not try this with SingleChildScrollView

How to align an item to the bottom of a list?

I'm trying to make an item go to the bottom of a list. I've tried using Expanded with a child of SizedBox. I've also tried the Align widget. It works with a Column, but not if the parent is a SingleChildScrollView.
What it should look like:
What it does look like:
Code (what it does look like):
return Scaffold(
backgroundColor: Color(0xFFE9E9E9),
body: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16),
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: _SettingsList(tournamentId: tournamentId),
),
Expanded(child: const SizedBox()),
Align(
alignment: FractionalOffset.bottomCenter,
child: buildDeleteTournamentButton(),
),
],
),
);
I think the problem is that you are using the Expanded or Align widget as a child of the list view so it tries to put the widget directly below the other ones. To achieve the first design I would recommend one of this two ways:
Replace your ListView with a Stack and use Align to align your "Delete tournament"-Widget at the bottom.
Replace your ListView with a Column and wrap the Container in an Expanded. Place your "Delete tournament"-Widget as the second child of the Column.
I really hope I could help.

Expand Textfield if available space, set minHeight with scroll if not

I've got a Column indide a Scaffold, and one of the Column's children is a TextField. I'd like the Textfield to expand and take all the available space, but if there is not enough space (basically when the keyboard shows up), I want the Textfield to be 3 lines height min and the Column to be scrollable so the focus on the Textfield works as intended.
I've tried a lot of different widgets, like Expand, IntrinsicHeight, LayoutBuilder, ConstrainedBox, SingleChildScrollView...
But none of the tested combination did work as expected...
The SingleChildScrollView page did help me a lot but none of the example match my situation :
https://docs.flutter.io/flutter/widgets/SingleChildScrollView-class.html
Scaffold(
body: Column(
children: <Widget>[
Text("Some\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nlong\ntext"),
RaisedButton(child: Text("Some button")),
Text("Second line"),
Expanded(
child: Padding(
//Use the expand parameter instead of padding + maxLines, once released : https://github.com/flutter/flutter/pull/27205
padding: const EdgeInsets.only(top: 10, bottom: 30),
child: TextField(
decoration: InputDecoration(
hintText: "Message...",
),
maxLength: 500,
maxLengthEnforced: true,
maxLines: 50,
),
),
),
Center(
child: RaisedButton(
child: Text('OK'),
onPressed: _send,
),
)
],
),
)
With that code the first part works fine : when not keyboard is shown, the Textfield is expanded as expected.
But when the keyboard shows up, the layout overflow (because there is no SingleChildScrollView).
EDIT : the new TextField.extends property helped a bit but didn't solved my issue...

How do I remove Flutter IconButton big padding?

I want to have a row of IconButtons, all next to each other, but there seems to be pretty big padding between the actual icon, and the IconButton limits. I've already set the padding on the button to 0.
This is my component, pretty straightforward:
class ActionButtons extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.lightBlue,
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
IconButton(
icon: new Icon(ScanrIcons.reg),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
),
IconButton(
icon: new Icon(Icons.volume_up),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
)
],
),
);
}
}
I want to get rid of most of the light blue space, have my icons start earlier on the left, and closer to each other, but I can't find the way to resize the IconButton itself.
I'm almost sure this space is taken by the button itself, 'cause if I change their alignments to centerRight and centerLeft they look like this:
Making the actual icons smaller doesn't help either, the button is still big:
thanks for the help
Simply pass an empty BoxConstrains to the constraints property and a padding of zero.
IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
)
You have to pass the empty constrains because, by default, the IconButton widget assumes a minimum size of 48px.
Two ways to workaround this issue.
Still Use IconButton
Wrap the IconButton inside a Container which has a width.
For example:
Container(
padding: const EdgeInsets.all(0.0),
width: 30.0, // you can adjust the width as you need
child: IconButton(
),
),
Use GestureDetector instead of IconButton
You can also use GestureDetector instead of IconButton, recommended by Shyju Madathil.
GestureDetector( onTap: () {}, child: Icon(Icons.volume_up) )
It's not so much that there's a padding there. IconButton is a Material Design widget which follows the spec that tappable objects need to be at least 48px on each side. You can click into the IconButton implementation from any IDEs.
You can also semi-trivially take the icon_button.dart source-code and make your own IconButton that doesn't follow the Material Design specs since the whole file is just composing other widgets and is just 200 lines that are mostly comments.
Wrapping the IconButton in a container simply wont work, instead use ClipRRect and add a material Widget with an Inkwell, just make sure to give the ClipRRect widget enough border Radius 😉.
ClipRRect(
borderRadius: BorderRadius.circular(50),
child : Material(
child : InkWell(
child : Padding(
padding : const EdgeInsets.all(5),
child : Icon(
Icons.favorite_border,
),
),
onTap : () {},
),
),
)
Instead of removing a padding around an IconButton you could simply use an Icon and wrap it with a GestureDetector or InkWell as
GestureDetector(
ontap:(){}
child:Icon(...)
);
Incase you want the ripple/Ink splash effect as the IconButton provides on click wrap it with an InkWell
InkWell(
splashColor: Colors.red,
child:Icon(...)
ontap:(){}
)
though the Ink thrown on the Icon in second approach wont be so accurate as for the IconButton, you may need to do some custom implementation for that.
Here's a solution to get rid of any extra padding, using InkWell in place of IconButton:
Widget backButtonContainer = InkWell(
child: Container(
child: const Icon(
Icons.arrow_upward,
color: Colors.white,
size: 35.0,
),
),
onTap: () {
Navigator.of(_context).pop();
});
I was facing a similar issue trying to render an Icon at the location the user touches the screen. Unfortunately, the Icon class wraps your chosen icon in a SizedBox.
Reading a little of the Icon class source it turns out that each Icon can be treated as text:
Widget iconWidget = RichText(
overflow: TextOverflow.visible,
textDirection: textDirection,
text: TextSpan(
text: String.fromCharCode(icon.codePoint),
style: TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
package: icon.fontPackage,
),
),
);
So, for instance, if I want to render Icons.details to indicate where my user just pointed, without any margin, I can do something like this:
Widget _pointer = Text(
String.fromCharCode(Icons.details.codePoint),
style: TextStyle(
fontFamily: Icons.details.fontFamily,
package: Icons.details.fontPackage,
fontSize: 24.0,
color: Colors.black
),
);
Dart/Flutter source code is remarkably approachable, I highly recommend digging in a little!
A better solution is to use Transform.scale like this:
Transform.scale(
scale: 0.5, // set your value here
child: IconButton(icon: Icon(Icons.smartphone), onPressed: () {}),
)
You can use ListTile it gives you a default space between text and Icons that would fit your needs
ListTile(
leading: Icon(Icons.add), //Here Is The Icon You Want To Use
title: Text('GFG title',textScaleFactor: 1.5,), //Here Is The Text Also
trailing: Icon(Icons.done),
),
I like the following way:
InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () {},
child: Container(
padding: const EdgeInsets.all(8),
child: const Icon(Icons.favorite, color: Colors.red),
),
),
enter image description here
To show splash effect (ripple), use InkResponse:
InkResponse(
Icon(Icons.volume_up),
onTap: ...,
)
If needed, change icons size or add padding:
InkResponse(
child: Padding(
padding: ...,
child: Icon(Icons.volume_up, size: ...),
),
onTap: ...,
)