본문 바로가기

코딩강의/expense_tracker(플러터-유데미)

~125. Using Theme Data in Widgets

1. 테마 지정하기

- 앱 전체에 반영할 테마를 세팅해보자. 기본 개념은, useMeterial3 테마를 기반으로 내가 하나씩 더 얹히는 느낌.

 

2. 세팅된 테마를 위젯에 적용시켜보자.

- 자동적용 되는게 있고, 내가 위젯을 만들었을 때 테마에서 만든걸 가지고 올수도 있다.

 

- main.dart

import 'package:flutter/material.dart';

import 'package:expense_tracker/wigets/expenses.dart';

var kColorScheme =
    ColorScheme.fromSeed(seedColor: const Color.fromARGB(255, 96, 59, 181));

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData().copyWith(
        useMaterial3: true,
        colorScheme: kColorScheme,
        appBarTheme: const AppBarTheme().copyWith(
          backgroundColor: kColorScheme.onPrimaryContainer,
          foregroundColor: kColorScheme.primaryContainer,
        ),
        cardTheme: const CardTheme().copyWith(
          color: kColorScheme.secondaryContainer,
          margin: const EdgeInsets.symmetric(
            horizontal: 16,
            vertical: 8,
          ),
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
              backgroundColor: kColorScheme.primaryContainer),
        ),
        textTheme: ThemeData().textTheme.copyWith(
              titleLarge: TextStyle(
                fontWeight: FontWeight.bold,
                color: kColorScheme.onSecondaryContainer,
                fontSize: 16,
              ),
            ),
      ),
      home: const Expenses(),
    ),
  );
}

1) fromSeed는 해당 컬러를 기반으로 응용해서 알아서 컬러가 지정된다. (1인 개발할 때 좋을듯, 컬러감각 없을 때)

2) copyWith를 통해서 기존 테마를 내가 매뉴얼하게 수정할수도 있다.

3) 텍스트 테마도 바꿀수있음

 

- expense_list.dart

import 'package:expense_tracker/wigets/expenses_list/expense_item.dart';
import 'package:flutter/material.dart';

import 'package:expense_tracker/models/expense.dart';

class ExpensesList extends StatelessWidget {
  const ExpensesList(
      {super.key, required this.expenses, required this.onRemoveExpense});

  final List<Expense> expenses;
  final void Function(Expense expense) onRemoveExpense;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: expenses.length,
        itemBuilder: (ctx, index) => Dismissible(
            key: ValueKey(expenses[index]),
            background: Container(
              color: Theme.of(context).colorScheme.error.withOpacity(0.75),
              margin: EdgeInsets.symmetric(
                horizontal: Theme.of(context).cardTheme.margin!.horizontal,
              ),
            ),
            onDismissed: (direction) {
              onRemoveExpense(expenses[index]);
            },
            child: ExpenseItem(expenses[index])));
  }
}

1) Dismissible 부분 테마 적용 (스와이프 했을 때 백그라운드 배경 설정)

이건 플러터 내부 colorScheme에서 있는걸 가져와서 적용했다. 그리고 간격은 내가 매뉴얼하게 테마 설정한 것을 가지고 와서 적용했다.

 

- expense_item.dart

import 'package:flutter/material.dart';

import 'package:expense_tracker/models/expense.dart';

class ExpenseItem extends StatelessWidget {
  const ExpenseItem(this.expense, {super.key});

  final Expense expense;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: 20,
          vertical: 16,
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(expense.title, style: Theme.of(context).textTheme.titleLarge),
            const SizedBox(height: 4),
            Row(
              children: [
                Text('\$${expense.amount.toStringAsFixed(2)}'),
                const Spacer(),
                Row(
                  children: [
                    Icon(categoryIcons[expense.category]),
                    const SizedBox(width: 8),
                    Text(expense.formattedDate),
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

1) Text부분은 내가 지정한 테마를 가지고 와서 스타일을 적용하였다.

 

- 결과 화면