Tugas 12 - Flutter Music Application

Pada tugas ini, saya akan mencoba membuat aplikasi pemutar musik tempat penggemar dapat terus mengikuti kabar terbaru dari artis favoritnya. Di dalam aplikasi akan ditampilkan foto dan deskripsi artist, album lagu, dan juga komentar fans. Berikut adalah beberapa kode program penting

playlist_home_screen.dart
Digunakan untuk menampilkan halaman home.

// Copyright 2022 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import '../../../shared/classes/classes.dart';
import '../../../shared/providers/providers.dart';
import '../../../shared/views/views.dart';

class PlaylistHomeScreen extends StatelessWidget {
  const PlaylistHomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    PlaylistsProvider playlistProvider = PlaylistsProvider();
    List<Playlist> playlists = playlistProvider.playlists;
    return LayoutBuilder(
      builder: (context, constraints) {
        return Scaffold(
          primary: false,
          appBar: AppBar(
            title: const Text('PLAYLISTS'),
            toolbarHeight: kToolbarHeight * 2,
          ),
          body: Column(
            children: [
              Expanded(
                child: GridView.builder(
                  padding: const EdgeInsets.all(15),
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: (constraints.maxWidth ~/ 175).toInt(),
                    childAspectRatio: 0.70,
                    mainAxisSpacing: 10,
                    crossAxisSpacing: 10,
                  ),
                  itemCount: playlists.length,
                  itemBuilder: (context, index) {
                    final playlist = playlists[index];
                    return GestureDetector(
                      child: ImageTile(
                        image: playlist.cover.image,
                        title: playlist.title,
                        subtitle: playlist.description,
                      ),
                      onTap: () =>
                          GoRouter.of(context).go('/playlists/${playlist.id}'),
                    );
                  },
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}


playlist_screen.dart
Untuk menampilkan halaman playlist.
// Copyright 2022 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import '../../../shared/classes/classes.dart';
import '../../../shared/extensions.dart';
import '../../../shared/views/adaptive_image_card.dart';
import '../../../shared/views/views.dart';
import 'playlist_songs.dart';

class PlaylistScreen extends StatelessWidget {
  const PlaylistScreen({required this.playlist, super.key});

  final Playlist playlist;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      final colors = Theme.of(context).colorScheme;
      final double headerHeight = constraints.isMobile
          ? max(constraints.biggest.height * 0.5, 450)
          : max(constraints.biggest.height * 0.25, 250);
      if (constraints.isMobile) {
        return Scaffold(
          appBar: AppBar(
            leading: BackButton(
              onPressed: () => GoRouter.of(context).go('/playlists'),
            ),
            title: Text(playlist.title),
            actions: [
              IconButton(
                icon: const Icon(Icons.play_circle_fill),
                onPressed: () {},
              ),
              IconButton(
                onPressed: () {},
                icon: const Icon(Icons.shuffle),
              ),
            ],
          ),
          body: ArticleContent(
            child: PlaylistSongs(
              playlist: playlist,
              constraints: constraints,
            ),
          ),
        );
      }
      return Scaffold(
        body: CustomScrollView(
          slivers: [
            SliverAppBar(
              leading: BackButton(
                onPressed: () => GoRouter.of(context).go('/playlists'),
              ),
              expandedHeight: headerHeight,
              pinned: false,
              flexibleSpace: FlexibleSpaceBar(
                background: AdaptiveImageCard(
                  axis: constraints.isMobile ? Axis.vertical : Axis.horizontal,
                  constraints:
                      constraints.copyWith(maxHeight: headerHeight).normalize(),
                  image: playlist.cover.image,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(
                        'PLAYLIST',
                        style: context.titleSmall!
                            .copyWith(color: colors.onSurface),
                      ),
                      Text(
                        playlist.title,
                        style: context.displaySmall!
                            .copyWith(color: colors.onSurface),
                      ),
                      Text(
                        playlist.description,
                        style: context.bodyLarge!.copyWith(
                          color: colors.onSurface.withOpacity(0.8),
                        ),
                      ),
                      const SizedBox(height: 8),
                      Row(
                        children: [
                          IconButton(
                            icon: Icon(
                              Icons.play_circle_fill,
                              color: colors.tertiary,
                            ),
                            onPressed: () {},
                          ),
                          TextButton.icon(
                            onPressed: () {},
                            icon: Icon(
                              Icons.shuffle,
                              color: colors.tertiary,
                            ),
                            label: Text(
                              'Shuffle',
                              style: context.bodySmall!.copyWith(
                                color: colors.tertiary,
                              ),
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
            SliverToBoxAdapter(
              child: ArticleContent(
                child: PlaylistSongs(
                  playlist: playlist,
                  constraints: constraints,
                ),
              ),
            ),
          ],
        ),
      );
    });
  }
}


playlist_songs.dart
Untuk menampilkan halaman artist.
// Copyright 2022 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../shared/classes/classes.dart';
import '../../../shared/extensions.dart';
import '../../../shared/playback/bloc/bloc.dart';
import '../../../shared/views/image_clipper.dart';
import '../../../shared/views/views.dart';

class PlaylistSongs extends StatelessWidget {
  const PlaylistSongs(
      {super.key, required this.playlist, required this.constraints});

  final Playlist playlist;
  final BoxConstraints constraints;

  @override
  Widget build(BuildContext context) {
    return AdaptiveTable<Song>(
      items: playlist.songs,
      breakpoint: 450,
      columns: const [
        DataColumn(
          label: Padding(
            padding: EdgeInsets.only(left: 20),
            child: Text('#'),
          ),
        ),
        DataColumn(
          label: Text('Title'),
        ),
        DataColumn(
          label: Padding(
            padding: EdgeInsets.only(right: 10),
            child: Text('Length'),
          ),
        ),
      ],
      rowBuilder: (context, index) => DataRow.byIndex(
        index: index,
        cells: [
          DataCell(
            // Add HoverableSongPlayButton
            HoverableSongPlayButton(
              // Add this line
              hoverMode: HoverMode.overlay, // Add this line
              song: playlist.songs[index], // Add this line
              child: Center(
                // Modify this line
                child: Text(
                  (index + 1).toString(),
                  textAlign: TextAlign.center,
                ),
              ),
            ),
          ),
          DataCell(
            Row(children: [
              Padding(
                padding: const EdgeInsets.all(2),
                child: ClippedImage(playlist.songs[index].image.image),
              ),
              const SizedBox(width: 10),
              Expanded(child: Text(playlist.songs[index].title)),
            ]),
          ),
          DataCell(
            Text(playlist.songs[index].length.toHumanizedString()),
          ),
        ],
      ),
      itemBuilder: (song, index) {
        return ListTile(
          onTap: () => BlocProvider.of<PlaybackBloc>(context).add(
            PlaybackEvent.changeSong(song),
          ),
          leading: ClippedImage(song.image.image),
          title: Text(song.title),
          subtitle: Text(song.length.toHumanizedString()),
        );
      },
    );
  }
}


Selain itu, terdapat 2 mode yaitu dark dan light. Potongan kode programnya adalah sebagai berikut.

theme.dart
ThemeData light([Color? targetColor]) {
    final _colors = colors(Brightness.light, targetColor);
    return ThemeData.light().copyWith(
      pageTransitionsTheme: pageTransitionsTheme,
      colorScheme: _colors,
      appBarTheme: appBarTheme(_colors),
      cardTheme: cardTheme(),
      listTileTheme: listTileTheme(_colors),
      bottomAppBarTheme: bottomAppBarTheme(_colors),
      bottomNavigationBarTheme: bottomNavigationBarTheme(_colors),
      navigationRailTheme: navigationRailTheme(_colors),
      tabBarTheme: tabBarTheme(_colors),
      drawerTheme: drawerTheme(_colors),
      scaffoldBackgroundColor: _colors.background,
      useMaterial3: true,
    );
  }

  ThemeData dark([Color? targetColor]) {
    final _colors = colors(Brightness.dark, targetColor);
    return ThemeData.dark().copyWith(
      pageTransitionsTheme: pageTransitionsTheme,
      colorScheme: _colors,
      appBarTheme: appBarTheme(_colors),
      cardTheme: cardTheme(),
      listTileTheme: listTileTheme(_colors),
      bottomAppBarTheme: bottomAppBarTheme(_colors),
      bottomNavigationBarTheme: bottomNavigationBarTheme(_colors),
      navigationRailTheme: navigationRailTheme(_colors),
      tabBarTheme: tabBarTheme(_colors),
      drawerTheme: drawerTheme(_colors),
      scaffoldBackgroundColor: _colors.background,
      useMaterial3: true,
    );
  }

Agar lebih memahami alur kode program yang ada, Anda dapat mengunjungi repositori github yang sudah saya berikan.

Berikut adalah beberapa hasil dari aplikasi yang dibuat.




Komentar

Postingan populer dari blog ini

Tugas 1 - Ulasan Sejarah Mobile Phone dan Pemrograman

Tugas 3 - Membuat Aplikasi Ucapan Ulang Tahun

Tugas 2 - Membuat Program Android Sederhana