I am trying to display a long text on one line without clipping or ellipsing on a flutter web application. To do so, I want to make it horizontally scrollable. I have found this code from https://www.geeksforgeeks.org/flutter-scrollable-text/
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
//adding App Bar
appBar: AppBar(
backgroundColor: Color.fromRGBO(15, 157, 88, 1),
title: Text(
"GeeksForGeeks",
style: TextStyle(
color: Colors.white,
),
),
),
body: MyApp(),
),
));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Container(
// adding margin
margin: const EdgeInsets.all(15.0),
// adding padding
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
// adding borders around the widget
border: Border.all(
color: Colors.blueAccent,
width: 5.0,
),
),
// SingleChildScrollView should be
// wrapped in an Expanded Widget
child: Expanded(
//contains a single child which is scrollable
child: SingleChildScrollView(
//for horizontal scrolling
scrollDirection: Axis.horizontal,
child: Text(
"GeeksForGeeks is a good platform to learn programming."
" It is an educational website.",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
fontSize: 20.0,
letterSpacing: 3,
wordSpacing: 3,
),
),
),
),
),
);
}
}
But it didn't work for me.The text was clipped but not scrollable. I tried to add overflow: TextOverflow.visible to the Text widget but without result.I don't have any other idea because wrapping a Text in a SingleChildScrollView is the easiest thing I can think about for this problem.
The issue is happening because of Expanded widget. Remove this and it will work just fine,
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Container(
// adding margin
margin: const EdgeInsets.all(15.0),
// adding padding
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
// adding borders around the widget
border: Border.all(
color: Colors.blueAccent,
width: 5.0,
),
),
child: SingleChildScrollView(
//for horizontal scrolling
scrollDirection: Axis.horizontal,
child: Text(
"GeeksForGeeks is a good platform to learn programming."
" It is an educational website.",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
fontSize: 20.0,
letterSpacing: 3,
wordSpacing: 3,
),
),
),
),
);
}
}
First of all, for flutter to detect items under a scroll, you have to use ListView as of now. Add a listview widget and under that keep your text or other widgets and essentially flutter will detect your scroll widgets perfectly.
in ListView widget theres a property called scrollDirection: and you can set the value to Axis.horizontal, that does the trick.
For further references please check this out : How to create a horizontal list in flutter
tip : avoid geeksforgeeks on the go for learning flutter, learned it the hard way
Related
I am new to flutter and having come from an android dev background, having trouble placing my widgets appropriately.
I intent to place a bunch of texts/buttons one on top of another. Below is how i want to set it in my final screen. Additionally, I want to set the entire page's background color as say Red.
Given i dont need the title bar etc, I thought I'd start by not using the Scaffold at all. So here's my code as of now. I am first trying just to the 'MYAPP' text placed correctly, and not getting it to work.
void main() {
runApp(const MaterialApp(
home: MyPage(),
));
}
And in a separate file, I define MyPage
class MyPage extends StatelessWidget {
const MyPage ({Key? key}) : super(key: key);
static const TextStyle myStyle = TextStyle(
color: AppColors.complementColor,
fontSize: 80,
);
#override
Widget build(BuildContext context) {
return Container( // -> using Container, so I can set the background color as Red.
color: Colors.Red,
child: Column(
children: [
Container( // -> using container again so I can add axis etc, and margins
child: const Text(
'MYAPP',
style: myStyle,
textDirection: TextDirection.ltr,
))
],
),
);
}
}
What happens with this is that I get my MYAPP, in the top middle of screen. What i want is for it to be in the left side (and with margin from start).
I thought of adding, mainAxisAlignment: MainAxisAlignment.center and crossAxisAlignment: CrossAxisAlignment.start, but when I add crossAxisAlignment, the text box isnt getting shown at all, and even the main background color which was originally red, changes to black.
So I've got a few questions.
How do I get my text 'MYAPP' to be placed properly using the widgets I have, and why does adding crossAxisAlignment as start removes the entire widget.
If I need to add margin/padding etc, does it make sense to do the way I am doing (i.e. have a container around column)
When I set the color of root container to Red, even then the topmost bar of my android phone (the one that is used to scroll down any notifications) is not really of red color, but an offset of red. Why is that?
Is it better if I used scaffold without appbar for this?
If i dont give any axis alignment for my column, why is the text placed in the top center and why not top left? Additionally, why does the text have some padding already from the surrounding container?
Please use this code
void main() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: MyPage(),
));
}
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
static const TextStyle myStyle = TextStyle(
color: Colors.black,
fontSize: 80,
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.red,
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(left: 20.0),
child: Text(
'MYAPP',
style: myStyle,
textDirection: TextDirection.ltr,
),
),
const Padding(
padding: EdgeInsets.only(left: 25),
child: Text(
'This is my app',
),
),
const SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(left: 25.0, right: 25),
child: Row(
children: [
Expanded(
child: SizedBox(
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.transparent,
elevation: 0,
// side: const BorderSide(width: 2.0, color: Colors.black,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: const BorderSide(
color: Colors.black, width: 3))),
child: const Text(
'This is my button',
style: TextStyle(color: Colors.black),
),
onPressed: () {},
),
),
),
],
),
),
],
),
),
);
}
}
Output :
I am new to flutter, and I want to put a textbox which only continues to take text without creating a new line after it reaches the screen size limit, like I want it to be scrollable in Horizontal direction if it reaches the screen size limit, so how to do that? Here is the code for only the textbox part
Expanded(
flex: 1,
child: Container(
child: Padding(
padding: EdgeInsets.fromLTRB(0, 0, 12, 25),
child: Text(
_input,
style: GoogleFonts.titilliumWeb(
fontSize: 50.0,
color: Colors.grey[800],
),
),
),
alignment: Alignment(1.0, 1.0),
),
)
Here is a solution for both a Text and a TextField:
Scrollable Text
In order to achieve this, place your scrollable content (here, your container) inside a SingleChildScrollView.
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.amber.shade300,
padding: EdgeInsets.all(16.0),
child: Text(
'Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.',
style: GoogleFonts.titilliumWeb(
fontSize: 24.0,
color: Colors.grey[800],
),
),
),
)
Scrollable TextField
Here, I used IntrinsicWidth to make the text centered with its prefixed icon and then scrollable.
Container(
height: 48.0,
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0),
margin: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.amber.shade300,
border: Border.all(
color: Colors.brown,
width: 3.0,
),
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: IntrinsicWidth(
child: TextField(
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: 'Search',
border: InputBorder.none,
),
),
),
),
)
Full source code for easy copy-paste
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.amber.shade300,
padding: EdgeInsets.all(16.0),
child: Text(
'Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.',
style: GoogleFonts.titilliumWeb(
fontSize: 24.0,
color: Colors.grey[800],
),
),
),
),
),
);
}
}
class TransactionWidget extends StatelessWidget {
final List<Transaction> _transaction;
TransactionWidget(this._transaction);
#override
Widget build(BuildContext context) {
return Container(
height: 500,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Text(
'\$${_transaction[index].amount.toString()}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.blue),
),
decoration: BoxDecoration(
border: Border.all(width: 2, color: Colors.lightBlue)),
padding: EdgeInsets.all(8),
), // amount ICON (Left)
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_transaction[index].title,
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 17),
), // Text Title
Text(
DateFormat('dd-MM-yyyy').format(_transaction[index].date),
style: TextStyle(fontSize: 13, color: Colors.grey),
), // Text Date
],
) // Text of Title and Date
],
));
},
itemCount: _transaction.length,
));
}
}
I am building a flutter app that shows a list of transactions entered by the user. The following code is to build and display multiple transactions, however whenever I open the keyboard to enter a new transaction the overflow error occurs. Above the transaction list I have added the 'Card' widget that takes the user input and adds a new transaction.
The screenshot of the app
Scaffold(
resizeToAvoidBottomInset: false,
...
)
This will avoid resizing when keyboard opens and thus avoid any overflows
You are using a fixed size in your Container, the 'height: 500', so don't care if you are using a ListView.
Try to remove if you can, because the ListView will manage the size.
Instead of setting a height for your listview container to 500, you can wrap your listview container with the Expanded widget, this will adjust the listview to changes in the screen size and orientation.
I am not sure if I am missing something here, but in Flutter I want to crate two widgets that can be moved around independently of each other.
My current code is this:
class SurpriseReveal extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Hi",
style: TextStyle(fontSize: 20, color: Colors.pink[700]),
textAlign: TextAlign.center,
),
InkWell(
onTap: null,
splashColor: Colors.pink[900],
child: Container(
// set your desired height here
height: 150,
// set your desired width here
width: 150,
// decoration property gives it a color and makes it round like a floating action button
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.pink[300],
),
// add your desired padding here
padding: const EdgeInsets.symmetric(vertical: 10.0),
// add the child element
child: Center(
child: Text(
'Hi',
// style of the text
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.pink[900],
),
),
),
),
),
],
),
);
}
}
This creates something that looks like this:
What I would like to be able to do is choose the positioning of these widgets on the screen independently of each other. For example, If I wanted to have a gap between the text and the button, or the button off to one side.
Would I need to create two separate functions that return Widget?
To add space between your widgets you can wrap them with a Padding() widget. However, if you want to dispose your widgets independantly wherever on the screen wrap them in a stack widget and use Positionned() widget to set their constrainst.
I need to modify the line spacing. Unfortunately, the height parameter of TextStyle affects the first line as well what you can see here:
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(backgroundColor: Colors.blue.withOpacity(0.5)),
body: Container(
color: Colors.yellow,
child: Container(
color: Colors.red,
child: Text(
'first line\nsecond line',
style: TextStyle(height: 2.5, fontSize: 20),
),
),
),
);
}
}
I immediately thought of a solution: Stack with Positioned widget, with negative top value. Let's do it in two steps, first embed it in Stack.
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(backgroundColor: Colors.blue.withOpacity(0.5)),
body: Container(
color: Colors.yellow,
child: Stack(
children: <Widget>[
Container(
color: Colors.red,
child: Text(
'first line\nsecond line',
style: TextStyle(height: 2.5, fontSize: 20),
),
),
],
),
),
);
}
}
Output looks exactly like before:
Second step: wrap it with Positioned widget.
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(backgroundColor: Colors.blue.withOpacity(0.5)),
body: Container(
color: Colors.yellow,
child: Stack(
// fit: StackFit.loose,
children: <Widget>[
Positioned( // .fill
top: -20,
// bottom: 0,
// left: 50,
// right: 0,
child: Container(
color: Colors.red,
child: Text(
'first line\nsecond line',
style: TextStyle(height: 2.5, fontSize: 20),
),
),
),
],
),
),
);
}
}
This is almost what I wanted. However, if you pay attention to the colors, what was before blue, is now yellow. Adding Positioned widget makes Stack to be expanded rather than fit the content - that prevents me from using it in more complex layouts - e.g. ListView. Flutter outputs warning RenderStack object was given an infinite size during layout.
I noticed that Positioned widget does it as soon as you add any of top/left/bottom/right - before it fits the content. I tried to experiment with Stack's fit property, of Positioned with .fill initializer, but I didn't succeed.