In this article, we will explore the creation of a language-learning app using Flutter. It is a popular open-source UI software development toolkit created by Google. Flutter allows developers to build natively compiled applications for mobile, web, and desktop from a single codebase, making it an ideal choice for creating cross-platform language learning apps. A sample video is given below to get an idea about what we are going to do in this article.
Step-by-Step Implementation
Step 1: Project Setup
Start by creating a new Flutter project using the following command in the terminal or command prompt:
flutter create language_learning_app
Step 2: Add dependencies
In pubspec.yaml file, add flip_card as dependency in dependencies section, and press Ctrl + S, in order to install it and use in the project.
Step 3: Create MyApp Widget
Create the MyApp widget, which is the root of our application.
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(
debugShowCheckedModeBanner: false ,
title: 'Learning App' ,
theme: ThemeData(
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.green)),
home: const MyHomePage(title: 'Gfg French Learning App' ),
);
}
} |
Step 4: Create FlashcardScreen Widget
FlashCard widget requires category when navigating from MyHomePage to get data from data.dart based on selected category. The FlipCard widget is used to show word and its translation by flipping the card. The ElevatedButton with the label “Next” changes the word on the card when clicked.
import 'package:flip_card/flip_card.dart' ;
import 'package:flutter/material.dart' ;
import 'package:today_app/data.dart' ;
class FlashcardScreen extends StatefulWidget {
final String category;
const FlashcardScreen({required this .category});
@override
State<FlashcardScreen> createState() =>
_FlashcardScreenState(category: category);
} class _FlashcardScreenState extends State<FlashcardScreen> {
final String category;
_FlashcardScreenState({required this .category});
var _currItem = 0;
late List<Map<String, String>> jsonData;
GlobalKey<FlipCardState> cardKey = GlobalKey<FlipCardState>();
TextStyle textStyle = TextStyle(
color: Colors.green.shade900, fontSize: 20, fontWeight: FontWeight.w600);
@override
void initState() {
super.initState();
jsonData = (data[ this .category] as List).cast<Map<String, String>>();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xffA7D397),
appBar: AppBar(
centerTitle: true ,
title: Text( "Learning Made Easy" ),
elevation: 5,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Guess the Word and Flip! ????" ,
style: TextStyle(fontSize: 30, color: Colors.green.shade900),
),
SizedBox(height: 20),
SizedBox(height: 25),
SizedBox(
width: 300,
height: 300,
child: FlipCard(
key: cardKey,
side: CardSide.FRONT,
direction: FlipDirection.HORIZONTAL,
front: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25)),
elevation: 7,
shadowColor: Colors.grey,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Text(jsonData[_currItem][ "word" ] ?? "" ,
textAlign: TextAlign.center, style: textStyle),
),
),
),
back: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25)),
elevation: 7,
shadowColor: Colors.grey,
color: Colors.yellow.shade200,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Text(jsonData[_currItem][ "result" ] ?? "" ,
textAlign: TextAlign.center, style: textStyle),
),
),
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
setState(() {
_currItem = (_currItem + 1) % jsonData.length;
cardKey.currentState?.toggleCardWithoutAnimation();
});
},
child: Text( "Next" ))
])));
}
} |
In this code, we have created a small json data and assigned it to variable data to be used in FlashcardScreen widget to show words and their corresponding french word.
var data = { "Food" : [
{ "word" : "Tea" , "result" : "Thé" },
{ "word" : "rice" , "result" : "riz" },
],
"Basics" : [
{ "word" : "Bonjour" , "result" : "Hello" },
{ "word" : "Bye" , "result" : "Au revoir" },
],
"Travel" : [
{ "word" : "Hostel" , "result" : "Auberge" },
{ "word" : "Journey" , "result" : "Voyage" },
],
"School" : [
{ "word" : "Teacher" , "result" : "Professeure/Professeur" },
{ "word" : "classmate" , "result" : "camarade de classe" }
]
}; |
Step 5: Create MyHomePage Widget
In MyHomePage widget, there are four categories displayed using GridView. In _buildCard, GestureDetector is used to handle click event when any of the container is clicked, and navigates to FlashCard screen.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this .title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
} class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true ,
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Center(
child: Column(
children: [
SizedBox(height: 20),
Text(
"What you want to learn today? ????????" ,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.green),
),
SizedBox(height: 20),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: 1.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
padding: EdgeInsets.all(10.0),
children: <Widget>[
_buildCard( "Basics" ),
_buildCard( "Food" ),
_buildCard( "Travel" ),
_buildCard( "School" ),
],
),
),
],
),
),
),
);
}
Widget _buildCard(String text) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => FlashcardScreen(category: text),
));
},
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Color(0xffA7D397),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Center(
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
} |
Step 6: Test Your App
Run your app using the following command:
flutter run