Fliin
On this page

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.

16 of 16 variants pass
Track row, current state
Platform
Brightness
Text scale
Direction

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-row

Also installs: core, list-row

Examples

Current

The track playing now: current and playing highlight it and tell the screen reader. The duration has a spoken form in durationLabel.

Track row, current state
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.

Track row, default state
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).

Track row, album state
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.

iOS · Light
Track row, iOS, Light, text 1.0×, Left to right
Text 1.0× · Left to right
Track row, iOS, Light, text 1.0×, Right to left
Text 1.0× · Right to left
Track row, iOS, Light, text 2.0×, Left to right
Text 2.0× · Left to right
Track row, iOS, Light, text 2.0×, Right to left
Text 2.0× · Right to left
iOS · Dark
Track row, iOS, Dark, text 1.0×, Left to right
Text 1.0× · Left to right
Track row, iOS, Dark, text 1.0×, Right to left
Text 1.0× · Right to left
Track row, iOS, Dark, text 2.0×, Left to right
Text 2.0× · Left to right
Track row, iOS, Dark, text 2.0×, Right to left
Text 2.0× · Right to left
Android · Light
Track row, Android, Light, text 1.0×, Left to right
Text 1.0× · Left to right
Track row, Android, Light, text 1.0×, Right to left
Text 1.0× · Right to left
Track row, Android, Light, text 2.0×, Left to right
Text 2.0× · Left to right
Track row, Android, Light, text 2.0×, Right to left
Text 2.0× · Right to left
Android · Dark
Track row, Android, Dark, text 1.0×, Left to right
Text 1.0× · Left to right
Track row, Android, Dark, text 1.0×, Right to left
Text 1.0× · Right to left
Track row, Android, Dark, text 2.0×, Left to right
Text 2.0× · Left to right
Track row, Android, Dark, text 2.0×, Right to left
Text 2.0× · Right to left

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
  • Current
  • Default

Arrows to move, Enter to open, Escape to close.