A ternary kifejezések, vagy magyarul három operandusú kifejezések az egyszerűbb feltételes kifejezéseknek kedvelt formái.
Egy korábbi bejegyzésben volt már arról szó, hogyan lehet megoldani képernyők feltételtől függő megjelenítését.
Ebben a praktikus példában ugyanez kerül bemutatásra, de most a ternary kifejezést használom erre.
Ez mondjuk a kiinduló állapot, ahol a StartScreen és a QuestionsScreen képernyőket váltogattuk:
import 'package:flutter/material.dart';
import 'package:flutter_quiz_app/start_screen.dart';
import 'package:flutter_quiz_app/questions_screen.dart';
class Quiz extends StatefulWidget {
const Quiz({super.key});
@override
State<Quiz> createState() {
return _QuizState();
}
}
class _QuizState extends State<Quiz> {
Widget? activeScreen;
@override
void initState() {
activeScreen = StartScreen(switchScreen);
super.initState();
}
void switchScreen() {
setState(
() {
activeScreen = const QuestionsScreen();
},
);
}
@override
Widget build(context) {
return MaterialApp(
home: Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(255, 78, 13, 151),
Color.fromARGB(255, 107, 15, 168)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: activeScreen,
),
),
);
}
}
Ternary használatával
Elsőként az initState()-re nem lesz szükség. És ahelyett, hogy magát az aktív képernyőt (ami egy widget) egy változóban tárolnánk, az egyes képernyőkhöz rendelhetünk valamilyen tetszőleges azonosítót. Akár számot, akár valami szöveget.
Természetesen ezt is el kell tárolni egy változóban, de most nem magát a widgetet tesszük változóba, hanem az azonosítót:
var activeScreen = 'start-screen';
A switchScreen metódusban pedig a setState-el a másik képernyő azonosítóját adjuk meg:
activeScreen = 'questions-screen';
A képernyő váltás logikája pedig így valósul meg:
child: activeScreen == 'start-screen'
? StartScreen(switchScreen)
: const QuestionsScreen(),
A teljesség igényével itt a végleges kód:
import 'package:flutter/material.dart';
import 'package:flutter_quiz_app/start_screen.dart';
import 'package:flutter_quiz_app/questions_screen.dart';
class Quiz extends StatefulWidget {
const Quiz({super.key});
@override
State<Quiz> createState() {
return _QuizState();
}
}
class _QuizState extends State<Quiz> {
var activeScreen = 'start-screen';
void switchScreen() {
setState(
() {
activeScreen = 'questions-screen';
},
);
}
@override
Widget build(context) {
return MaterialApp(
home: Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(255, 78, 13, 151),
Color.fromARGB(255, 107, 15, 168)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: activeScreen == 'start-screen'
? StartScreen(switchScreen)
: const QuestionsScreen(),
),
),
);
}
}
Rövidebb, mint az initState használatával. Ami persze nem azt jelenti, hogy az nem jó, de vannak esetek, amikor a ternary kifejezések használata praktikusabb.
Élve a maximalizussal azt mondhatjuk, hogy a ternary kifejezés használata ott a child-nál, ahol a kódban is látszik, nehezen olvashatóvá teszi a kódot.
build metódus módosítása
Megtehetjük, hogy átalakítjuk kicsit a Widget build metódusát, ami először akkor fut le, amikor a widget megjelenik a képernyőn, azaz bekerül a widget fába. Majd pedig akkor, amikor a setState meghívódik.
A build metódoson belül létrehozhatunk egy változót, ami csak a metódoson belül érhető el, tehát nem az egész osztályon belül.
Widget build(context) {
var screenWidget = StartScreen(switchScreen);
A változó a startScreen lett, ami kezdőértéket is kap. Persze a cél az, hogy mindig az legyen a változóban, amelyik képernyő az aktív. Itt használjuk a ternary kifejezést inkább:
final screenWidget = activeScreen == 'start-screen'
? StartScreen(switchScreen)
: const QuestionsScreen();
Sőt, akkor már final lett a változó típusa, mert ez csak akkor állítódik be, amikor a build metódus lefut. A screenWidget változót értelem szerűen itt használjuk:
child: screenWidget
if használata
És végül, ha az if feltételes utasítással akarnám megoldani, akkor így kellene:
Widget screenWidget = StartScreen(switchScreen);
if (activeScreen == 'questions-screen') {
screenWidget = const QuestionsScreen();
}