code milestone 3

紅寶鐵軌客
Join to follow...
Follow/Unfollow Writer: 紅寶鐵軌客
By following, you’ll receive notifications when this author publishes new articles.
Don't wait! Sign up to follow this writer.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.
寫程式中、折磨中、享受中 ......
576   0  
·
2021/07/11
·
4 mins read


這是 milestone 3 的程式碼:

lib/main.dart:

import 'package:flutter/material.dart';
import 'package:happy_recorder/screens/audio_session.dart';
import 'package:happy_recorder/screens/my_home_page.dart';
import 'package:happy_recorder/screens/page_404.dart';
import 'package:happy_recorder/theme/style.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: themeCustomLight,
      darkTheme: themeCustomDark, // Provide dark theme.
      themeMode: ThemeMode.system,
      initialRoute: '/',
      routes: {
        '/': (context) => MyHomePage(title: 'Happy Recorder v0.0'),
        '/audio': (context) => AudioSession(
            arIndex: (ModalRoute.of(context)!.settings.arguments as int)),
      },
      onUnknownRoute: (RouteSettings settings) {
        return MaterialPageRoute(
            builder: (_) => Page404(routeName: settings.name));
      },
    );
  }
}


lib/theme/style.dart:

import 'package:flutter/material.dart';

//
// 完全使用 Material light/dark 預設
//
final themeLight = ThemeData.light().copyWith(
  primaryColor: Colors.deepPurple,
  /*
  // fontFamily 不能用
  // textTheme 等等設定需要依照 light 及 dart 各設定一次,非常不 DRY
  textTheme: ThemeData.light().textTheme.copyWith(
    headline1: TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold),
    headline6: TextStyle(fontSize: 18.0, fontStyle: FontStyle.italic),
    bodyText2: TextStyle(fontSize: 15.0, fontFamily: 'Hind'),
  ),
  */
);
final themeDark = ThemeData.dark().copyWith(
  primaryColor: Colors.blueGrey,
);

//
// 使用 ThemeData.from 設定色盤
//
final themeFromLight = ThemeData.from(
  // 只能設定 textTheme 及 colorScheme, 其他通通都不能用
  textTheme: myBaseTextTheme,
  colorScheme: const ColorScheme.light(
          //secondary: Colors.red,
          )
      .copyWith(
    primary: Colors.deepPurple,
  ),
);
final themeFromDark = ThemeData.from(
  textTheme: myBaseTextTheme,
  colorScheme: const ColorScheme.dark(
          //secondary: Colors.red,
          )
      .copyWith(
    primary: Colors.blueGrey,
  ),
);

//
// 自定 Theme
//
final themeCustomLight = ThemeData(
  brightness: Brightness.light,
  colorScheme: ColorScheme.light().copyWith(
      primary: Colors.pink,
      secondary: Colors.pinkAccent,
      background: Colors.blueGrey[100]),
  //accentColor no longer work, https://flutter.dev/docs/release/breaking-changes/theme-data-accent-properties
  textTheme: myBaseTextTheme,
  // fontFamily: 'Georgia', // 還是 light, dark 都要寫一次
  appBarTheme: AppBarTheme(
    backgroundColor: Colors.pink,
  ),
  bottomAppBarTheme: BottomAppBarTheme(
    color: Colors.pink,
  ),
  floatingActionButtonTheme: myFabTheme,
);

final themeCustomDark = ThemeData(
  brightness: Brightness.dark,
  colorScheme: ColorScheme.dark().copyWith(primary: Colors.blue),
  textTheme: myBaseTextTheme,
  floatingActionButtonTheme: myFabTheme,
);

const myFabTheme = FloatingActionButtonThemeData(
  foregroundColor: Colors.yellow,
  backgroundColor: Colors.pink,
  shape: CircleBorder(
    side: BorderSide(
      width: 3,
      color: Colors.red,
      style: BorderStyle.solid,
    ),
  ),
);

const myBaseTextTheme = TextTheme(
  headline5: TextStyle(
      fontSize: 20.0, fontWeight: FontWeight.w800, fontFamily: 'JBMono'),
  headline6: TextStyle(
      fontSize: 18.0, fontWeight: FontWeight.w600, fontFamily: 'JBMono'),
  subtitle1:
      TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold), // ListTile title
  subtitle2: TextStyle(
      fontSize: 18.0, fontWeight: FontWeight.normal, fontFamily: 'JBMono'),
  bodyText2: TextStyle(
      fontSize: 16.0, fontStyle: FontStyle.italic), // ListTile subtitle
);


lib/screens/my_home_page.dart:

import 'package:flutter/material.dart';
import 'package:happy_recorder/models/audio_rec.dart';
import 'package:happy_recorder/theme/style.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  //int _counter = 0;
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  void _openDrawer() {
    _scaffoldKey.currentState!.openDrawer();
  } // _openDrawer()

  void _closeDrawer() {
    Navigator.of(context).pop();
  } // _closeDrawer()

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: audioRec.length,
        itemBuilder: (context, index) {
          return Hero(
            tag: 'audio_rec_$index',
            child: Card(
              child: ListTile(
                title: Text(audioRec[index].title),
                subtitle: Text(audioRec[index].description),
                onTap: () {
                  Navigator.pushNamed(context, '/audio', arguments: index);
                },
                trailing: Icon(
                  Icons.play_arrow,
                  color: Theme.of(context).colorScheme.secondary,
                  //color: cardListArrow,
                  //semanticLabel: 'Play $audioRec[index].title audio',
                ),
              ),
            ),
          );
        },
      ),
      drawer: Drawer(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text('This is the Drawer'),
              ElevatedButton(
                onPressed: _closeDrawer,
                child: const Text('Close Drawer'),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        child: Container(height: 30.0),
      ),
      floatingActionButton: FloatingActionButton(
        //onPressed: _incrementCounter,
        onPressed: () {
          Navigator.pushNamed(context, '/new');
        },
        tooltip: 'new recording',
        child: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }
}


lib/screens/audio_session.dart:

import 'package:flutter/material.dart';
import 'package:happy_recorder/models/audio_rec.dart';

class AudioSession extends StatefulWidget {
  final int arIndex;

  // do we need key?
  AudioSession({Key? key, required this.arIndex}) : super(key: key);
  //AudioSession({required this.arIndex});

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

class _AudioSessionState extends State<AudioSession> {
  int _selectedBottomBarItemIndex = 0;

  void _onBottomBarItemTapped(int index) {
    setState(() {
      _selectedBottomBarItemIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      appBar: AppBar(
        title: Text("Record"),
        // automaticallyImplyLeading: false, // not display <- back btn
      ),
      body: Container(
        padding: const EdgeInsets.all(5.0),
        //color: Theme.of(context).scaffoldBackgroundColor,
        child:
          Column(
            children: [
              Hero(
                tag: 'audio_rec_${widget.arIndex}',
                child: Card(
                  child: ListTile(
                    title: Text(audioRec[widget.arIndex].title),
                    subtitle: Text(audioRec[widget.arIndex].description),
                  ),
                ),
              ),
              Container(
                width: double.infinity, // make it max width,
                padding: const EdgeInsets.all(10.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // Dart 2.3 以上才支援
                    if (_selectedBottomBarItemIndex != 0)
                      Text(
                        "Bottom bar $_selectedBottomBarItemIndex selected",
                        //style: TextStyle(fontFamily: 'JBMono', fontSize: 18),
                        style: Theme.of(context).textTheme.subtitle2,
                      )
                    else
                      Text(
                        "nothing selected",
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                    Text(' '),
                    Text(
                      'Audio info',
                      style: Theme.of(context).textTheme.headline5,
                    ),
                  ],
                ),
              ),
            ],
          ),
      ),
      // bottomNavigationBar 不使用 BottomNavigationBar() 是因為它的按鈕一定有一個預設是已選定
      bottomNavigationBar: Container(
        height: 110,
        padding: const EdgeInsets.only(top: 10.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Column(
              children: [
                Ink(
                  decoration: ShapeDecoration(
                    color: Theme.of(context).colorScheme.secondary,
                    //color: Colors.black,
                    shape: CircleBorder(),
                  ),
                  child: IconButton(
                    icon: const Icon(Icons.record_voice_over),
                    iconSize: 38,
                    color: Theme.of(context).bottomAppBarColor,
                    onPressed: () {
                      _onBottomBarItemTapped(1);
                    },
                  ),
                ),
                Text(
                  'record',
                  style: TextStyle(color: Theme.of(context).colorScheme.secondary.withOpacity(0.8)),
                ),
              ],
            ),
            Column(
              children: [
                Ink(
                  decoration: ShapeDecoration(
                    color: Theme.of(context).colorScheme.secondary,
                    shape: CircleBorder(),
                  ),
                  child: IconButton(
                    icon: const Icon(Icons.stop),
                    iconSize: 38,
                    color: Theme.of(context).bottomAppBarColor,
                    onPressed: () {
                      Navigator.pop(context);
                    },
                  ),
                ),
                Text(
                  'stop',
                  style: TextStyle(color: Theme.of(context).colorScheme.secondary.withOpacity(0.8)),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}


lib/screens/page_404.dart:

import 'package:flutter/material.dart';

class Page404 extends StatelessWidget {
  const Page404({Key? key, required this.routeName}) : super(key: key);

  final String? routeName;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Going to " + (routeName ?? "null") + "?"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Page Not found'),
            SizedBox(height: 5),
            Icon(
              Icons.sentiment_very_dissatisfied_outlined,
              color: Theme.of(context).colorScheme.error,
            ),
          ],
        )
      )
    );
  }
}


lib/models/audio_rec.dart:

class AudioRec {
  final String title;
  final String description;

  AudioRec(this.title, this.description);
}

// Generate test data
List audioRec = List.generate( 20, (i) => AudioRec(
    'Audio $i',
    'An audio description for audio $i title',
  ),
);




WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.


Article info

This article is part of:
Categories:
Tags:
Total: 906 words


Share this article:
About the Author

很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯




Join the discussion now!
Don't wait! Sign up to join the discussion.
WriterShelf is a privacy-oriented writing platform. Unleash the power of your voice. It's free!
Sign up. Join WriterShelf now! Already a member. Login to WriterShelf.