I have a TextField in my app that's immediately followed by a RaisedButton.
When I type in that TextField, the button is moved up to be just above my keyboard. If I scroll all the way down in the TextField, I can see all of the text. However, when I'm typing and go to a new line, it doesn't scroll all the way down, and the button covers part of the last line of text.
How can I make sure that the full line of text is always visible when I'm typing?
Ideally I'd like the button not to be above the keyboard when I'm typing but rather hidden by it.
If it's easier, though, I'd also be fine with a solution that ensures the TextField is scrolled all of the way down.
Here's the (simplified) relevant piece of my app:
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Title')),
body: new Column(children: <Widget>[
new Expanded(child: new Container(
child: new TextField(
maxLines: null,
controller: textController,
),
padding: new EdgeInsets.all(8.0),
)),
new RaisedButton(
onPressed: () => _myFunction(context),
child: new Center(child: new Text('Save'))
)
]),
);
}
By Adding
margin: new EdgeInsets.only(bottom: 50.0),
in Expanded Widget
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Title')),
body: new Column(children: <Widget>[
new Expanded(child: new Container(
margin: new EdgeInsets.only(bottom: 50.0),
child: new TextField(
maxLines: null,
controller: textController,
),
padding: new EdgeInsets.all(8.0),
)),
new RaisedButton(
onPressed: () => _myFunction(context),
child: new Center(child: new Text('Save'))
)
]),
);
}
Related
I'm trying to create a card with a text within a container but I would like to show only a part of the text and when the user click on "show more", show the rest. I saw a Widget to construct text like this here, but I need expand the card container either and I don't know how to do that because I need to know how many lines the text have to expand with the correctly size. Exists a way to calculate the size according the number of lines or characters?
I tried to create the card as follows, where the DescriptionText is the Widget on the link and specify a minHeight in the Container in the hope of expanding the container along with the text but did not work.
Widget _showAnswerCard(Answer answer, User user) {
return Card(
elevation: 3.0,
color: Theme.of(context).backgroundColor,
child: Container(
constraints: BoxConstraints(minHeight: 90),
padding: EdgeInsets.all(10.0),
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(flex: 1, child: _showUserAvatar(answer)),
Expanded(flex: 3, child: _showAnswerDetails(answer, user)),
],
),
));
}
Widget _showAnswerDetails(Answer answer, User user) {
return Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(
flex: 3,
child: DescriptionTextWidget(text: answer.content),
),
Expanded(
flex: 1,
child: _showAnswerOptions(),
)
],
);
}
I'll really appreciate if someone could help me with that.
Just use Wrap widget to wrap your Card widget.
Based on your link for suggested answer. I did change to use Wrap widget.
Jus do copy/paste below code and check.
import 'package:flutter/material.dart';
class ProductDetailPage extends StatelessWidget {
final String description =
"Flutter is Google’s mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.";
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text("Demo App"),
),
body: new Container(
child: new DescriptionTextWidget(text: description),
),
);
}
}
class DescriptionTextWidget extends StatefulWidget {
final String text;
DescriptionTextWidget({#required this.text});
#override
_DescriptionTextWidgetState createState() =>
new _DescriptionTextWidgetState();
}
class _DescriptionTextWidgetState extends State<DescriptionTextWidget> {
bool flag = true;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Wrap(
children: <Widget>[
Card(
margin: EdgeInsets.all(8),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
child: Column(
children: <Widget>[
Container(
child: Text(
widget.text,
overflow: flag ? TextOverflow.ellipsis : null,
style: TextStyle(
fontSize: 15,
),
),
),
InkWell(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
flag ? "show more" : "show less",
style: new TextStyle(color: Colors.blue),
),
],
),
onTap: () {
setState(() {
flag = !flag;
});
},
),
],
)),
),
],
);
}
}
Result:
The solution I can think of is to use two labels, one for displaying only one line of text and one for displaying all the text. When the button is clicked, the two labels are alternately displayed in an animated manner. There is no computer at the moment, it is not convenient to verify, I hope to give you some help in the implementation of the program.
I've the below code working fine, and showing the FlatButton under the TextField:
import 'package:flutter/material.dart';
class LocationCapture extends StatelessWidget {
LocationCapture(this.clickCallback, this.tc);
final TextEditingController tc;
final VoidCallback clickCallback;
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// Row(
// children: <Widget>[
TextField(controller: tc,),
FlatButton(
child: const Icon(Icons.my_location),
onPressed: () => clickCallback(),
)
// ])
]);
}
}
I tried adding Row to make them in single line, but it is not working, and showing blank screen!!
** UPDATE**
I was able to put them in line, by wrapping each element into a container, but still not happy for this as it require me to assign the container width, I need this to be done automatically:
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 180,
child: TextField(
controller: tc,
enabled: false,
textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(hintText: "")
)
),
Container(
child: FlatButton(
child: const Icon(Icons.my_location),
onPressed: () => clickCallback(),
)
),
]
);
This is how you can do it.
textDirection property of Row() widget will allow you to start the positioning of the children widget from the mentioned directions.
NOTE :- **You can remove or comment out the 'textDirection' if your are using MaterialApp() widget in your project. It takes care of the textDirection.
Expanded() widget is used to occupy the remaining whole space.
child: Row(
textDirection: TextDirection.rtl,
children: <Widget>[
FlatButton(onPressed: () {}, child: Text("Demo Button")),
Expanded(child: TextFormField())
],
)
I am trying to make a basic "new activity" in flutter
I have followed the flutters docs and made a button that navigates to the next page with:
Navigator.push(context, new MaterialPageRoute(builder: (context)=> new HomePage(title: title,)));
This is the build method of the 2nd page/activity (HomePage.dart)
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Home"),
textTheme: orbitTextTheme),
body: new Center(
child: new Container(
color: Color.orange,
height: 150.0,
width: 150.0,
child:new Column(
children: <Widget>[
new TextField(
controller: _textController,
decoration: new InputDecoration(
hintText: "Try to type?"
),
)
],
),
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _newReg,
tooltip: 'New reg', //externalize
backgroundColor: Color.orange,
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
BUT, the second page is not full size: (Notice the missing floating action button)
Can anyone tell me what am doing wrong?
UPDATE
Was calling the Navigator.push( in a callback from googleSignIn (which presents a modal). So putting in a small delay fixed the bug. Thanks!
This graphical bug happens whenever you pop the last visible route before pushing a new one.
Consider using pushReplacement or pushReplacementNamed instead.
I'm learning Flutter, and I've made some VERY simple modifications to the starter app, so that the floating button changes the text item to a random string from an array.
The problem is that the text is too close to the edge of the screen--needs padding. But whenever I try to add a padding: element in any number of places, VSCode doesn't seem to like it. I've seen padding used in other example code, but can't seem to get it to work in this case.
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'Welcome to DadBot!',
),
new Text(
_txt,
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _changeText,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
}
The easiest way to get padding is to wrap your widget in a Padding widget and specify the offset you want.
Fixed the issue by wrapping the Text widget in question within a Padding class, like so:
new Padding(
padding: new EdgeInsets.all(10.0),
child: new Text(
_txt,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display1,
),
),
I'm still getting used to the way Flutter does things, but I like it!
I am doing a Flutter app and managed to show the AdMob banner ad, however the ad overlaps the bottom of my app's main screen:
By following this article, I managed to make the app screen's bottom properly displayed, but the persistentFooterButtons is sacrificed, which I think is not an ideal solution.
I am thinking about putting the Scaffold object and a fixed height area into a column that is contained by a Center object, something similar to the following:
#override
Widget build(BuildContext context) {
return new Center(
child: new Column (
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Expanded (
child: _getScaffold(),
),
new Expanded (
child: new Container(height: 50.0,)
)
],
),
);
}
But in this way I get the exception "A RenderFlex overflowed by 228 pixels on the bottom":
Anybody can show me how to build such layout? I want every component of my scaffold properly displayed, with a fixed height dummy footer that is ok to be overlapped by the Admob's banner ad.
Any help is much welcome.
Jimmy
Also we can add some trick like bottomNavigationBar under the Scaffold
bottomNavigationBar: Container(
height: 50.0,
color: Colors.white,
),
This will take floating button up.
Finally I got it:
#override
Widget build(BuildContext context) {
return new Center(
child: new Column (
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Expanded (
child: _getScaffold(),
),
new Container(height: 50.0,
child: new Placeholder(color:Colors.blue))
],
),
);
}
The trick is Expanded here is for the Scaffold only, but for the dummy footer just a fixed height Container is required. Now I can display everything available from the Scaffold object.
Layout building of Flutter sometimes really confuses me...
If I understand your question well, I think you want to have your ad shown from the bottom while using a FAB. I think using a Stack widget here is a good solution, I created this example in a rush but should be enough to show you what I mean:
class AdBar extends StatefulWidget {
#override
_AdBarState createState() => new _AdBarState();
}
class _AdBarState extends State<AdBar> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new ListView(
children: new List.generate(50, (int index) {
return new Text("widgets$index");
}),
),
persistentFooterButtons:
<Widget>[
new Stack(
children: <Widget>[
new Container (
color: Colors.transparent,
child: new Material(
color: Colors.cyanAccent,
child: new InkWell(
onTap: () {
},
child: new Container(
//color: Colors.cyanAccent,
width: MediaQuery
.of(context)
.size
.width * 0.90,
height: MediaQuery
.of(context)
.size
.height * 0.25,
),
),),),
new Positioned(
right: 0.0,
child: new FloatingActionButton(
onPressed: () {}, child: new Icon(Icons.fastfood)))
],
)
]
);
}
}