Skip to content

Commit 9fc8627

Browse files
authored
[flutter_markdown] Add horizontal scroll for markdown table (#6983)
Add horizontal scroll for markdown table when using `tableColumnWidth: FixedColumnWidth(width)` Fix [flutter/flutter#129052](flutter/flutter#129052)
1 parent d43a827 commit 9fc8627

File tree

5 files changed

+104
-7
lines changed

5 files changed

+104
-7
lines changed

packages/flutter_markdown/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.7.3
2+
3+
* Adds horizontal scrolling for table when using `tableColumnWidth: FixedColumnWidth(width)`.
4+
15
## 0.7.2+1
26

37
* Fixes a crash caused by text selection when `selectable` is true and `onSelectionChanged` is null.

packages/flutter_markdown/lib/src/builder.dart

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,12 +438,20 @@ class MarkdownBuilder implements md.NodeVisitor {
438438
);
439439
}
440440
} else if (tag == 'table') {
441-
child = Table(
442-
defaultColumnWidth: styleSheet.tableColumnWidth!,
443-
defaultVerticalAlignment: styleSheet.tableVerticalAlignment,
444-
border: styleSheet.tableBorder,
445-
children: _tables.removeLast().rows,
446-
);
441+
if (styleSheet.tableColumnWidth is FixedColumnWidth) {
442+
final ScrollController tableScrollController = ScrollController();
443+
child = Scrollbar(
444+
controller: tableScrollController,
445+
child: SingleChildScrollView(
446+
controller: tableScrollController,
447+
scrollDirection: Axis.horizontal,
448+
padding: styleSheet.tablePadding,
449+
child: _buildTable(),
450+
),
451+
);
452+
} else {
453+
child = _buildTable();
454+
}
447455
} else if (tag == 'blockquote') {
448456
_isInBlockquote = false;
449457
child = DecoratedBox(
@@ -558,6 +566,15 @@ class MarkdownBuilder implements md.NodeVisitor {
558566
_lastVisitedTag = tag;
559567
}
560568

569+
Table _buildTable() {
570+
return Table(
571+
defaultColumnWidth: styleSheet.tableColumnWidth!,
572+
defaultVerticalAlignment: styleSheet.tableVerticalAlignment,
573+
border: styleSheet.tableBorder,
574+
children: _tables.removeLast().rows,
575+
);
576+
}
577+
561578
Widget _buildImage(String src, String? title, String? alt) {
562579
final List<String> parts = src.split('#');
563580
if (parts.isEmpty) {

packages/flutter_markdown/lib/src/style_sheet.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class MarkdownStyleSheet {
3838
this.tableHead,
3939
this.tableBody,
4040
this.tableHeadAlign,
41+
this.tablePadding,
4142
this.tableBorder,
4243
this.tableColumnWidth,
4344
this.tableCellsPadding,
@@ -134,6 +135,7 @@ class MarkdownStyleSheet {
134135
tableHead: const TextStyle(fontWeight: FontWeight.w600),
135136
tableBody: theme.textTheme.bodyMedium,
136137
tableHeadAlign: TextAlign.center,
138+
tablePadding: const EdgeInsets.only(bottom: 4.0),
137139
tableBorder: TableBorder.all(
138140
color: theme.dividerColor,
139141
),
@@ -231,6 +233,7 @@ class MarkdownStyleSheet {
231233
),
232234
tableBody: theme.textTheme.textStyle,
233235
tableHeadAlign: TextAlign.center,
236+
tablePadding: const EdgeInsets.only(bottom: 8),
234237
tableBorder: TableBorder.all(color: CupertinoColors.separator, width: 0),
235238
tableColumnWidth: const FlexColumnWidth(),
236239
tableCellsPadding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
@@ -312,6 +315,7 @@ class MarkdownStyleSheet {
312315
tableHead: const TextStyle(fontWeight: FontWeight.w600),
313316
tableBody: theme.textTheme.bodyMedium,
314317
tableHeadAlign: TextAlign.center,
318+
tablePadding: const EdgeInsets.only(bottom: 4.0),
315319
tableBorder: TableBorder.all(
316320
color: theme.dividerColor,
317321
),
@@ -371,6 +375,7 @@ class MarkdownStyleSheet {
371375
TextStyle? tableHead,
372376
TextStyle? tableBody,
373377
TextAlign? tableHeadAlign,
378+
EdgeInsets? tablePadding,
374379
TableBorder? tableBorder,
375380
TableColumnWidth? tableColumnWidth,
376381
EdgeInsets? tableCellsPadding,
@@ -436,6 +441,7 @@ class MarkdownStyleSheet {
436441
tableHead: tableHead ?? this.tableHead,
437442
tableBody: tableBody ?? this.tableBody,
438443
tableHeadAlign: tableHeadAlign ?? this.tableHeadAlign,
444+
tablePadding: tablePadding ?? this.tablePadding,
439445
tableBorder: tableBorder ?? this.tableBorder,
440446
tableColumnWidth: tableColumnWidth ?? this.tableColumnWidth,
441447
tableCellsPadding: tableCellsPadding ?? this.tableCellsPadding,
@@ -502,6 +508,7 @@ class MarkdownStyleSheet {
502508
tableHead: tableHead!.merge(other.tableHead),
503509
tableBody: tableBody!.merge(other.tableBody),
504510
tableHeadAlign: other.tableHeadAlign,
511+
tablePadding: other.tablePadding,
505512
tableBorder: other.tableBorder,
506513
tableColumnWidth: other.tableColumnWidth,
507514
tableCellsPadding: other.tableCellsPadding,
@@ -620,6 +627,9 @@ class MarkdownStyleSheet {
620627
/// The [TextAlign] to use for `th` elements.
621628
final TextAlign? tableHeadAlign;
622629

630+
/// The padding to use for `table` elements.
631+
final EdgeInsets? tablePadding;
632+
623633
/// The [TableBorder] to use for `table` elements.
624634
final TableBorder? tableBorder;
625635

@@ -740,6 +750,7 @@ class MarkdownStyleSheet {
740750
other.tableHead == tableHead &&
741751
other.tableBody == tableBody &&
742752
other.tableHeadAlign == tableHeadAlign &&
753+
other.tablePadding == tablePadding &&
743754
other.tableBorder == tableBorder &&
744755
other.tableColumnWidth == tableColumnWidth &&
745756
other.tableCellsPadding == tableCellsPadding &&
@@ -798,6 +809,7 @@ class MarkdownStyleSheet {
798809
tableHead,
799810
tableBody,
800811
tableHeadAlign,
812+
tablePadding,
801813
tableBorder,
802814
tableColumnWidth,
803815
tableCellsPadding,

packages/flutter_markdown/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output,
44
formatted with simple Markdown tags.
55
repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown
66
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22
7-
version: 0.7.2+1
7+
version: 0.7.3
88

99
environment:
1010
sdk: ^3.3.0

packages/flutter_markdown/test/scrollable_test.dart

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,69 @@ void defineTests() {
110110
]);
111111
},
112112
);
113+
114+
testWidgets(
115+
'table',
116+
(WidgetTester tester) async {
117+
const String data = '|Header 1|Header 2|Header 3|'
118+
'\n|-----|-----|-----|'
119+
'\n|Col 1|Col 2|Col 3|';
120+
await tester.pumpWidget(
121+
boilerplate(
122+
MediaQuery(
123+
data: const MediaQueryData(),
124+
child: MarkdownBody(
125+
data: data,
126+
styleSheet: MarkdownStyleSheet(
127+
tableColumnWidth: const FixedColumnWidth(150),
128+
),
129+
),
130+
),
131+
),
132+
);
133+
134+
final Iterable<Widget> widgets = tester.allWidgets;
135+
final Iterable<SingleChildScrollView> scrollViews =
136+
widgets.whereType<SingleChildScrollView>();
137+
expect(scrollViews, isNotEmpty);
138+
expect(scrollViews.first.controller, isNotNull);
139+
},
140+
);
141+
142+
testWidgets(
143+
'two tables use different scroll controllers',
144+
(WidgetTester tester) async {
145+
const String data = '|Header 1|Header 2|Header 3|'
146+
'\n|-----|-----|-----|'
147+
'\n|Col 1|Col 2|Col 3|'
148+
'\n'
149+
'\n|Header 1|Header 2|Header 3|'
150+
'\n|-----|-----|-----|'
151+
'\n|Col 1|Col 2|Col 3|';
152+
153+
await tester.pumpWidget(
154+
boilerplate(
155+
MediaQuery(
156+
data: const MediaQueryData(),
157+
child: MarkdownBody(
158+
data: data,
159+
styleSheet: MarkdownStyleSheet(
160+
tableColumnWidth: const FixedColumnWidth(150),
161+
),
162+
),
163+
),
164+
),
165+
);
166+
167+
final Iterable<Widget> widgets = tester.allWidgets;
168+
final Iterable<SingleChildScrollView> scrollViews =
169+
widgets.whereType<SingleChildScrollView>();
170+
expect(scrollViews, hasLength(2));
171+
expect(scrollViews.first.controller, isNotNull);
172+
expect(scrollViews.last.controller, isNotNull);
173+
expect(scrollViews.first.controller,
174+
isNot(equals(scrollViews.last.controller)));
175+
},
176+
);
113177
});
114178
}

0 commit comments

Comments
 (0)