I'm trying to figuring out how I can show my text on multiple lines. Here's my code:
title: Row(
children: [
Text(
_snapshot.data['username'],
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w700),
),
SizedBox(width: 5.0),
Text(
"${comment.data()['comment']}",
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w500),
)
],
),
But when the text is too long I get this error:
When I wrapped second text with expanded it looks like that
I want something like this
I think you can try use a RichText, see this code:
RichText(
text: TextSpan(
text: 'Title ', // _snapshot.data['username']
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black),
children: <TextSpan>[
TextSpan(//"${comment.data()['comment']}"
text: 'this is a very long text text text'
'text text text text text text text text text text'
'text text text text text text text text text',
style: TextStyle(
fontWeight: FontWeight.normal,
),
)
],
),
),
Using "maxLines" (Text widget) property should work, It should wrap the text.
This looks like a use-case for RichText because the only difference between the two Text widgets is the font-weight.
You can update your code to use this instead and add as much space as you want before ${comment.data()['comment']}:
title: RichText(
text: TextSpan(
title: _snapshot.data['username'],
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w700),
children: <TextSpan>[
TextSpan(text: " ${comment.data()['comment']}", style: TextStyle(fontWeight: FontWeight.w500)),
],
),
)
I use this way.
https://i.stack.imgur.com/6WrQi.png
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: ListView(
children: const <Widget>[
Card(
child: ListTile(
leading: FlutterLogo(size: 56.0),
title: Text('Two-line ListTile Two-line ListTile Two-line ListTile'),
subtitle: Text('Here is a second line'),
),
),
Card(
child: ListTile(
leading: FlutterLogo(size: 72.0),
title: Text('Three-line ListTile'),
subtitle: Text(
'A sufficiently long subtitle warrants three lines.'
),
isThreeLine: true,
),
),
],
),
),
);
}
}
Just add your Text widget inside a Sizedbox or Container with fixed width, and it will flow into multiline.
SizedBox(
width: 200,
child: Text("Some long text",
maxLines: 3,
style: const TextStyle(fontSize: 14, color: colorWhite))
)
You can use maxLine and overflow properties to control how much lines the text can run through, and what happens when the maximum line is exceeded
Related
I'm creating instagram app clone in flutter with firebase at backend. It's a beginner level project so the coding and structure is basic.
I am stuck at adding comment section under each post. I'm using streambuilder to display data and trying to create a function in which with every image is on the feed screen would have a comment box which is connected to the current-image document in cloud-firestore.
Below is my code and images of database:
class FeedScreen extends StatefulWidget {
const FeedScreen({Key? key}) : super(key: key);
#override
_FeedScreenState createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
User? user = FirebaseAuth.instance.currentUser;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomNavigationBar: BottomNavigation(),
appBar: AppBar(
backgroundColor: Colors.black,
automaticallyImplyLeading: false,
title: Text(
"Platform",
style: TextStyle(
color: Colors.white,
fontSize: 32.96,
fontWeight: FontWeight.w500,
fontFamily: 'Yaldevi',
),
),
),
body: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.hasData){
final List<DocumentSnapshot> documents = snapshot.data!.docs;
return ListView(
children: documents.map((doc) => SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: doc['profileImage'] == null ?
CircleAvatar(
radius: 16.6,
backgroundColor: Colors.white24,
) :
CircleAvatar(
radius: 16.6,
backgroundImage: NetworkImage(
doc['profileImage']
)
),
title: Text(
doc['displayName'],
style: TextStyle(
color: Colors.white,
fontSize: 16.5,
)
),
subtitle: doc['title'] !=null ?
Text(
doc['title'],
style: TextStyle(
color: Colors.white,
fontSize: 12.5,
),
) :
Text(
"Some Title",
style: TextStyle(
color: Colors.white,
)
),
),
if(doc['photoURL'] != null) ... [
Container(
height: 400,
width: 400,
child: Image(
image: NetworkImage(
doc['photoURL'],
),
fit: BoxFit.contain,
)
),
IconButton(
icon: Icon(
Icons.mode_comment_outlined,
color: Colors.white,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) =>
CommentSection(),
));
},
)
] else if(doc['photoURL'] == null) ...[
Container(
height: 400,
width: 400,
child: Image(
image: AssetImage(
"assets/images/placeholder.png"
),
fit: BoxFit.contain,
)
)
],
ListTile(
leading: Padding(
padding: EdgeInsets.only(bottom: 13.5 ),
child: Text( "# " +
doc['displayName'],
style: TextStyle(
color: Colors.white,
),
),
),
subtitle: Padding(
padding: EdgeInsets.only(bottom: 13.5),
child: doc['decsription'] != null ?
Text( ":" +
doc['decsription'],
style: TextStyle(
color: Colors.white,
)
) :
Text(
"Some Descritiption",
style: TextStyle(
color: Colors.white,
)
)
)
),
]
),
)).toList(),
);
} else {
return CircularProgressIndicator();
}
}
)
);
}
}
and here`s the comment screen code
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class CommentSection extends StatefulWidget {
// const CommentSection({Key? key}) : super(key: key);
#override
_CommentSectionState createState() => _CommentSectionState();
}
class _CommentSectionState extends State<CommentSection> {
var username = ' ';
List photoURL = [];
User? user = FirebaseAuth.instance.currentUser;
CollectionReference userRef = FirebaseFirestore.instance.collection('users');
final _formKey = GlobalKey<FormState>();
late String comments = ' ';
sendComment() async {
final isValid = _formKey.currentState!.validate();
final name = user!.displayName;
var res = await userRef.where('userid', isEqualTo: user!.uid).get();
_formKey.currentState!.save();
var doc = userRef.doc('photoURL');
doc.set({
'comment' : comments,
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 50),
child: TextFormField(
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
labelText: "Leave a Comment..",
labelStyle: TextStyle(
color: Colors.white,
)
),
onSaved: (value) {
comments = value!;
}
),
)
],
)
),
ElevatedButton.icon(
onPressed: sendComment,
icon: Icon(Icons.send,
color: Colors.white,
),
label: Text(
"Send"
))
],
)
),
);
}
}
That's a really broad use-case, and honestly a bit too broad to answer on Stack Overflow. I recommend focusing on a more concrete, specific problem.
For example, you mention in your comment:
I tried creating a separate collection for comment but the comment would be fetched for every image in database and I'm trying to save and retrieve the comment data for particular image
To allow reading only comments on a specific image, you'll need to associate each comment in the database with an image. The two most common approaches for this are:
Create a document for each image in a top-level collection, and then create a subcollection under that document for the comments on that specific image.
Create a single top-level comments collection, and store the ID of the image in each comment document.
I have this error with that code code :
import 'package:flutter/material.dart';
import 'package:yummy/main.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
backgroundColor: Colors.white,
leading: IconButton(
icon: Image.asset("doodles/theuser.png"),
onPressed: (){},
),
centerTitle: true,
title: Image.asset("doodles/halfyummylog.png"),
actions: <Widget>[
IconButton(onPressed: (){}, icon: Image.asset(("doodles/favrec.png")))
],
),
body: Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: Color(0xFFFFDEE2),
child: Column(
children: <Widget>[
Image.asset("doodles/DinnerPlace.png"),
SizedBox(
height: 30,
), Container(
decoration: BoxDecoration(color : Colors.white, borderRadius: BorderRadius.circular(14)),
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(Icons.search,color: Colors.grey,size : 33),
hintText: "Search",
hintStyle: TextStyle(
fontFamily: "SFProDisplay",
color : Colors.grey,
fontSize: 20.0
),
),
)),
],
),
),
);
}
}
The error pop at the bottom of the image "doodles/DinnerPlace.png" after the appbar and I don't know why.
If somoene can help me for resolve this I will be really greatful.
As your container of the body is 100, you have to bound the image within this height.But the height of Image is not specified, so it take the space more than body's container's 100.So either bound the image with container with height like this -
Container(
height: 70,
child: Image.asset("doodles/DinnerPlace.png"),
)
or increase the size of body's Container from 100 to 200.
The problem was because of the second container I just add an Expanded widget for the container and it's working properly now.
I've tried to fix this with the following code but I'm afraid the error is still prevalent:
The following assertion was thrown building:
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 360 pos 10: 'data != null'
child: Row(
children: [
Text(
(contact.data()['rating'] == null)
? "n/a"
: contact.data()['rating'].toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.tealAccent)),
Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
radius: 25,
backgroundImage: AssetImage("assets/girl2.jpg"),
),
),
Spacer(),
Text(
contact.data()['name'],
style: TextStyle(
fontWeight: FontWeight.w400, color: Colors.tealAccent),
),
Spacer(),
Text(
contact.data()['location'],
style: TextStyle(
letterSpacing: 1,
fontSize: 10,
fontWeight: FontWeight.w300,
color: Colors.tealAccent),
),
],
),
How would one go about solving this?
You can just add:
contact.data()['rating'] ?? "empty"
The above will check if the expression on the left is not null, if it is then "empty" will be added to the Text widget. You have to add the condition to the other Text widgets also.
I'm trying to figure out how to iterate through documents in firestore and create a text widget for each one.
I've figured out how to access those elements. I used debugPrint() and got the results I'm expecting, but I can't get it to display below my other widgets. I get a red screen with a ton of errors (on phone).Below is my code for what I've tried so far.
QuerySnapshot querySnapshot = await
Firestore.instance.collection("users").document(user.uid).collection("trails").getDocuments();
var list = querySnapshot.documents;
list.forEach((doc) => debugPrint(doc.data["Trail Name"].toString()));//works
final topContentText = Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
//these widgets are generating correctly
Text(
"First Name: $firstName",
style: TextStyle(color: Colors.white, ),
),
Text(
"Last Name: $lastName",
textAlign: TextAlign.left,
style: TextStyle(color: Colors.white,),
),
Text(
"Email: $email",
style: TextStyle(color: Colors.white, ),
),
//these ones are causing my errors.
list.forEach((doc) => Text(
"Trail Name: ${doc.data["Trail Name"].toString()}",
style: TextStyle(color: Colors.white, ),
),)
],
);
final topContent = Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.40,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
child: Center(
child: topContentText,
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
return Scaffold(
body: Column(
children: <Widget>[topContent, bottomContent],
),
);
The screen on my device lights up red with errors on creating child widgets, when I'm expecting it to display the Trail Name(s) below the other info. I only included necessary code, but could include more (such as the widget's build method) if needed. Thanks for any assistance. I'm new to flutter.
Try using the map function:
List<Widget> _widgets = list.map((doc) => Text(
"Trail Name: ${doc.data["Trail Name"].toString()}",
style: TextStyle(color: Colors.white, ),
),).toList();
And then for the children of the column, just add that list to the list you specify, like:
children: [ ... ] + _widgets;
Just wondering how I would change the height of an OutlineButton? I suppose this would likely apply to other button types as well.
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
SizedBox(
width: 100.0,
height: 8.0,
child: OutlineButton(
borderSide: BorderSide(width: 4.0)
child: Text('Hi'),
onPressed: (){},
),
),
],
),
body: Container(),
);
I am finding the button just about 8px too high for my case, and want to squish it a bit.
SizedBox should do the work. Wrap your button by a SizedBox.
From the document:
If given a child, this widget forces its child to have a specific width and/or height (assuming values are permitted by this widget's parent). If either the width or height is null, this widget will size itself to match the child's size in that dimension.
If not given a child, this widget will size itself to the given width and height, treating nulls as zero.
This will work for RaisedButton also
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Layout',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("SizedBox Demo"),
),
body: new Center(
child: new SizedBox(
width: 200.0,
height: 80.0,
child: new OutlineButton(
borderSide: BorderSide(width: 4.0),
child: Text('I am a button'),
onPressed: (() {})),
),
),
);
}
}
UPDATED (2018/05/26):
If you want to reduce the height of OutlineButton inside AppBar, use Padding
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
Padding(
child: OutlineButton(
borderSide: BorderSide(width: 4.0)
child: Text('Hi'),
onPressed: (){},
padding: EdgeInsets.all(10.0),
),
),
],
),
body: Container(),
);
Flutter 2.5
OutlineButton is deprecated. Instead, use the Material button.
Put the Material Button inside Padding.
The padding property of Padding will control the height and width of the button.
AppBar(
title: Text("Stack Overflow"),
actions: [
Padding(
padding: EdgeInsets.all(8.0),
child: MaterialButton(
color: Colors.yellow,
onPressed: () {
},
child: Text('SUBMIT'),
),
)
],
)
Thanks #phuc-tran, I've made a small fix:
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
Padding(
padding: EdgeInsets.all(10.0),
child: OutlineButton(
borderSide: BorderSide(color: Colors.blue),
child: Text('Hi'),
onPressed: (){},
),
),
],
),
body: Container(),
);