Skip to content

Instantly share code, notes, and snippets.

@Zekfad
Last active October 26, 2022 16:24
Show Gist options
  • Save Zekfad/a92d65958eb8b0de4dd9c791cdad37a5 to your computer and use it in GitHub Desktop.
Save Zekfad/a92d65958eb8b0de4dd9c791cdad37a5 to your computer and use it in GitHub Desktop.
Question 74210767
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Row(
children: [
Flexible(
// Main RichText, it is consists of `WidgetSpan`s and `TextSpan`s.
child: RichText(
maxLines: 1,
overflow: TextOverflow.ellipsis,
text: TextSpan(
children: [
const Tuple2(1, 'Name1 Surname1'),
const Tuple2(2, 'Name2 Surname2'),
const Tuple2(3, 'Name3 Surname3'),
].map<InlineSpan>((entry) {
final nameWidget = Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Text(
entry.item2,
overflow: TextOverflow.ellipsis,
// softWrap: false,
),
);
return ButtonSpan(
onTap: () async {
print('Tap');
},
child: nameWidget,
);
})
.interject(
(previous, index, next) => const TextSpan(
text: ', ',
),
)
.toList(),
),
),
),
],
),
),
);
}
}
// Custom `WidgetSpan`
class ButtonSpan extends WidgetSpan {
ButtonSpan({
required super.child,
this.onTap,
this.maxWidthDelta,
});
final void Function()? onTap;
final double? maxWidthDelta;
@override
// ignore: overridden_fields
late final Widget child = Material(
color: Colors.transparent,
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(4)),
onTap: onTap,
child: maxWidthDelta == null
? super.child
// Failed attempt, as constrains are for full paragraph
: LayoutBuilder(builder: (context, constraints) =>
ConstrainedBox(
constraints: constraints.copyWith(
maxWidth: constraints.maxWidth + maxWidthDelta!,
),
child: super.child,
),
),
),
);
}
// AUX code
/// Interjector function. It has 3 arguments:
/// * [E] previous element.
/// * [int] index of previous element in original iterable,
/// * [E] next element.
typedef IterableInterjectFunction<E> = E Function(E previous, int index, E next);
/// Interject values between elements of iterable.
/// [interjector] function has 3 arguments:
/// * [E] previous element.
/// * [int] index of previous element in original iterable,
/// * [E] next element.
Iterable<E> interjectIterable<E>(Iterable<E> iterable, IterableInterjectFunction<E> interjector) sync * {
if (iterable.length < 2) {
yield* iterable;
return;
}
final it = iterable.iterator
..moveNext();
var previous = it.current;
var i = 0;
yield previous;
while (it.moveNext()) {
yield interjector(previous, i++, it.current);
yield previous = it.current;
}
}
extension IterableInterject<E> on Iterable<E> {
/// Interject values between elements of iterable.
/// [interjector] function has 3 arguments:
/// * [E] previous element.
/// * [int] index of previous element in original iterable,
/// * [E] next element.
Iterable<E> interject(IterableInterjectFunction<E> interjector) =>
interjectIterable(this, interjector);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment