Flutter: line spacing affecting first line, problem with Positioned widget as a solution - flutter

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.

Related

Flutter - Place Text Box without using Scaffold

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 :

Horizontal scroll Text in flutter

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

How to solve stack widget problem in flutter pageview?

Im developing a quotes app as a beginner in flutter.I had used a stack widget to use both image and text in the center of my screen.And added "pageview widget" to have multiple page in my app.But the problem im facing is,whenever im trying to swipe the page,image get swiped but the text stayed the same.I mean the fist page "Text", still showing in the middle of 2nd page.Moreover i cant drag to the next page while touching the letter,its only being done via touching above or under the letter.I just wants to have a simple multipage app with text and image. How can i solve this Problem?
class OverviewScreen extends StatefulWidget {
const OverviewScreen({key, Key,}) : super(key: key);
#override
_OverviewScreenState createState() => _OverviewScreenState();
}
class _OverviewScreenState extends State<OverviewScreen> {
PageController pageController =PageController(initialPage: 0);
#override
Widget build(BuildContext context) {
return MaterialApp(
home:Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
title: Text("Hu R Rehman",
style: TextStyle(fontFamily: "MonteCarlo"),),
centerTitle: true,
leading: Icon(Icons.menu),
shape:RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(16))
),
backgroundColor: Colors.transparent,
elevation: 0,
),
body:Center(
child: Stack(
alignment: Alignment.center,
children: [
PageView(
controller: pageController,
children: [
Image(
image:AssetImage('Image/soc1.jpg'),
fit:BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
p1()
],
),
const Text('Text'
,style: TextStyle(fontSize: 31.0,
fontFamily:"MonteCarlo",
color: Colors.white,
fontWeight: FontWeight.w700 )
),
],
),
)
),
);
}
}
Here p1() is the second page
class p1 extends StatefulWidget {
#override
_p1State createState() => _p1State();
}
class _p1State extends State<p1> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
),
);
}
}
If you take a look at widget tree, There are two widgets PageView and Text placed as Stack Children, and according to widget priority render Text widget will be at the top. Also, it is independent from PageView, and there will be no effect on this Text widget by changing Pageview.
let say you wish to part it on 1st child of PageView, you can move it there by wrapping with stack like this
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
PageView(
controller: pageController,
children: [
Stack(
alignment: Alignment.center,
children: [
Image(
image: AssetImage('Image/soc1.jpg'),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
const Text(
'Text',
style: TextStyle(
fontSize: 31.0,
fontFamily: "MonteCarlo",
color: Colors.white,
fontWeight: FontWeight.w700,
),
),
],
),
p1()
],
),
],
),
)
Does it solve your issue?
Try putting Stack inside PageView children.
PageView(controller: pageController, children: [
Stack(
alignment: Alignment.center,
children: [
Image(
image: AssetImage('Image/soc1.jpg'),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
const Text('Text',
style: TextStyle(
fontSize: 31.0,
fontFamily: "MonteCarlo",
color: Colors.white,
fontWeight: FontWeight.w700)),
],
),
p1(),
],
);

Flutter : Change toolbar color in both Android and iOS

I'm very new to flutter, Just trying to create a page where top portion has a red background( stacked) and some text content above it. I want to extend the background colour to the toolbar as well. tried with AnnotatedRegion but it didn't work as expected.Image is attached for reference where toolbar still has a white background, but wanted Red color.
#override
Widget build(BuildContext context) {
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Column(
children: <Widget>[
SafeArea(
child: Stack(
children: <Widget>[
Container(
width: 500,
height: 350,
// alignment: Alignment.center,
color: Color.fromRGBO(255, 0, 0, 1),
),
Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: Text(
"Lorem ipsum dolor sit amet",
textAlign: TextAlign.center,
style: mainTextStyle,
),
),
),
Container(
padding: new EdgeInsets.symmetric(horizontal: 20.0),
)
],
),
),
Container(
child: Text("Hey Test"),
)
],
),
),
);
}
}
Just add AppBar to the scaffold and backgroundColor to red
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Color.fromRGBO(255, 0, 0, 1),
),
body: Container(
child: //widget
)
);
}
Just wrap your SafeArea widget with Container widget and set color in the Container widget
Like this
Scaffold(
body: Container(
color: Colors.green, /* Set your status bar color here */
child: SafeArea(child: Container(
/* Add your Widget here */
)),
),
);

Overlay a card partially on an image

I am trying to partially overlay a Card on an image using Stack, just like this
So this is what I have tried
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Container(
margin: const EdgeInsets.all(10.0),
child: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
ClipRRect(
child: Image.asset("assets/images/placeholder.jpg"),
borderRadius: new BorderRadius.circular(8.0),
), // image
new Positioned(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text('1625 Main Street',
style: TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('My City, CA 99984'),
leading: Icon(
Icons.restaurant_menu,
color: Colors.blue[500],
),
),
],
),
) //card
)
],
)),
);
}
However it displays the card at the bottom of the image but trying to overlap it partially over the image with the help of Stack's bottom, top arguments makes the card not display all together. How can I go about it?
I think the issue is that when you're making your stack, you're not allowing it to size itself properly. A stack sizes itself to any children which are not positioned - in your case, the ClipRRect. The ClipRRect looks like it is sized to its child image, which has a defined height. So the stack will also be this size I believe (you can turn on debug painting to see).
It looks like you want the image and white to be the background for your entire page, which means that you should be letting the stack expand to the size of the page. Wrapping your image in an alignment should do this.
The next part is that you've made your card positioned, but not defined any parameters. You want to define at the least the top, but probably also the left and right.
This works for me (although I'm not using all the same widgets, but it should apply anyways):
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Card over stack"),
),
body: Stack(
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
decoration:
BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10.0)), color: Colors.lightBlueAccent),
height: 100,
),
),
Positioned(
top: 60,
right: 10,
left: 10,
child: Card(
child: ListTile(
title: Text('1625 Main Street', style: TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('My City, CA 99984'),
leading: Icon(
Icons.restaurant_menu,
color: Colors.blue[500],
),
),
),
)
],
),
),
);
}
}