'Flutter - How to know free screen size for text widget
In my flutter project, I've used ExpansionPanel and in it there are star icon, text, checkbox, popup window as shown in the picture. But when I insert more text it is overflowing. And here you can see three dots (...) and it's fixed. I did it manually when text lenght more than 15, then, It cuts the substring and adds ... at the end and full title can be shown when expansion panel expanded.
I want to do it dynamic, according to different width of screen. In this case how can I determine free space for the text widget?
import 'package:flutter/material.dart';
import '../blocs/multi_blocs.dart';
import '../models/task.dart';
import '../widgets/task_tile.dart';
class TasksList extends StatelessWidget {
final List<Task> tasks;
const TasksList({
Key? key,
required this.tasks,
}) : super(key: key);
void _cancelOrDeleteCallBack(BuildContext ctx, Task task) {
task.isCancelled == false
? ctx.read<TodosBloc>().add(CancelTask(task: task))
: ctx.read<TodosBloc>().add(DeleteTask(task: task));
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: GestureDetector(
// behavior: HitTestBehavior.translucent,
child: ExpansionPanelList.radio(
elevation: 3,
children: tasks
.map(
(task) => ExpansionPanelRadio(
headerBuilder: (context, isOpen) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TaskTile(
task: task,
checkboxCallback: (checkboxState) {
context.read<TodosBloc>().add(UpdateTask(task: task));
},
cancelOrDeleteCallback: () =>
_cancelOrDeleteCallBack(context, task),
likeCallback: () => context
.read<TodosBloc>()
.add(LikeOrDislikeTask(task: task)),
restoreCallback: () => context
.read<TodosBloc>()
.add(RestoreTask(task: task)),
),
),
body: ListTile(
title: SelectableText(
'Task:\n${task.title}\n\nDescription:\n${task.description}',
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: true,
),
),
),
value: Text(task.id),
),
)
.toList(),
),
),
);
}
}
Solution 1:[1]
We cant calculate the remaining screen for texts. just wrap your text with Expanded widget. and give overflow: TextOverflow.eclipse to text. it will solve your issue.
Solution 2:[2]
I implemented your 'TaskTile' widget like your layout.
- TaskTile
-- Row
--- Icon
--- Expanded
---- Text(overflow: TextOverflow.ellipsis)
--- CheckBox
--- Hamburger button
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return TasksList(
tasks: [
{
'id': '123',
'title': 'title1',
'desc': 'desc',
},
{
'id': '333',
'title': 'title2',
'desc': 'descasdfkjsklfjklasdjfklajsldkfalskdfj',
}
],
);
}
}
class TasksList extends StatelessWidget {
final List<Map<String, dynamic>> tasks;
const TasksList({
Key key,
@required this.tasks,
}) : super(key: key);
// void _cancelOrDeleteCallBack(BuildContext ctx, Task task) {
// task.isCancelled == false
// ? ctx.read<TodosBloc>().add(CancelTask(task: task))
// : ctx.read<TodosBloc>().add(DeleteTask(task: task));
// }
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: GestureDetector(
// behavior: HitTestBehavior.translucent,
child: ExpansionPanelList.radio(
elevation: 3,
children: tasks
.map(
(task) => ExpansionPanelRadio(
headerBuilder: (context, isOpen) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
Icon(Icons.favorite),
Expanded(
child: Text(
task['desc'],
overflow: TextOverflow.ellipsis,
),
),
Icon(Icons.add_box),
Icon(Icons.bug_report_rounded),
],
),
),
body: ListTile(
title: SelectableText(
'Task:\n${task['title']}\n\nDescription:\n${task['desc']}',
toolbarOptions: const ToolbarOptions(
copy: true,
selectAll: true,
cut: true,
),
),
),
value: Text(task['id']),
),
)
.toList(),
),
),
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Prashant Vaddoriya |
| Solution 2 | KuKu |


