Project Aplikasi Expense Tracker – Part 5

Pada main.dart digunakan stateful widget, karena proses render ulang tampilan dihandle disini.

import 'package:flutter/material.dart';

import './models/trans.dart';
import './widgets/expense_list.dart';
import './widgets/form_expense.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expense Tracker',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<Trans> _trans = [
    Trans(
        id: 'a001',
        title: 'Notebook Aspire A5',
        amount: 8200000,
        txdate: DateTime.now()),
    Trans(
        id: 'a002',
        title: 'Samsung Galaxy A5',
        amount: 3200000,
        txdate: DateTime.now()),
  ];

  void _addNewExpense(String newTitle, double newAmount) {
    final newExpense = Trans(
        id: DateTime.now().toString(),
        title: newTitle,
        amount: newAmount,
        txdate: DateTime.now());

    setState(() {
      _trans.add(newExpense);
    });
  }

  void _showFormExpense(BuildContext ctx) {
    showModalBottomSheet(
      context: ctx,
      builder: (_) {
        return FormExpense(_addNewExpense);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expense Tracker'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => _showFormExpense(context),
          )
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Card(
                color: Colors.blue,
                child: Text('Chart'),
              ),
              ExpenseList(_trans),
            ]),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => _showFormExpense(context),
      ),
    );
  }
}

Pembahasan Code

Fungsi untuk menambahkan data yang diinput user kedalam list dan mentrigger setState() untuk melakukan render ulang tampilan.

void _addNewExpense(String newTitle, double newAmount) {
  final newExpense = Trans(
      id: DateTime.now().toString(),
      title: newTitle,
      amount: newAmount,
      txdate: DateTime.now());

  setState(() {
    _trans.add(newExpense);
  });
}

Kita gunakan widget IconButton yang akan tampil disisi kanan atas, dan FloatingActionButton akan tampil dibawah. Ketika button ini ditekan, form input expense akan tampil.

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expense Tracker'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => _showFormExpense(context),
          )
        ],
      ),
...
...
...
body: SingleChildScrollView(
  child: Column(
...
...
...
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
  child: Icon(Icons.add),
  onPressed: () => _showFormExpense(context),
),

Fungsi _showFormExpense adalah fungsi untuk menampilkan form input dari form_expense.dart secara modal.

void _showFormExpense(BuildContext ctx) {
  showModalBottomSheet(
    context: ctx,
    builder: (_) {
      return FormExpense(_addNewExpense);
    },
  );
}

Menggunakan ThemeData

Kita akan bahas sedikit mengenai ThemeData, yang berguna untuk mengatur konsistensi styling pada design. Kita tambahkan code berikut pada class MyApp.

  • primaryColor, untuk mengatur warna appBar.
  • accentColor, untuk mengatur warna button, pada aplikasi ini floatingbutton.
  • textTheme, untuk semua warna Text widget.

Yang perlu diperhatikan adalah informasi pada ThemeData akan ditimpa oleh inline styling pada widget. (Sama seperti css styling pada html).

theme: ThemeData(
  primaryColor: Colors.red,
  accentColor: Colors.red[200],
  textTheme: TextTheme(bodyText2: TextStyle(color: Colors.purple)),
),
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expense Tracker',
      theme: ThemeData(
        primaryColor: Colors.red,
        accentColor: Colors.red[200],
        textTheme: TextTheme(bodyText2: TextStyle(color: Colors.purple)),
      ),
      home: MyHomePage(),
    );
  }
}

Perhatian, karena Flutter ada SDK yang masih berkembang, ada kemungkinan dikemudian hari code diatas tidak berjalan. Silakan lihat dokumentasi terbaru ThemeData.

Sharing is caring:

Leave a Comment