Mobiilikehitys Flutterilla · Oppitunti

Material 3 -väriteemat ja siemenvärit

Luo harmonisia väriteemoja yhdestä siemenväristä ColorScheme.fromSeedin avulla.

Oppitunti 1/413 vaihetta

Material 3 -väriteemat ja siemenvärit on ilmainen Mobiilikehitys Flutterilla-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Mobiilikehitys Flutterilla-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Mikä on Material 3:n värijärjestelmä?

Material 3 (M3) toi käyttöön rakenteisen värijärjestelmän — joukon nimettyjä värien rooleja, joita koko sovellus käyttää yhdenmukaisesti. Sen sijaan että raakaheksadesimaaliarvoja ripoteltaisiin eri widgeteihin, määritätte rooleja, kuten primary, onPrimary, surface ja error, ja Flutterin teemoitusmoottori soveltaa niitä automaattisesti.

  • primary — painikkeissa, FAB-painikkeissa ja aktiivisissa välilehdissä käytettävä brändiväri
  • onPrimary — primary-värin päälle piirretty teksti tai kuvakkeet
  • surface — korttien, paneelien ja valintaikkunoiden taustaväri
  • onSurface — pinnoille piirretty teksti
  • error / onError — kelpoisuus- ja hälytysvärit

Jokaisesta roolista on sekä vaalea että tumma muunnelma, joten voitte tukea kumpaakin teemaa yhdellä värijärjestelmän määrittelyllä.

Mihin ColorScheme.fromSeed ratkaisee ongelman

Ennen M3:a kehittäjien piti valita käsin jokainen värien rooli — primary, secondary, tertiary, pinnat, säilöt ja niiden on-vastineet. Arvoja on yli 25, ja saavutettavien kontrastisuhteiden määrittäminen käsin altistaa virheille.

ColorScheme.fromSeed ratkaisee tämän ottamalla vastaan yhden siemenvärin ja käyttämällä Googlen HCT-väriavaruuden (Hue, Chroma, Tone) algoritmia täyden, harmonisen ja WCAG:n mukaisen paletin automaattiseen luomiseen.

  • Yksi syöte → yli 25 tulosroolia
  • Taataan kontrasti etu- ja taustaväriparien välillä
  • Vaalea ja tumma muunnelma samasta siemenväristä
  • Yhdenmukainen Material You -suunnittelukielen kanssa

Ensimmäinen ColorScheme.fromSeed

ColorScheme.fromSeed-koodin käyttäminen on suoraviivaista. Välittäkää se MaterialApp-widgetin sisällä ThemeData-oliolle. Flutter hoitaa loput.

seedColor-parametri hyväksyy minkä tahansa Color-arvon — yleensä brändivärinne. Flutter johtaa siitä koko paletin.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'M3 Theming Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4), // brand purple
        ),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Color Scheme Demo')),
      body: const Center(child: Text('Hello Material 3')),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.palette),
      ),
    );
  }
}

Vaalea ja tumma teema samasta siemenväristä

Yksi ColorScheme.fromSeed-menetelmän suurimmista eduista on, että sen avulla voit luoda sekä vaalean että tumman teeman samasta siemenväristä, mikä takaa visuaalisen yhtenäisyyden eri tiloissa.

Vaihda niiden välillä välittämällä brightness-parametri. Flutter säätää sävyt automaattisesti — tummissa teemoissa siemenväristä käytetään vaaleampia sävyjä tummilla pinnoilla.

import 'package:flutter/material.dart';

const Color _brandColor = Color(0xFF00897B); // teal brand

ThemeData lightTheme() => ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: _brandColor,
        brightness: Brightness.light,
      ),
      useMaterial3: true,
    );

ThemeData darkTheme() => ThemeData(
      colorScheme: ColorScheme.fromSeed(
        seedColor: _brandColor,
        brightness: Brightness.dark,
      ),
      useMaterial3: true,
    );

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: lightTheme(),
      darkTheme: darkTheme(),
      themeMode: ThemeMode.system, // follows device setting
      home: const Scaffold(
        body: Center(child: Text('Adaptive theme')),
      ),
    );
  }
}

Väriroolien käyttäminen widgeteissä

Kun ColorScheme on määritetty, voit käyttää sen rooleja kaikkialla lausekkeella Theme.of(context).colorScheme. Tällöin widgetit eivät ole sidoksissa kiinteästi määritettyihin väreihin, ja ne noudattavat automaattisesti vaaleaa tai tummaa tilaa.

Widgeteissä yleisesti käytettäviä rooleja:

  • colorScheme.primary — interaktiivisten elementtien korostusväri
  • colorScheme.onPrimary — ensisijaisten taustojen teksti- ja kuvakeväri
  • colorScheme.surface — korttien ja valintaikkunoiden taustat
  • colorScheme.onSurface — tekstin oletusväri
  • colorScheme.error — virhetilan ilmaisimet
import 'package:flutter/material.dart';

class StatusBadge extends StatelessWidget {
  final String label;
  final bool isActive;

  const StatusBadge({super.key, required this.label, required this.isActive});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
      decoration: BoxDecoration(
        color: isActive ? cs.primaryContainer : cs.surfaceContainerHighest,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Text(
        label,
        style: TextStyle(
          color: isActive ? cs.onPrimaryContainer : cs.onSurfaceVariant,
          fontWeight: FontWeight.w600,
        ),
      ),
    );
  }
}

Säilöroolit: primaryContainer ja kumppanit

M3 toi käyttöön säilöroolit — päävärien pehmeämmät ja vähemmän kromaattiset versiot, jotka on tarkoitettu käyttöliittymäelementtien, kuten sirujen, korttien ja täytettyjen painikkeiden, taustoiksi.

  • primaryContainer — pehmeä ensisijainen tausta (sopii esimerkiksi valituille siruille ja täytetyille tonaalisille painikkeille)
  • onPrimaryContainer — primaryContainerin päällä käytettävä teksti
  • secondaryContainer / tertiaryContainer — vastaavat roolit toissijaisille ja kolmassijaisille paleteille
  • errorContainer — pehmeä punainen väri tekstinsisäisille virheilmoituksille

Säilöjen käyttäminen taustoissa suoran primary-värin sijaan luo visuaalisen hierarkian ja pitää kontrastisuhteet turvallisina ilman opasiteetin manuaalista säätämistä.

import 'package:flutter/material.dart';

class InfoCard extends StatelessWidget {
  final String title;
  final String body;

  const InfoCard({super.key, required this.title, required this.body});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    return Card(
      color: cs.primaryContainer,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    color: cs.onPrimaryContainer,
                    fontWeight: FontWeight.bold,
                  ),
            ),
            const SizedBox(height: 8),
            Text(
              body,
              style: TextStyle(color: cs.onPrimaryContainer),
            ),
          ],
        ),
      ),
    );
  }
}

Yksittäisten roolien ohittaminen

Joskus tietylle roolille algoritmisesti luotu väri ei vastaa tarkasti brändiohjeistustasi. Voit ohittaa yksittäisiä rooleja käyttämällä lauseketta ColorScheme.fromSeed(...).copyWith(...). Tällöin kaikki automaattisesti luodut roolit säilyvät, mutta voit määrittää tietyille rooleille täsmälliset arvot.

Tämä toimintatapa on hyödyllinen esimerkiksi silloin, kun suunnittelujärjestelmäsi edellyttää error-roolille tarkkaa punaista sävyä, joka poikkeaa HCT-algoritmin tuottamasta väristä.

import 'package:flutter/material.dart';

ThemeData buildTheme() {
  // Start from seed, then pin specific roles
  final base = ColorScheme.fromSeed(
    seedColor: const Color(0xFF1565C0), // deep blue brand
  );

  return ThemeData(
    colorScheme: base.copyWith(
      // Exact error red from our design system
      error: const Color(0xFFB00020),
      onError: Colors.white,
      // Pin tertiary to our accent orange
      tertiary: const Color(0xFFE65100),
      onTertiary: Colors.white,
    ),
    useMaterial3: true,
  );
}

Dynaaminen väri: taustakuvaan mukautuminen

Android 12 ja uudemmat versiot tukevat dynaamista väriä — järjestelmä poimii siemenvärin käyttäjän taustakuvasta ja käyttää sitä kaikissa sovelluksissa. Flutter tukee tätä dynamic_color-paketin avulla.

Toimintatapa on seuraava: yritä ladata järjestelmän värimalli ja käytä omaa siemenväriäsi varalla, jos värimallia ei ole saatavilla (iOS:ssä, vanhemmissa Android-versioissa tai kun käyttäjä ei ole määrittänyt taustakuvaa).

Tämä saa sovelluksen tuntumaan tuetuilla laitteilla natiivilla ja henkilökohtaisella tavalla, mutta säilyttää yhtenäisyyden muualla.

// pubspec.yaml: dynamic_color: ^1.7.0

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

const Color _fallbackSeed = Color(0xFF6750A4);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return DynamicColorBuilder(
      builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
        final lightScheme = lightDynamic ??
            ColorScheme.fromSeed(
              seedColor: _fallbackSeed,
              brightness: Brightness.light,
            );

        final darkScheme = darkDynamic ??
            ColorScheme.fromSeed(
              seedColor: _fallbackSeed,
              brightness: Brightness.dark,
            );

        return MaterialApp(
          theme: ThemeData(colorScheme: lightScheme, useMaterial3: true),
          darkTheme: ThemeData(colorScheme: darkScheme, useMaterial3: true),
          themeMode: ThemeMode.system,
          home: const Scaffold(
            body: Center(child: Text('Dynamic Color')),
          ),
        );
      },
    );
  }
}

Paletin esikatselu väriruudukolla

Kehityksen aikana on hyödyllistä näyttää kaikki keskeiset väriroolit näytöllä, jotta voit tarkistaa luodun paletin visuaalisesti. Tämä debug-näkymä on nopea tapa tarkistaa kontrasti ja yhteensopivuus ennen julkaisua.

Rakenna yksinkertainen ruudukko, joka yhdistää roolien nimet niiden väreihin ja on-vastineisiin käyttämällä kontekstista saatavaa reaaliaikaista ColorScheme-arvoa.

import 'package:flutter/material.dart';

class PalettePreviewScreen extends StatelessWidget {
  const PalettePreviewScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    final roles = [
      ('Primary', cs.primary, cs.onPrimary),
      ('PrimaryContainer', cs.primaryContainer, cs.onPrimaryContainer),
      ('Secondary', cs.secondary, cs.onSecondary),
      ('SecondaryContainer', cs.secondaryContainer, cs.onSecondaryContainer),
      ('Tertiary', cs.tertiary, cs.onTertiary),
      ('Surface', cs.surface, cs.onSurface),
      ('Error', cs.error, cs.onError),
      ('ErrorContainer', cs.errorContainer, cs.onErrorContainer),
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('Color Palette')),
      body: ListView(
        children: roles.map((r) {
          final (name, bg, fg) = r;
          return Container(
            height: 56,
            color: bg,
            alignment: Alignment.centerLeft,
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Text(name, style: TextStyle(color: fg, fontWeight: FontWeight.w500)),
          );
        }).toList(),
      ),
    );
  }
}

Värimallien yleiset sudenkuopat

Vältä näitä virheitä käyttäessäsi M3-värimalleja:

  • Heksavärien määrittäminen kiinteästi widgeteissä — Käytä aina Theme.of(context).colorScheme.*, jotta widgetit reagoivat teeman muutoksiin ja tummaan tilaan.
  • Colors.white- tai Colors.black-värien käyttäminen suoraan — Ne eivät toimi oikein tummassa tilassa. Käytä niiden sijaan colorScheme.onSurface- tai colorScheme.surface-roolia.
  • useMaterial3: true -asetuksen unohtaminen — Ilman tätä lippua Flutter käyttää M2:n oletusarvoja, eivätkä M3:n väriroolit välttämättä vaikuta sisäänrakennettuihin widgeteihin oikein.
  • primaryColor-arvon käyttäminen ThemeDatasta — Se on M2:n käsite. M3:ssa kaikki widgetit lukevat värit colorScheme-arvosta. Aseta ThemeData.colorScheme, älä ThemeData.primaryColor.
  • Kirkkauden ja taustan yhteensopimattomuus — Jos luot Brightness.dark-värimallin ja yhdistät sen valkoiseen scaffoldiin, käyttöliittymän teksti voi muuttua lukukelvottomaksi.

Kaikki yhdessä: teemallinen sovellusrakenne

Tässä on täydellinen minimaalinen sovellusrakenne, joka havainnollistaa parhaita käytäntöjä: siemeneen perustuva värimalli, vaalean ja tumman tilan tuki, useMaterial3: true sekä widgetit, jotka lukevat roolit kontekstista — missään ei käytetä kiinteästi määritettyjä värejä.

import 'package:flutter/material.dart';

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

const Color _seed = Color(0xFF2E7D32); // forest green brand

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Green Theme',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: _seed,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: _seed,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      themeMode: ThemeMode.system,
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Scaffold(
      backgroundColor: cs.surface,
      appBar: AppBar(
        title: Text('Dashboard', style: TextStyle(color: cs.onPrimary)),
        backgroundColor: cs.primary,
      ),
      body: Center(
        child: FilledButton.icon(
          onPressed: () {},
          icon: const Icon(Icons.eco),
          label: const Text('Go Green'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        backgroundColor: cs.tertiary,
        foregroundColor: cs.onTertiary,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Pikatarkistus: ColorScheme.fromSeed

Testaa ymmärrystäsi siitä, miten ColorScheme.fromSeed toimii Material 3:ssa.

Oppitunnin yhteenveto: Material 3:n värimallit ja siemenvärit

Tässä ovat oppitunnin keskeiset asiat:

  • M3:n ColorScheme määrittää täydellisen joukon nimettyjä värirooleja (primary, surface, error, säilöt ja niiden on-vastineet), joita Flutter-widgetit käyttävät automaattisesti.
  • ColorScheme.fromSeed luo yli 25 roolia yhdestä brändiväristä Googlen HCT-algoritmin avulla ja takaa näin harmonian sekä saavutettavuuden.
  • Välitä brightness: Brightness.light tai Brightness.dark, jotta samasta siemenväristä luodaan sopiva vaalea tai tumma muunnelma — yhdistä tämä aina MaterialApp.darkTheme-arvoon täyden tumman tilan tuen saamiseksi.
  • Käytä rooleja widgeteissä lausekkeella Theme.of(context).colorScheme — älä koskaan määritä heksa-arvoja kiinteästi widgettien tiedostoissa.
  • Käytä säilörooleja (primaryContainer, onPrimaryContainer) käyttöliittymäkomponenttien taustoissa; ne luovat visuaalisen hierarkian ilman opasiteetin manuaalista säätämistä.
  • Ohita yksittäisiä rooleja .copyWith()-menetelmällä, kun tietyn brändivärin on oltava täsmälleen oikea.
  • Android 12:ssa ja uudemmissa dynamic_color-paketin tarjoama dynaaminen väri poimii järjestelmän siemenvärin; määritä aina varaväri muita alustoja varten.
  • Aseta useMaterial3: true aina ThemeData-arvolle, jotta sisäänrakennetut widgetit lukevat M3-värimallia oikein.
Aloita maksutta

Opi Dart tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
22
Oppitunnit
88

Usein kysytyt kysymykset

Onko oppitunti ”Material 3 -väriteemat ja siemenvärit” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Mobiilikehitys Flutterilla-oppimispolun 3 oppituntia, myös oppitunnin “Material 3 -väriteemat ja siemenvärit”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Material 3 -väriteemat ja siemenvärit”?

Luo harmonisia väriteemoja yhdestä siemenväristä ColorScheme.fromSeedin avulla. Harjoittelet Mobiilikehitys Flutterilla-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Mobiilikehitys Flutterilla-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Mobiilikehitys Flutterilla-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Material 3 -väriteemat ja siemenvärit”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Mobiilikehitys Flutterilla-oppitunnilla?

Kyllä. Jokainen Mobiilikehitys Flutterilla-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Material 3 -väriteemat ja siemenvärit
  2. Dynaaminen väri ja mukautuvat vaaleat/tummat teemat
  3. Mukautettu ThemeExtension brändin design-tokeneille
  4. Responsiivinen typografia ja komponenttien teemoitus
← Takaisin: Mobiilikehitys Flutterilla