Flutter when I used ListTile ThreeLines, I don't know how to use ThreeLine
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('ddd'),
),
body:Container(
child: Column(
children: <Widget>[
ListTile(
isThreeLine: true,
leading: Icon(Icons.event_note),
title: Text('Title 1'),
// subtitle: Text('Title2'),
subtitle: Column(
children: <Widget>[
Text('Titile2'),
Text('Title 3'),
Text('Title 4'),
Text('and so on')
],
),
)
],
),
) ,
),
);
}
}
When i delete isThreeLines, the code is Ok
ListTile
Thanks
As from the docs:
The value of subtitle, which is optional, will occupy the space
allocated for an additional line of text, or two lines if isThreeLine
is true.
It basically means the subtitle of the ListTile is given more space to have text which is more than one line in length:
By default, the ListTile in flutter can display only 2 lines. The Title and the SubTitle. In case there is a third line of text to be displayed, the isThreeLine is set to true and can allow another line to be present. The subtitle will be taking care of giving the 3rd line of text. It is expected that, if the isThreeLine is set to true, the subtitle should be non-null. Anything after "\n" inside subtitle will come in next line
ListTile(
title: Text("First Line",
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text("Second One Text "\nThis is Line Third Text"),
isThreeLine: true,
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
child: Icon(Icons.delete,color: Colors.red,),
onTap: () {
},
),
],
),
onTap: (){},
)
By default, the ListTile in flutter can display only 2 lines. The Title and the SubTitle. In case there is a third line of text to be displayed, the isThreeLine is set to true and can allow another line to be present. The subtitle will be taking care of giving the 3rd line of text. It is expected that, if the isThreeLine is set to true, the subtitle should be non-null.
Related
I have the following app bar in flutter and trying to align the subtext "Your desired business name" under the title enter. I have tried different methods but still can't get to align. It should have "enter" at the top and then the subtext aligned center
Here is my current code
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(75.0),
child: AppBar(
centerTitle: true,
title: Text('enter'),
actions: <Widget>[
new Container(),
new Center(
child: Text(
'Your desired business name',
textAlign: TextAlign.center,
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),
)),
],
)),
);
}
To align Text under AppBar title you can use bottom property of AppBar which takes PreferredSize widget as a parameter which also helps you to adjust the height of AppBar according to your need.
Here's the code
AppBar(
title: Text('Title 1'),
centerTitle: true,
bottom: PreferredSize(
child: Text("Title 2"),
preferredSize: Size.zero),
)
The menu bar actions widgets get aligned on the right and as far as I know it is not possible to obtain your desidered layout.
Should you consider a column based widget with a title and subtitle:
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
centerTitle: true,
title: Column(children: [
Text(
"Title",
),
GestureDetector(
child: Text('subtitle'),
onTap: () {
print("tapped subtitle");
},
)
]),
...
In this example there is a GestureDetector for give interactivity to subtitle, since it seems it is what you are trying to do.
I am using this code for adding subtitle and show UserIcon
//name,status and userPic are variable's
#override
Widget build(BuildContext context)
{
return new Scaffold(
appBar: new AppBar(
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
Text(
status,
style: TextStyle(color: Colors.white, fontSize: 14.0),
)
],
),
leading: new Padding(
padding: const EdgeInsets.all(5.0),
child: new CircleAvatar(
backgroundImage: new NetworkImage(userPicUrl),
),
),
actions: <Widget>[new Icon(Icons.more_vert)],
),
);
}
Output
You should add Column view.
title: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Title",
style: TextStyle(color: Colors.white, fontSize: 16.0),
),
Text(
"Sub Title",
style: TextStyle(color: Colors.white, fontSize: 14.0),
),
]
),
In these cases I prefer to use a ListTile:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:
AppBar(
title:
ListTile(
title:
Text("Enter", style: TextStyle(color:Colors.white)),
subtitle:
Text("Your desired business name", style: TextStyle(color:Colors.white)),
)
),
);
}
If you need the Text widget centered just wrap it within a Center widget.
The answer in https://stackoverflow.com/a/53880971/9185192 works but with null safety landing in Dart it is not allowed to set preferredSize to null.
So the solution is to set preferredSize to zero or any other valid number.
appBar: AppBar(
title: Text('Title 1'),
centerTitle: true,
bottom: PreferredSize(
child: Text("Title 2"),
preferredSize: Size.fromHeight(0),
),
)
appBar: AppBar(
title: Center(
child: Text('Flutter Tutorial'),
),
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Flutter Demo'
),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Hell World!'
)
],
)
);
}
}
Why the text Hell World only centering horizontally and not vertically as I have also specified CrossAxisAligment.
Is it because of this : Issue
Row don't take all the vertical space available by default. It takes only the needed space (but it takes all the horizontal space).
Forcing the row to expend vertically should do the trick:
body: SizedBox.expand(
child: Row(...),
),
use center widget
Center(child: Row(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('Hell World!')],))
Using this simple design, how can I display the second image under the listview? In reality the list will be fetched from firebase where each item is an ExpansionTile, so the height of the listview can in no way be fixed.
The column should be scrollable so you can see the full image if you scroll down below the list.
import 'package:flutter/material.dart';
List<Widget> list = <Widget>[
ListTile(
title: Text('CineArts at the Empire',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('85 W Portal Ave'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
ListTile(
title: Text('The Castro Theater',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('429 Castro St'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
];
class CartWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Column(children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: list,
),
),
Image.network("https://via.placeholder.com/350x500"), // error: hides above widget
]));
}
}
The way I understood your problem is that you want the bottom image to appear inside the list view instead of under it, as if it was just another item. Solution: Make it just another item!
More concrete, this is how your implementation for a helper function that enriches the list with the image may look like:
List<Widget> _buildListWithFooterImage(List<Widget> items) {
return items.followedBy([
Image.network("https://via.placeholder.com/350x500")
]);
}
Then, you could use that function during your build:
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: _buildListWithFooterImage(list)
)
),
]
)
);
}
Also, I believe your question is similar to this one.
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 inserted 6 cards, however it is not possible to scroll the screen.
According to the image below, a red stripe appears in the footer, and the screen does not scroll.
What is missing to be able to scroll the screen?
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Myapp",
home: new HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
appBar: new AppBar(
backgroundColor: new Color(0xFF26C6DA),
),
body: new Column(
children: <Widget>[
new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text('The Enchanted Nightingale'),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
],
),
),
...
...
...
],
)
);
}
Columns don't scroll. Try replacing your outer Column with a ListView. You may need to put shrinkWrap: true on it.
To make a column scrollable, simply wrap it in a SingleChildScrollView.
This might do the trick, worked like charm for me:
shrinkWrap: true, physics: ClampingScrollPhysics(),
I needed placing SingleChildScrollView inside Column. The SingleChildScrollView also needed Column as a child, but the scroll wasn't working for me in that case. The solution was to wrap the SingleChildScrollView with Expanded. So here's how it looked:
Column(
children: <Widget>[
MyFirstWidget(),
Expanded(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// Scrollable content.
],
),
),
),
],
),
you have to put it on ListView.builder
ListView.builder(
itemBuilder: (BuildContext context, int index){
final item = yourItemLists[index];
new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text('The Enchanted Nightingale'),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
],
),
);
},
itemCount: yourItemLists.length,
);
A column in a column make the layout impossible to calculate without setting height.
The second column is useless since it contains only one element, try to put the ListTile directly as the body of the Card.
You should use ListView.builder in place of the inner column (as I suggested above that columns are not scrollable).
Set shrinkWrap: true, and physics: ClampingScrollPhysics() inside ListView.builder. Just using shrinkWrap: true didn't solve my problem. But setting physics to ClampingScrollPhysics() started to make it scroll.
There are generally two ways to make a screen scrollable. One is by using Column, and the other is by using ListView.
Use Column (wrapped in SingleChildScrollView):
SingleChildScrollView( // Don't forget this.
child: Column(
children: [
Text('First'),
//... other children
Text('Last'),
],
),
)
Use ListView:
ListView(
children: [
Text('First'),
//... other children
Text('Last'),
],
)
This approach is simpler to use, but you lose features like crossAxisAlignment. For this case, you can wrap your children widget inside Align and set alignment property.
You can also Wrap the parent Column in a Container and then wrap the Container with the SingleChildscrollView widget. (This solved my issue).
Just Add physics: ClampingScrollPhysics(),