Tutorial Membuat Aplikasi Al-Quran Dengan Flutter #6: Menampilkan Detail Surah


👍 0 ❤️ 0 💡 0 🔥 0 🙌 0 🥳 0
Tutorial Membuat Aplikasi Al-Quran Dengan Flutter #6: Menampilkan Detail Surah

Halo teman-teman, kita hampir di ujung seri artikel nih, sebelumnya kita kan membuat daftar surah, selanjutnya kita akan menampilkan detail surah, jadi jika klik salah satu dari daftar surah nanti akan menuju halaman detail surah.

Pada halaman detail surah nanti kita membuat tampilan detail surah, lalu membuat daftar ayat serta kita akan membuat media player untuk memutar audio.

Langkah 1 - Membuat DetailSurah

Langkah pertama kita buat file dengan nama detail_surah_page.dart pada folder /lib, lalu pada file tersebut kita ketik kode berikut:

import 'package:alquran_flutter/detail_surah_model.dart';
import 'package:alquran_flutter/remote_resource.dart';
import 'package:flutter/material.dart';

class DetailSurahPage extends StatefulWidget {
  final int id;
  const DetailSurahPage({super.key, required this.id});

  @override
  State<DetailSurahPage> createState() => _DetailSurahPageState();
}

class _DetailSurahPageState extends State<DetailSurahPage> {
  final remoteResource = RemoteResource();
  final List<Ayat> ayatList = [];
  DetailSurahModel detailSurah = DetailSurahModel();

  @override
  void initState() {
    getDetailSurah(widget.id);
    super.initState();
  }

  void getDetailSurah(int id) async {
    final result = await remoteResource.detailSurah(id);
    result.fold(
      (error) => {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error: $error'))),
      },
      (data) {
        setState(() {
          detailSurah = data;
          ayatList.addAll(data.ayat ?? []);
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios_new_rounded),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: 200,
            padding: const EdgeInsets.all(12),
            margin: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.secondaryContainer,
              borderRadius: BorderRadius.circular(20),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      detailSurah.namaLatin ?? '',
                      style: const TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      detailSurah.nama ?? '',
                      style: const TextStyle(
                        fontSize: 26,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
                Divider(
                  color: Colors.blueGrey.withValues(alpha: 0.5),
                  thickness: 1,
                  height: 20,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Column(
                      spacing: 2,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '(${detailSurah.arti})',
                          style: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                        Text(
                          '${detailSurah.tempatTurun?.toUpperCase()} | ${detailSurah.jumlahAyat} Ayat',
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: ayatList.length,
              itemBuilder: (context, index) {
                return cardAyat(ayatList[index]);
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget cardAyat(Ayat ayat) {
    return Card(
      elevation: 0.5,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          spacing: 8,
          children: [
            Row(
              spacing: 4,
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Container(
                  padding: EdgeInsets.all(5),
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Theme.of(context).colorScheme.primary,
                      width: 1,
                    ),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Text(
                    '${ayat.surah}:${ayat.nomor}',
                    style: TextStyle(fontSize: 11),
                  ),
                ),

                Expanded(
                  child: Directionality(
                    textDirection: TextDirection.rtl,
                    child: Text(
                      ayat.ar ?? '',
                      style: const TextStyle(fontSize: 24),
                    ),
                  ),
                ),
              ],
            ),
            Text('${ayat.idn}'),
          ],
        ),
      ),
    );
  }
}

Penambahan kode di atas yang pertama import beberapa package atau library yang dibutuhkan.

import 'package:alquran_flutter/detail_surah_model.dart';
import 'package:alquran_flutter/remote_resource.dart';
import 'package:flutter/material.dart';

lalu pada kelas DetailSurahPage() kita membuat construktur dengan nama id dengan tipe data int, konstrutor ini digunakan untuk menerima data berniali angka.

class DetailSurahPage extends StatefulWidget {
  final int id;
  const DetailSurahPage({super.key, required this.id});

  @override
  State<DetailSurahPage> createState() => _DetailSurahPageState();
}

Lalu kita inisialisasi remoteresource dan bebeberapa model dan variabel.

class _DetailSurahPageState extends State<DetailSurahPage> {
  final remoteResource = RemoteResource();
  final List<Ayat> ayatList = [];
  DetailSurahModel detailSurah = DetailSurahModel();
...
}

Lalu kita membuat fungsi untuk mendapatkan data dari remote service dengan nama void getDetailSurah(int id), lalu kita panggil pada methode initState(), dengan memasukkan parameter id surah yang di ambil dari widget.id

void initState() {
    getDetailSurah(widget.id);
    super.initState();
  }

  void getDetailSurah(int id) async {
    final result = await remoteResource.detailSurah(id);
    result.fold(
      (error) => {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error: $error'))),
      },
      (data) {
        setState(() {
          detailSurah = data;
          ayatList.addAll(data.ayat ?? []);
        });
      },
    );
  }

lalu kita membuat tampilan kartu untuk ayat nanti dengan Widget cardAyat().

Widget cardAyat(Ayat ayat) {
    return Card(
      elevation: 0.5,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          spacing: 8,
          children: [
            Row(
              spacing: 4,
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Container(
                  padding: EdgeInsets.all(5),
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Theme.of(context).colorScheme.primary,
                      width: 1,
                    ),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Text(
                    '${ayat.surah}:${ayat.nomor}',
                    style: TextStyle(fontSize: 11),
                  ),
                ),

                Expanded(
                  child: Directionality(
                    textDirection: TextDirection.rtl,
                    child: Text(
                      ayat.ar ?? '',
                      style: const TextStyle(fontSize: 24),
                    ),
                  ),
                ),
              ],
            ),
            Text('${ayat.idn}'),
          ],
        ),
      ),
    );
  }

Lalu kita tampilkan pada ui utama pada method build().

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios_new_rounded),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: 200,
            padding: const EdgeInsets.all(12),
            margin: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.secondaryContainer,
              borderRadius: BorderRadius.circular(20),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      detailSurah.namaLatin ?? '',
                      style: const TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      detailSurah.nama ?? '',
                      style: const TextStyle(
                        fontSize: 26,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
                Divider(
                  color: Colors.blueGrey.withValues(alpha: 0.5),
                  thickness: 1,
                  height: 20,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Column(
                      spacing: 2,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '(${detailSurah.arti})',
                          style: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                        Text(
                          '${detailSurah.tempatTurun?.toUpperCase()} | ${detailSurah.jumlahAyat} Ayat',
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: ayatList.length,
              itemBuilder: (context, index) {
                return cardAyat(ayatList[index]);
              },
            ),
          ),
        ],
      ),
    );
  }

Langkah 2 - Membuat Audio Player

Langkah selanjutnya kita akan membuat audio player untuk memutar audio dari internet, kita buka file detail_surah_page.dart lalu rubah kode menjadi berikut;

import 'package:alquran_flutter/detail_surah_model.dart';
import 'package:alquran_flutter/remote_resource.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';

class DetailSurahPage extends StatefulWidget {
  final int id;
  const DetailSurahPage({super.key, required this.id});

  @override
  State<DetailSurahPage> createState() => _DetailSurahPageState();
}

class _DetailSurahPageState extends State<DetailSurahPage> {
  final remoteResource = RemoteResource();
  final List<Ayat> ayatList = [];
  DetailSurahModel detailSurah = DetailSurahModel();

  late AudioPlayer player;
  Stream<Duration> get _positionStream => player.positionStream;
  Stream<Duration?> get _durationStream => player.durationStream;

  @override
  void dispose() {
    player.dispose();
    super.dispose();
  }

  @override
  void initState() {
    player = AudioPlayer();
    getDetailSurah(widget.id);
    super.initState();
  }

  void getDetailSurah(int id) async {
    final result = await remoteResource.detailSurah(id);
    result.fold(
      (error) => {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error: $error'))),
      },
      (data) {
        setState(() {
          detailSurah = data;
          ayatList.addAll(data.ayat ?? []);
        });
        player.setUrl(detailSurah.audio ?? '');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios_new_rounded),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: 200,
            padding: const EdgeInsets.all(12),
            margin: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.secondaryContainer,
              borderRadius: BorderRadius.circular(20),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      detailSurah.namaLatin ?? '',
                      style: const TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      detailSurah.nama ?? '',
                      style: const TextStyle(
                        fontSize: 26,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
                Divider(
                  color: Colors.blueGrey.withValues(alpha: 0.5),
                  thickness: 1,
                  height: 20,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Column(
                      spacing: 2,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '(${detailSurah.arti})',
                          style: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                        Text(
                          '${detailSurah.tempatTurun?.toUpperCase()} | ${detailSurah.jumlahAyat} Ayat',
                        ),
                      ],
                    ),
                    StreamBuilder<PlayerState>(
                      stream: player.playerStateStream,
                      builder: (context, snapshot) {
                        final playerState = snapshot.data;
                        final processingState = playerState?.processingState;
                        final playing = playerState?.playing ?? false;

                        if (processingState == ProcessingState.loading ||
                            processingState == ProcessingState.buffering) {
                          return IconButton(
                            icon: CircularProgressIndicator(),
                            onPressed: null,
                          );
                        } else if (playing) {
                          return AnimatedSwitcher(
                            duration: Duration(milliseconds: 300),
                            child: IconButton(
                              icon: Icon(
                                Icons.pause_circle_filled,
                                size: 48,
                                color: Theme.of(context).colorScheme.secondary,
                              ),
                              onPressed: player.pause,
                            ),
                          );
                        } else {
                          return AnimatedSwitcher(
                            duration: Duration(milliseconds: 300),
                            child: IconButton(
                              icon: Icon(
                                Icons.play_circle_filled,
                                size: 42,
                                color: Theme.of(context).colorScheme.secondary,
                              ),
                              onPressed: player.play,
                            ),
                          );
                        }
                      },
                    ),
                  ],
                ),
                StreamBuilder<Duration>(
                  stream: _positionStream,
                  builder: (context, positionSnapshot) {
                    final position = positionSnapshot.data ?? Duration.zero;
                    return StreamBuilder<Duration?>(
                      stream: _durationStream,
                      builder: (context, durationSnapshot) {
                        final duration = durationSnapshot.data ?? Duration.zero;
                        return Slider(
                          value: position.inSeconds.toDouble(),
                          min: 0,
                          max: duration.inSeconds.toDouble(),
                          onChanged:
                              (value) =>
                                  player.seek(Duration(seconds: value.toInt())),
                          activeColor: Theme.of(context).colorScheme.secondary,
                          // Color of the part already played
                          inactiveColor: Colors.grey[300],
                        );
                      },
                    );
                  },
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: ayatList.length,
              itemBuilder: (context, index) {
                return cardAyat(ayatList[index]);
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget cardAyat(Ayat ayat) {
    return Card(
      elevation: 0.5,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          spacing: 8,
          children: [
            Row(
              spacing: 4,
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Container(
                  padding: EdgeInsets.all(5),
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Theme.of(context).colorScheme.primary,
                      width: 1,
                    ),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Text(
                    '${ayat.surah}:${ayat.nomor}',
                    style: TextStyle(fontSize: 11),
                  ),
                ),

                Expanded(
                  child: Directionality(
                    textDirection: TextDirection.rtl,
                    child: Text(
                      ayat.ar ?? '',
                      style: const TextStyle(fontSize: 24),
                    ),
                  ),
                ),
              ],
            ),
            Text('${ayat.idn}'),
          ],
        ),
      ),
    );
  }
}

Perubahan kode diatas yang pertama memasukkan library audio player,

import 'package:just_audio/just_audio.dart';

Lalu inisisalaisasi libray just_audio dengan nama kelas AudioPlayer dan membuat dua varibel untuk menentukan durasi audio, lalu tidak lupa kita inisialisasi player pada iniState, serta dispose ketika kelas AudioPlayer tidak digunakan.

late AudioPlayer player;
Stream<Duration> get _positionStream => player.positionStream;
Stream<Duration?> get _durationStream => player.durationStream;

@override
void dispose() {
 player.dispose();
 super.dispose();
}

@override
void initState() {
 player = AudioPlayer();
 getDetailSurah(widget.id);
 super.initState();
}

Kode di atase menggunakan Stream<Duration> yang artinya stream ini mengalirkan data yang bertipe data duration, serta untuk mengaksesnya menggunakan get dimasukkan dalam variabel yang dibuat.

Lalu kita masukkan atau set url untuk audio yang nati kita putar pada fungsi getDetailSurah pada method result.fold pada parameter true atau data benar

void getDetailSurah(int id) async {
    final result = await remoteResource.detailSurah(id);
    result.fold(
      (error) => {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error: $error'))),
      },
      (data) {
        setState(() {
          detailSurah = data;
          ayatList.addAll(data.ayat ?? []);
        });
        // memasukkan url audio
        player.setUrl(detailSurah.audio ?? '');
      },
    );
  }

Lalu kita membuat button untuk play audio

// Play Button Audio
StreamBuilder<PlayerState>(
  stream: player.playerStateStream,
  builder: (context, snapshot) {
    final playerState = snapshot.data;
    final processingState = playerState?.processingState;
    final playing = playerState?.playing ?? false;
    if (processingState == ProcessingState.loading ||
        processingState == ProcessingState.buffering) {
        return IconButton(
          icon: CircularProgressIndicator(),
          onPressed: null,
        );
    } else if (playing) {
      return AnimatedSwitcher(
        duration: Duration(milliseconds: 300),
        child: IconButton(
          icon: Icon(Icons.pause_circle_filled,
          size: 48,
          color: Theme.of(context).colorScheme.secondary,
        ),
        onPressed: player.pause,
        ),
      );
    } else {
      return AnimatedSwitcher(
        duration: Duration(milliseconds: 300),
        child: IconButton(
          icon: Icon(Icons.play_circle_filled,
            size: 42,
            color: Theme.of(context).colorScheme.secondary,
          ),
          onPressed: player.play,
        ),
      );
    }
  },
),

Kode di atas kita menggunakan widget StreamBuilder untuk membuat UI berdasarkan stream data.

player.playerStateStream ini Stream dari just_audio yang memancarkan objek PlayerState — ini mencakup status playing dan processingState.

Lalu mengambil data dari snapshot dari streamBuilder

final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing ?? false;

Lalu membuat loading ketika data di muat.

if (processingState == ProcessingState.loading ||
    processingState == ProcessingState.buffering) {
  return IconButton(
    icon: CircularProgressIndicator(),
    onPressed: null,
  );
}

lalu jika posisi audio diputar maka menampilkan icon pause.

else if (playing) {
  return AnimatedSwitcher(
    duration: Duration(milliseconds: 300),
    child: IconButton(
      icon: Icon(Icons.pause_circle_filled, size: 48),
      onPressed: player.pause,
    ),
  );
}

lalu jika tidak memutar lagu akan menampilkan tombol play

else {
  return AnimatedSwitcher(
    duration: Duration(milliseconds: 300),
    child: IconButton(
      icon: Icon(Icons.play_circle_filled, size: 42),
      onPressed: player.play,
    ),
  );
}

Lalu kita membuat slider untuk mengetahui posisi lagu berapa menit

StreamBuilder<Duration>(
  stream: _positionStream,
  builder: (context, positionSnapshot) {
    final position = positionSnapshot.data ?? Duration.zero;
    return StreamBuilder<Duration?>(
      stream: _durationStream,
      builder: (context, durationSnapshot) {
      final duration = durationSnapshot.data ?? Duration.zero;
      return Slider(
        value: position.inSeconds.toDouble(),
        min: 0,
        max: duration.inSeconds.toDouble(),
        onChanged: (value) =>
          player.seek(Duration(seconds: value.toInt())),
          activeColor: Theme.of(context).colorScheme.secondary,
          // Color of the part already played
          inactiveColor: Colors.grey[300],
        );
      },
    );
  },
),

Langkah 3 - Membuat Navigation

Setelah membuat tampilan untuk detail surah, sekarang kita akan membuat navigasi yang nanti kita pasang pada halaman home_page.dart, jadi ketika kita memilih salah satu dari daftar surah nanti kita akan di arahkan ke halaman detail surah.

Kita buka file home_page.dart lalu kita tambahkan kode berikut:

Navigator.push(
	context,
	MaterialPageRoute(
		builder: (context) => DetailSurahPage(id: surah.nomor ?? 0),
	),
);

Kode di atas masukkan di bawah comment // Move to detail page, di dalam widget buildSurahCard(), sehingga widget tersebut menjadi berikut:

 Widget buildSurahCard(SurahModel surah) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
      margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.secondaryContainer,
        boxShadow: [
          BoxShadow(
            color: Colors.blueGrey.withValues(alpha: 0.5),
            spreadRadius: 0.5,
            offset: Offset(0, 0.5), // changes position of shadow
          ),
        ],
        borderRadius: BorderRadius.circular(20),
      ),
      child: InkWell(
        onTap: () {
          // Move to detail page
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => DetailSurahPage(id: surah.nomor ?? 0),
            ),
          );
        },
        child: Row(
          spacing: 8,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Stack(
              alignment: Alignment.center,
              children: [
                SvgPicture.asset(
                  'assets/icons/jewish-star.svg',
                  colorFilter: ColorFilter.mode(
                    Theme.of(context).colorScheme.secondary,
                    BlendMode.srcIn,
                  ),
                  width: 52,
                  height: 52,
                ),
                Center(
                  child: Text(
                    surah.nomor.toString(),
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
              ],
            ),
            Expanded(
              flex: 2,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    surah.namaLatin ?? '',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                  ),
                  Text(surah.arti ?? ''),
                ],
              ),
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(
                    '${surah.nama}',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  Text('${surah.jumlahAyat} Ayat'),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

Langkah 4 - Uji Coba

Sekarang kita jalankan aplikasi yang kita buat, lalu pada daftar surah kita pilih salah satu nanti tampilannya kurang lebih seperti berikut.

Lalu untuk detail halaman surah seperti berikut

Coba kita putar atau play audio, jika berhasil maka akan mengeluarkan suara.

Kesimpulan

Jadi pada artikel terakhir ini kita sudah banyak belajar bagaimana membuat halaman detail surah, lalu membuat audio player dengan package just_audio, serta membuat navigation yang mengarahkan dari daftar list surah ke halaman detail surah. Kurang lebih seperti itu Tutorial Membuat Aplikasi Al-Qur'an dengan Flutter. Terimakasih

Source Code : https://github.com/hunt3r6/flutter-alquran


Membangun Dashboard dan Aplikasi Android Food Store Dengan Laravel Filament, Flutter dan Payment Gateway


Faisal Mahadi
Mobile Apps Developer | Android Enthusiast | Keep Learning | Android Dev Serta Owner Hariankoding.com

Suka dengan tulisan di SantriKoding? Kamu bisa memberikan dukungan dengan berdonasi atau bagikan konten ini di sosial media. Terima kasih atas dukungan Anda!

KEBIJAKAN KOMENTAR

Saat memberikan komenatar silahkan memberikan informasi lengkap tentang error, seperti: screenshot, link kode, dll. Baca aturan komentar kami