Blocks / lists
Track row
Shows a song in a list with its artwork, title, artist and length spoken in words, the song now playing marked by bars that move, read as one node.
Import
Track row is part of Fliin Pro. With a license key, sign in once with fliin login, then add it in a Flutter app where fliin init has run:
fliin login
fliin add track-rowExamples
Current
The track playing now: current and playing highlight it and tell the screen reader. The duration has a spoken form in durationLabel.
import 'package:your_app/ui/fliin/components/list_row/fl_list_row.dart';
import 'package:your_app/ui/fliin/components/result_card/fl_result_card.dart';
import 'package:your_app/ui/fliin/components/track_row/fl_track_row.dart';
import 'package:flutter/widgets.dart';
class TrackRowCurrentExample extends StatelessWidget {
const TrackRowCurrentExample({super.key});
@override
Widget build(BuildContext context) {
return FlListGroup(
children: [
FlTrackRow(
title: 'October Light',
subtitle: 'The Tides · Wild Coast',
duration: '3:31',
durationLabel: '3 minutes 31 seconds',
artwork: const FlResultImage(image: FlSampleImage(FlSampleArt.lamp)),
current: true,
playing: true,
currentLabel: 'Now playing',
onPressed: () {},
),
FlTrackRow(
title: 'The Night Train',
subtitle: 'North Orchestra · Journeys',
duration: '1:05:30',
durationLabel: '1 hour 5 minutes 30 seconds',
artwork: const FlResultImage(image: FlSampleImage(FlSampleArt.bag)),
currentLabel: 'Now playing',
onPressed: () {},
),
],
);
}
}Default
Tracks in a list: title, artist and album, the artwork and the duration. Tapping a row plays it.
import 'package:your_app/ui/fliin/components/list_row/fl_list_row.dart';
import 'package:your_app/ui/fliin/components/result_card/fl_result_card.dart';
import 'package:your_app/ui/fliin/components/track_row/fl_track_row.dart';
import 'package:flutter/widgets.dart';
class TrackRowDefaultExample extends StatelessWidget {
const TrackRowDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return FlListGroup(
children: [
FlTrackRow(
title: 'October Light',
subtitle: 'The Tides · Wild Coast',
duration: '3:31',
durationLabel: '3 minutes 31 seconds',
artwork: const FlResultImage(image: FlSampleImage(FlSampleArt.lamp)),
current: false,
playing: false,
currentLabel: 'Now playing',
onPressed: () {},
),
FlTrackRow(
title: 'The Night Train',
subtitle: 'North Orchestra · Journeys',
duration: '1:05:30',
durationLabel: '1 hour 5 minutes 30 seconds',
artwork: const FlResultImage(image: FlSampleImage(FlSampleArt.bag)),
currentLabel: 'Now playing',
onPressed: () {},
),
],
);
}
}Album
An album's tracks: number in place of the artwork, the current track's bars taking its number's place, and a "More" button after each duration (trailing).
import 'package:your_app/ui/fliin/components/button/fl_button.dart';
import 'package:your_app/ui/fliin/components/list_row/fl_list_row.dart';
import 'package:your_app/ui/fliin/components/track_row/fl_track_row.dart';
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/icons/fl_icons.dart';
import 'package:flutter/widgets.dart';
class TrackRowAlbumExample extends StatelessWidget {
const TrackRowAlbumExample({super.key});
@override
Widget build(BuildContext context) {
FlTrackRow track(int n, String title, String duration, String spoken, {bool current = false}) => FlTrackRow(
number: '$n',
title: title,
subtitle: 'The Tides',
duration: duration,
durationLabel: spoken,
current: current,
playing: current,
currentLabel: 'Now playing',
trailing: FlButton.icon(
label: 'More, $title',
icon: FlIcon(FlIcons.ellipsis),
variant: FlButtonVariant.ghost,
size: FlButtonSize.sm,
onPressed: () {},
),
onPressed: () {},
);
return FlListGroup(
children: [
track(1, 'Wild Coast', '4:12', '4 minutes 12 seconds'),
track(2, 'October Light', '3:31', '3 minutes 31 seconds', current: true),
track(3, 'Morning Coffee', '2:48', '2 minutes 48 seconds'),
],
);
}
}Usage
The code the reference images render:
final example = ColoredBox(
color: FlScope.of(context).colors.surface,
child: SingleChildScrollView(
padding: EdgeInsetsDirectional.all(FlScope.of(context).space.lg),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlListGroup(
children: [
FlTrackRow(
title: "October Light",
subtitle: "The Tides · Wild Coast",
duration: (variant.dir == TextDirection.rtl
? "\u2066٣:٣١\u2069"
: "3:31"),
durationLabel: (variant.dir == TextDirection.rtl
? "٣\u00a0دقائق ٣١\u00a0ثانية"
: "3\u00a0minutes 31\u00a0secondes"),
artwork: const FlResultImage(
image: FlSampleImage(FlSampleArt.lamp),
),
current: true,
playing: true,
currentLabel: (variant.dir == TextDirection.rtl
? "قيد التشغيل"
: "Now playing"),
onPressed: () {},
),
FlTrackRow(
title: "Under the Lindens",
subtitle: "Nina Reed · Gardens",
duration: (variant.dir == TextDirection.rtl
? "\u2066٤:٠٥\u2069"
: "4:05"),
durationLabel: (variant.dir == TextDirection.rtl
? "٤\u00a0دقائق ٥\u00a0ثوانٍ"
: "4\u00a0minutes 5\u00a0secondes"),
artwork: const FlResultImage(
image: FlSampleImage(FlSampleArt.plant),
),
current: false,
playing: false,
currentLabel: (variant.dir == TextDirection.rtl
? "قيد التشغيل"
: "Now playing"),
onPressed: () {},
),
FlTrackRow(
title: "The Night Train",
subtitle: "North Orchestra · Journeys",
duration: (variant.dir == TextDirection.rtl
? "\u2066١:٠٥:٣٠\u2069"
: "1:05:30"),
durationLabel: (variant.dir == TextDirection.rtl
? "ساعة واحدة ٥\u00a0دقائق ٣٠\u00a0ثانية"
: "1 hour 5 minutes 30 seconds"),
artwork: const FlResultImage(
image: FlSampleImage(FlSampleArt.bag),
),
current: false,
playing: false,
currentLabel: (variant.dir == TextDirection.rtl
? "قيد التشغيل"
: "Now playing"),
onPressed: () {},
),
FlTrackRow(
title: "Morning Coffee",
subtitle: "The Tides · Wild Coast",
duration: (variant.dir == TextDirection.rtl
? "\u2066٢:٤٨\u2069"
: "2:48"),
durationLabel: (variant.dir == TextDirection.rtl
? "دقيقتان ٤٨\u00a0ثانية"
: "2\u00a0minutes 48\u00a0secondes"),
artwork: const FlResultImage(
image: FlSampleImage(FlSampleArt.mug),
),
current: false,
playing: false,
currentLabel: (variant.dir == TextDirection.rtl
? "قيد التشغيل"
: "Now playing"),
onPressed: () {},
),
],
),
],
),
),
);API
FlTrackRow: class extends StatelessWidget
FlTrackRow.new: const new({super.key, required String title, required String subtitle, required String duration, String? durationLabel, Widget? artwork, bool current, bool playing, String? currentLabel, String? pausedLabel, VoidCallback? onPressed, String? number, Widget? trailing})
FlTrackRow.title: get String
FlTrackRow.subtitle: get String
FlTrackRow.duration: get String
FlTrackRow.durationLabel: get String?
FlTrackRow.artwork: get Widget?
FlTrackRow.current: get bool
FlTrackRow.playing: get bool
FlTrackRow.currentLabel: get String?
FlTrackRow.pausedLabel: get String?
FlTrackRow.onPressed: get VoidCallback?
FlTrackRow.number: get String?
FlTrackRow.trailing: get Widget?
FlTrackRow.build: Widget(BuildContext context)Reference renders
The 16 images published with version 0.2.3, rendered by the shared harness on macOS with Flutter 3.47.7. fliin verify track-row compares your copy to them.
















Use it to
- show the songs of an album or playlist with their length
- show a song row that marks the track playing
- pick a song in a list to hear it
- show the artwork and artist of each track
- show a track length in hours, minutes and seconds
- Not for
- the whole library screen: use the music library (library)
- States