Open In App

Flutter - Build Language Learning App

Last Updated : 20 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In this article, we will explore how to create a language-learning app using Flutter, a popular open-source UI software development toolkit developed by Google. Flutter enables developers to build natively compiled applications for mobile, web, and desktop platforms from a single codebase. This makes it an ideal choice for creating cross-platform language-learning applications. Below, you will find a sample video that provides an overview of what we will be covering in this article.


Steps Implement Language Learning Application

Step 1 : Create a new Flutter Application

Create a new Flutter application using the command Prompt. To create a new app, write the below command and run it.

flutter create app_name

To know more about it refer this article: Creating a Simple Application in Flutter


Step 2 : Adding the Dependency

To add the dependency to the pubspec.yaml file, add flip_card as a dependency in the dependencies part of the pubspec.yaml file, as shown below:

Dart
dependencies:
     flutter:
       sdk: flutter
     flip_card: ^0.6.0

Now run the below command in the terminal.

flutter pub get

Or

Run the below command in the terminal.

flutter pub add flip_card


Step 3 : Working With main.dart

Add the boilerplate code below in main.dart to create a basic structure with an AppBar and body using a Scaffold.

Dart
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';

// Main function to run the app.
void main() {
  runApp(const MyApp());
}

// The main app widget.
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Hide the debug banner.
      debugShowCheckedModeBanner: false,
      // App title.
      title: 'Learning App',
      // Set the app theme.
      theme: ThemeData(
          colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.green)),
      // Set the home page.
      home: const MyHomePage(title: 'Gfg French Learning App'),
    );
  }
}

// The home page widget.
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  // Title of the home page.
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// State class for the home page.
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Center the title in the app bar.
        centerTitle: true,
        // Set the app bar title.
        title: Text(widget.title),
        // BackgroundColor of Appbar
        backgroundColor: Colors.green,
        // foregroundColor of Appbar
        foregroundColor: Colors.white,
      ),
      body: SingleChildScrollView(
        // Code Here
      ),
    );
  }


Step 4 : Create FlashcardScreen Widget

The FlashCard widget requires a category to be selected when navigating from MyHomePage, allowing it to retrieve data from the data variable based on that category. The FlipCard widget is designed to display a word and its translation by flipping the card. When the "Next" button, which is an ElevatedButton, is clicked, it changes the word displayed on the card.

flashCard.dart:

Dart
// The flashcard screen widget.
class FlashcardScreen extends StatefulWidget {
  // Category of flashcards to display.
  final String category;
  const FlashcardScreen({required this.category});

  @override
  State<FlashcardScreen> createState() =>
      _FlashcardScreenState(category: category);
}

// State class for the flashcard screen.
class _FlashcardScreenState extends State<FlashcardScreen> {
  // Category of flashcards.
  final String category;
  _FlashcardScreenState({required this.category});
  // Current flashcard index.
  var _currItem = 0;
  // List to store flashcard data.
  late List<Map<String, String>> jsonData;
  // Key to control the flip card.
  GlobalKey<FlipCardState> cardKey = GlobalKey<FlipCardState>();

  // Style for the text on the flashcards.
  TextStyle textStyle = TextStyle(
      color: Colors.green.shade900, fontSize: 20, fontWeight: FontWeight.w600);
  // Data for the flashcards.
  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"}
        ]
  };

  @override
  void initState() {
    super.initState();
    // Load the flashcard data for the selected category.
    jsonData = (data[this.category] as List).cast<Map<String, String>>();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        // Set the background color.
        backgroundColor: const Color(0xffA7D397),
        appBar: AppBar(
          // Center the title in the app bar.
          centerTitle: true,
          // Set the app bar title.
          title: const Text("Learning Made Easy"),
          // Add a shadow to the app bar.
          elevation: 5,
        ),
        body: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
              // Instruction text.
              Text(
                "Guess the Word and Flip! ????",
                style: TextStyle(fontSize: 30, color: Colors.green.shade900),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              // Add some spacing.
              const SizedBox(height: 25),
              SizedBox(
                width: 300,
                height: 300,
                child: FlipCard(
                  // Key to control the flip card.
                  key: cardKey,
                  // Set the flip direction.
                  direction: FlipDirection.HORIZONTAL,
                  front: Card(
                    shape: RoundedRectangleBorder(
                        // Round the corners.
                        borderRadius: BorderRadius.circular(25)),
                    // Add a shadow to the card
                    elevation: 7,
                    // Set the shadow color.
                    shadowColor: Colors.grey,
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Center(
                        // Display the word.
                        child: Text(jsonData[_currItem]["word"] ?? "",
                            textAlign: TextAlign.center, style: textStyle),
                      ),
                    ),
                  ),
                  back: Card(
                    shape: RoundedRectangleBorder(
                        // Round the corners.
                        borderRadius: BorderRadius.circular(25)),
                    // Add a shadow to the card.
                    elevation: 7,
                    // Set the shadow color
                    shadowColor: Colors.grey,
                    // Set the card background color.
                    color: Colors.yellow.shade200,
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Center(
                        // Display the result.
                        child: Text(jsonData[_currItem]["result"] ?? "",
                            textAlign: TextAlign.center, style: textStyle),
                      ),
                    ),
                  ),
                ),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              ElevatedButton(
                  onPressed: () {
                    setState(() {
                      // Move to the next flashcard.
                      _currItem = (_currItem + 1) % jsonData.length;
                      // Flip the card back to the front.
                      cardKey.currentState?.toggleCard();
                    });
                  },
                  // Button to go to the next flashcard.
                  child: const Text("Next"))
            ])));
  }
}


Step 6 : Create a UI widget

Create a UI widget to showcase category cards wrapped in GestureDetector to navigate to the flashcard screen when tapped in MyHomePage Class.

Dart
 // Helper method to build a category card.
Widget _buildCard(String text) {
    return GestureDetector(
      onTap: () {
        // Navigate to the flashcard screen when the card is tapped.
        Navigator.of(context).push(MaterialPageRoute(
            builder: (context) => FlashcardScreen(category: text),
        ));
      },
      child: Container(
        height: 200,
        width: 200,
        decoration: BoxDecoration(
                // Set the card background color.
                color: const Color(0xffA7D397),
                // Round the corners.
                borderRadius: BorderRadius.all(Radius.circular(20))
            ),
        child: Center(
          child: Text(
                // Display the category name.
                text,
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
          ),
        ),
      ),
    );
}


Step 7 : Develop UI

- GridView.count() : Display a grid of category cards.

Dart
 GridView.count(
      // Number of columns in the grid.
      crossAxisCount: 2,
      // Aspect ratio of the grid items.
      childAspectRatio: 1.0,
      // Spacing between rows.
      mainAxisSpacing: 10.0,
      // Spacing between columns.
      crossAxisSpacing: 10.0,
      // Padding around the grid.
      padding: const EdgeInsets.all(10.0),
      children: <Widget>[
            // Build a card for "Basics".
            _buildCard("Basics"),
            // Build a card for "Food".
            _buildCard("Food"),
            // Build a card for "Travel".
            _buildCard("Travel"),
            // Build a card for "School".
            _buildCard("School"),
      ],
),


- Column: Wrap the GridView inside a Column and display the text "What do you want to learn today? ?????" at the top.

Dart
Column(
    children: [
      // Add some spacing.
      const SizedBox(height: 20),
      // Welcome message.
      Text(
        "What you want to learn today? ????‍????",
        style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            // Style for the text.
            color: Colors.green),
      ),
      // Add some spacing.
      const SizedBox(height: 20),
      Container(
        // Set the container height.
        height: MediaQuery.of(context).size.height,
        // Set the container width.
        width: MediaQuery.of(context).size.width,
        child: GridView.count(
          // Number of columns in the grid.
          crossAxisCount: 2,
          // Aspect ratio of the grid items.
          childAspectRatio: 1.0,
          // Spacing between rows.
          mainAxisSpacing: 10.0,
          // Spacing between columns.
          crossAxisSpacing: 10.0,
          // Padding around the grid.
          padding: const EdgeInsets.all(10.0),
          children: <Widget>[
            // Build a card for "Basics".
            _buildCard("Basics"),
            // Build a card for "Food".
            _buildCard("Food"),
            // Build a card for "Travel".
            _buildCard("Travel"),
            // Build a card for "School".
            _buildCard("School"),
          ],
        ),
      ),
    ],
),


Then implement the above UI code in main.dart.

main.dart:

Dart
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';

// Main function to run the app.
void main() {
  runApp(const MyApp());
}

// The main app widget.
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Hide the debug banner.
      debugShowCheckedModeBanner: false,
      // App title.
      title: 'Learning App',
      // Set the app theme.
      theme: ThemeData(
          colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.green)),
      // Set the home page.
      home: const MyHomePage(title: 'Gfg French Learning App'),
    );
  }
}

// The home page widget.
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  // Title of the home page.
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// State class for the home page.
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Center the title in the app bar.
        centerTitle: true,
        // Set the app bar title.
        title: Text(widget.title),
        // BackgroundColor of Appbar
        backgroundColor: Colors.green,
        // foregroundColor of Appbar
        foregroundColor: Colors.white,
      ),
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            children: [
              // Add some spacing.
              const SizedBox(height: 20),
              // Welcome message.
              Text(
                "What you want to learn today? ????‍????",
                style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    // Style for the text.
                    color: Colors.green),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              Container(
                // Set the container height.
                height: MediaQuery.of(context).size.height,
                // Set the container width.
                width: MediaQuery.of(context).size.width,
                child: GridView.count(
                  // Number of columns in the grid.
                  crossAxisCount: 2,
                  // Aspect ratio of the grid items.
                  childAspectRatio: 1.0,
                  // Spacing between rows.
                  mainAxisSpacing: 10.0,
                  // Spacing between columns.
                  crossAxisSpacing: 10.0,
                  // Padding around the grid.
                  padding: const EdgeInsets.all(10.0),
                  children: <Widget>[
                    // Build a card for "Basics".
                    _buildCard("Basics"),
                    // Build a card for "Food".
                    _buildCard("Food"),
                    // Build a card for "Travel".
                    _buildCard("Travel"),
                    // Build a card for "School".
                    _buildCard("School"),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  // Helper method to build a category card.
  Widget _buildCard(String text) {
    return GestureDetector(
      onTap: () {
        // Navigate to the flashcard screen when the card is tapped.
        Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => FlashcardScreen(category: text),
        ));
      },
      child: Container(
        height: 200,
        width: 200,
        decoration: BoxDecoration(
            // Set the card background color.
            color: const Color(0xffA7D397),
            // Round the corners.
            borderRadius: BorderRadius.all(Radius.circular(20))),
        child: Center(
          child: Text(
            // Display the category name.
            text,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 24,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}


Complete Source code

Note : We can use all above code in main.dart only.

main.dart:

Dart
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';

// Main function to run the app.
void main() {
  runApp(const MyApp());
}

// The main app widget.
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // Hide the debug banner.
      debugShowCheckedModeBanner: false,
      // App title.
      title: 'Learning App',
      // Set the app theme.
      theme: ThemeData(
          colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.green)),
      // Set the home page.
      home: const MyHomePage(title: 'Gfg French Learning App'),
    );
  }
}

// The home page widget.
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  // Title of the home page.
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// State class for the home page.
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Center the title in the app bar.
        centerTitle: true,
        // Set the app bar title.
        title: Text(widget.title),
        // BackgroundColor of Appbar
        backgroundColor: Colors.green,
        // foregroundColor of Appbar
        foregroundColor: Colors.white,
      ),
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            children: [
              // Add some spacing.
              const SizedBox(height: 20),
              // Welcome message.
              Text(
                "What you want to learn today? ????‍????",
                style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    // Style for the text.
                    color: Colors.green),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              Container(
                // Set the container height.
                height: MediaQuery.of(context).size.height,
                // Set the container width.
                width: MediaQuery.of(context).size.width,
                child: GridView.count(
                  // Number of columns in the grid.
                  crossAxisCount: 2,
                  // Aspect ratio of the grid items.
                  childAspectRatio: 1.0,
                  // Spacing between rows.
                  mainAxisSpacing: 10.0,
                  // Spacing between columns.
                  crossAxisSpacing: 10.0,
                  // Padding around the grid.
                  padding: const EdgeInsets.all(10.0),
                  children: <Widget>[
                    // Build a card for "Basics".
                    _buildCard("Basics"),
                    // Build a card for "Food".
                    _buildCard("Food"),
                    // Build a card for "Travel".
                    _buildCard("Travel"),
                    // Build a card for "School".
                    _buildCard("School"),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  // Helper method to build a category card.
  Widget _buildCard(String text) {
    return GestureDetector(
      onTap: () {
        // Navigate to the flashcard screen when the card is tapped.
        Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => FlashcardScreen(category: text),
        ));
      },
      child: Container(
        height: 200,
        width: 200,
        decoration: BoxDecoration(
            // Set the card background color.
            color: const Color(0xffA7D397),
            // Round the corners.
            borderRadius: BorderRadius.all(Radius.circular(20))),
        child: Center(
          child: Text(
            // Display the category name.
            text,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 24,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}

// The flashcard screen widget.
class FlashcardScreen extends StatefulWidget {
  // Category of flashcards to display.
  final String category;
  const FlashcardScreen({required this.category});

  @override
  State<FlashcardScreen> createState() =>
      _FlashcardScreenState(category: category);
}

// State class for the flashcard screen.
class _FlashcardScreenState extends State<FlashcardScreen> {
  // Category of flashcards.
  final String category;
  _FlashcardScreenState({required this.category});
  // Current flashcard index.
  var _currItem = 0;
  // List to store flashcard data.
  late List<Map<String, String>> jsonData;
  // Key to control the flip card.
  GlobalKey<FlipCardState> cardKey = GlobalKey<FlipCardState>();

  // Style for the text on the flashcards.
  TextStyle textStyle = TextStyle(
      color: Colors.green.shade900, fontSize: 20, fontWeight: FontWeight.w600);
// Data for the flashcards.
  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"}
    ]
  };

  @override
  void initState() {
    super.initState();
    // Load the flashcard data for the selected category.
    jsonData = (data[this.category] as List).cast<Map<String, String>>();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        // Set the background color.
        backgroundColor: const Color(0xffA7D397),
        appBar: AppBar(
          // Center the title in the app bar.
          centerTitle: true,
          // Set the app bar title.
          title: const Text("Learning Made Easy"),
          // Add a shadow to the app bar.
          elevation: 5,
        ),
        body: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
              // Instruction text.
              Text(
                "Guess the Word and Flip! ????",
                style: TextStyle(fontSize: 30, color: Colors.green.shade900),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              // Add some spacing.
              const SizedBox(height: 25),
              SizedBox(
                width: 300,
                height: 300,
                child: FlipCard(
                  // Key to control the flip card.
                  key: cardKey,
                  // Set the flip direction.
                  direction: FlipDirection.HORIZONTAL,
                  front: Card(
                    shape: RoundedRectangleBorder(
                        // Round the corners.
                        borderRadius: BorderRadius.circular(25)),
                    // Add a shadow to the card
                    elevation: 7,
                    // Set the shadow color.
                    shadowColor: Colors.grey,
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Center(
                        // Display the word.
                        child: Text(jsonData[_currItem]["word"] ?? "",
                            textAlign: TextAlign.center, style: textStyle),
                      ),
                    ),
                  ),
                  back: Card(
                    shape: RoundedRectangleBorder(
                        // Round the corners.
                        borderRadius: BorderRadius.circular(25)),
                    // Add a shadow to the card.
                    elevation: 7,
                    // Set the shadow color
                    shadowColor: Colors.grey,
                    // Set the card background color.
                    color: Colors.yellow.shade200,
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Center(
                        // Display the result.
                        child: Text(jsonData[_currItem]["result"] ?? "",
                            textAlign: TextAlign.center, style: textStyle),
                      ),
                    ),
                  ),
                ),
              ),
              // Add some spacing.
              const SizedBox(height: 20),
              ElevatedButton(
                  onPressed: () {
                    setState(() {
                      // Move to the next flashcard.
                      _currItem = (_currItem + 1) % jsonData.length;
                      // Flip the card back to the front.
                      cardKey.currentState?.toggleCard();
                    });
                  },
                  // Button to go to the next flashcard.
                  child: const Text("Next"))
            ])));
  }
}


Step 8 : Test Your App

Run your app using the following command:

flutter run

Output:



Next Article

Similar Reads