online software programming courses

Flutter E-book Reading App using Audio Player

Check out the project structure first

 

flutter project structure

Check out yaml.spec set up and create asset folder based on that

Yo need to store you images in img folder and json files in json folder. You can ignore the last folder named assets folder though

In your lib folder create three files and name them

app_colors.dart, my_home_page.dart and my_tabs.dart

Currently you don't have detail_audio_page.dart and audio_file.dart. Don't worry we will create them in tutorial below

 

Check out code for main.dart

import 'package:flutter/material.dart';

import 'my_home_page.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Audio App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

Code for MyHomePage and name it my_home_page.dart

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:audio/app_colors.dart' as AppColors;
import 'package:flutter/material.dart';

import 'my_tabs.dart';
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  List popularBooks;
  List books;
  ScrollController _scrollController;
  TabController _tabController;
  ReadData() async {
   await DefaultAssetBundle.of(context).loadString("json/popularBooks.json").then((s){
      setState(() {
       popularBooks = json.decode(s);
      });
    });
   await DefaultAssetBundle.of(context).loadString("json/books.json").then((s){
     setState(() {
       books = json.decode(s);
     });
   });
  }

  @override
  void initState(){
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
    _scrollController = ScrollController();
    ReadData();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: AppColors.background,
          child: SafeArea(
            child: Scaffold(
              body: Column(
                children: [
                  Container(
                    margin: const EdgeInsets.only(left: 20, right: 20),
                    child:  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      ImageIcon(AssetImage("img/menu.png"), size:24, color:Colors.black),
                      Row(
                        children: [
                          Icon(Icons.search),
                          SizedBox(width: 10,),
                          Icon(Icons.notifications),
                        ],
                      )
                    ],
                  ),
                  ),
                  SizedBox(height: 20,),
                  Row(
                    children: [
                      Container(
                        margin: const EdgeInsets.only(left: 20),
                        child: Text("Popular Books", style: TextStyle(fontSize: 30))

                      )
                    ],
                  ),
                  SizedBox(height: 20,),
                  Container(
                    height: 180,
                    child: Stack(
                     children: [

                      Positioned(
                        top:0,
                        left: -20,
                        right: 0,
                        child: Container(
                    height: 180,
                    child: PageView.builder(
                        controller: PageController(viewportFraction: 0.8),
                        itemCount: popularBooks==null?0:popularBooks.length,
                        itemBuilder: (_, i){
                      return Container(
                        height: 180,
                        width: MediaQuery.of(context).size.width,
                        margin: const EdgeInsets.only(right: 10),
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(15),
                          image:DecorationImage(
                            image:AssetImage(popularBooks[i]["img"]),
                            fit:BoxFit.fill,
                          )
                        ),
                      );
                    }),
                  )
                      )
                      ]

                    )
                  ),
                  Expanded(child: NestedScrollView(
                    controller: _scrollController,
                    headerSliverBuilder: (BuildContext context, bool isScroll){

                      return[
                        SliverAppBar(
                          pinned: true,
                            backgroundColor:AppColors.sliverBackground,
                          bottom: PreferredSize(
                            preferredSize: Size.fromHeight(50),
                            child: Container(
                              margin: const EdgeInsets.only(bottom: 20, left: 10),
                              child: TabBar(
                                indicatorPadding: const EdgeInsets.all(0),
                                indicatorSize: TabBarIndicatorSize.label,
                                labelPadding: const EdgeInsets.only(right: 10),
                                controller: _tabController,
                                isScrollable: true,
                                indicator: BoxDecoration(
                                  borderRadius: BorderRadius.circular(10),
                                  boxShadow: [
                                    BoxShadow(
                                      color:Colors.grey.withOpacity(0.2),
                                      blurRadius: 7,
                                      offset: Offset(0, 0),
                                    )
                                  ]
                                ),
                                tabs: [
                                  AppTabs(color:AppColors.menu1Color, text:"New"),
                                  AppTabs(color:AppColors.menu2Color, text:"Popular"),
                                  AppTabs(color:AppColors.menu3Color, text:"Trending"),
                                ],
                              ),
                            ),
                          ),
                        )
                      ];
                    },
                    body: TabBarView(
                      controller: _tabController,
                      children: [
                        ListView.builder(
                            itemCount: books==null?0:books.length,
                            itemBuilder: (_,i){
                          return
                           Container(
                            margin: const EdgeInsets.only(left:20, right: 20,top:10, bottom: 10),
                            child: Container(
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(10),
                                color:AppColors.tabVarViewColor,
                                boxShadow: [
                                  BoxShadow(
                                    blurRadius: 2,
                                    offset: Offset(0, 0),
                                    color:Colors.grey.withOpacity(0.2),
                                  )
                                ]
                              ),
                              child: Container(
                                padding: const EdgeInsets.all(8),
                                child: Row(
                                  children: [
                                    Container(
                                      width: 90,
                                      height: 120,
                                      decoration: BoxDecoration(
                                          borderRadius: BorderRadius.circular(10),
                                          image: DecorationImage(
                                            image: AssetImage(books[i]["img"]),
                                          )
                                      ),
                                    ),
                                    SizedBox(width: 10,),
                                    Column(
                                      crossAxisAlignment: CrossAxisAlignment.start,
                                      children: [
                                        Row(
                                          children: [
                                            Icon(Icons.star, size:24, color:AppColors.starColor),
                                            SizedBox(width: 5,),
                                            Text(books[i]["rating"], style: TextStyle(
                                                color:AppColors.menu2Color
                                            ),),
                                          ],
                                        ),
                                        Text(books[i]["title"], style: TextStyle(fontSize: 16, fontFamily: "Avenir", fontWeight: FontWeight.bold),),
                                        Text(books[i]["text"], style: TextStyle(fontSize: 16, fontFamily: "Avenir", color:AppColors.subTitleText),),
                                        Container(
                                          width: 60,
                                          height: 20,
                                          decoration: BoxDecoration(
                                            borderRadius: BorderRadius.circular(3),
                                            color:AppColors.loveColor,
                                          ),
                                          child:Text("Love", style: TextStyle(fontSize: 10, fontFamily: "Avenir", color:Colors.white),),
                                          alignment: Alignment.center,
                                        )
                                      ],
                                    )
                                  ],
                                ),
                              ),
                            ),
                          );

                        }),
                        Material(
                          child: ListTile(
                            leading: CircleAvatar(
                              backgroundColor: Colors.grey,
                            ),
                            title: Text("Content"),
                          ),

                        ),
                        Material(
                          child: ListTile(
                            leading: CircleAvatar(
                              backgroundColor: Colors.grey,
                            ),
                            title: Text("Content"),
                          ),

                        ),
                      ],

                    ),
                  ))
                ],
              ),
            ),
          ),
    );
  }
}

Code for AppColors and name it app_colors.dart

import 'dart:ui';


final Color background = Color(0xFFfafafc);
final Color sliverBackground = Color(0xFFfafafc);
final Color menu1Color=Color(0xFFf9d263);
final Color menu2Color= Color(0xFFf2603d);
final Color menu3Color= Color(0xFF04abe6);
final Color tabVarViewColor=Color(0xFFfdfdfd);
final Color starColor=Color(0xFFfdc746);
final Color subTitleText=Color(0xFFc5c4ca);
final Color loveColor=Color(0xFF00ace6);
final Color audioBluishBackground=Color(0xFfdee7fa);
final Color audioBlueBackground= Color(0xFF04abe7);
final Color audioGreyBackground=Color(0xFFf2f2f2);

Code for my_tabs.dart

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

class AppTabs extends StatelessWidget {
  final Color color;
  final String text;
  const AppTabs({Key key, this.color, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return   Container(
      width:120,
      height: 50,
      child: Text(
        this.text, style: TextStyle(color:Colors.white, fontSize: 20),

      ),
      alignment: Alignment.center,

      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10),
          color:this.color,
          boxShadow: [
            BoxShadow(
              color:Colors.grey.withOpacity(0.3),
              blurRadius: 7,
              offset: Offset(0, 0),
            )
          ]
      ),
    );
  }
}

In your project folder create another folder and name it json. Then create two files name as books.json and popularBooks.json and copy the code

JSON file books.JSON

[
  {
    "rating": "4.5",
    "title":"THE WATER CURE",
    "text":"Martin Hyatt",
    "img": "img/pic-1.png",
    "audio": "https://st.bslmeiyu.com/uploads/%e6%9c%97%e6%96%87%e5%9b%bd%e9%99%85SBS%e7%b3%bb%e5%88%97/%e6%9c%97%e6%96%87%e5%9b%bd%e9%99%85%e8%8b%b1%e8%af%ad%e6%95%99%e7%a8%8b%e7%ac%ac1%e5%86%8c_V2/%e5%ad%a6%e7%94%9f%e7%94%a8%e4%b9%a6/P149_Chapter%2016_Vocabulary%20Preview.mp3"
  },
  {
    "rating": "4.5",
    "title":"PEACE LIFE",
    "text":"Hazard Bin",
    "img": "img/pic-2.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC2%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P027_Side%20by%20Side%20Gazette%2001_2Build%20Your%20Vocabulary!.mp3"
  },
  {
    "rating": "4.5",
    "title":"Day Remember",
    "text":"Nicholos",
    "img": "img/pic-3.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC2%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P027_Side%20by%20Side%20Gazette%2001_2Build%20Your%20Vocabulary!.mp3"
  },
  {
    "rating": "4.5",
    "title":"France",
    "text":"Paris",
    "img": "img/pic-4.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC1%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P150_Chapter%2016_1Model%20Conversation.mp3"
  },
  {
    "rating": "4.5",
    "title":"Germany",
    "text":"Berlin",
    "img": "img/pic-5.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC1%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P150_Chapter%2016_1Model%20Conversation.mp3"
  },
  {
    "rating": "4.5",
    "title":"Italy",
    "text":"Rome",
    "img": "img/pic-1.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC1%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P150_Chapter%2016_1Model%20Conversation.mp3"
  },
  {
    "rating": "4.5",
    "title":"Switzerland",
    "text":"Bern",
    "img": "img/pic-1.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC1%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P150_Chapter%2016_1Model%20Conversation.mp3"
  },
  {
    "rating": "4.5",
    "title":"Singapore",
    "text":"Singapore",
    "img": "img/pic-1.png",
    "audio": "https://st.bslmeiyu.com/uploads/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85SBS%E7%B3%BB%E5%88%97/%E6%9C%97%E6%96%87%E5%9B%BD%E9%99%85%E8%8B%B1%E8%AF%AD%E6%95%99%E7%A8%8B%E7%AC%AC1%E5%86%8C_V2/%E5%AD%A6%E7%94%9F%E7%94%A8%E4%B9%A6/P150_Chapter%2016_1Model%20Conversation.mp3"
  }
]

Code for popularBooks.json

[
  {
    "rating": "4.5",
    "title":"THE WATER CURE",
    "text":"Martin Hyatt",
    "img": "img/pic-8.png",
    "audio": "Voices.mp3"
  },
  {
    "rating": "4.6",
    "title":"PEACE LIFE",
    "text":"Hazard Bin",
    "img": "img/pic-7.png",
    "audio": "June - Bobby Richards.mp3"
  },
  {
    "rating": "4.5",
    "title":"Day Remember",
    "text":"Nicholos",
    "img": "img/pic-6.png",
    "audio": "Muriel - Bobby Richards.mp3"
  },
  {
    "rating": "4.5",
    "title":"France",
    "text":"Paris",
    "img": "img/pic-9.png",
    "audio": "Piano Trap.mp3"
  },
  {
    "rating": "4.5",
    "title":"Germany",
    "text":"Berlin",
    "img": "img/pic-10.png",
    "audio": "Voices.mp3"
  }


]