Flutter for Windows Desktop: Getting Started

Learn how to set up a development environment and create a simple Flutter calculator app for Windows Desktop. By Karol Wrótniak.

4.7 (3) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Managing Window Size

The application window concept doesn’t exist natively in Flutter. You have to handle it separately for each platform. You can change the platform-specific files generated by Flutter in the windows folder, but it’s more convenient to operate from the Dart code. You can do that using the window_manager plugin. The plug-in takes care of executing OS-specific actions. It also supports desktop platforms other than Windows. Add the dependency:

fluter pub add window_manager

The calculator view should always be in portrait orientation (a vertically oriented rectangle). Moreover, you need reasonable minimum and maximum sizes so the layout doesn’t break. You can enforce those restrictions before calling runApp in the main.dart file:

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

import 'calculator_body.dart';

Future<void> main() async {
  //1
  WidgetsFlutterBinding.ensureInitialized();
  await windowManager.ensureInitialized();

  //2
  await windowManager.setMinimumSize(const Size(309, 600));
  await windowManager.setMaximumSize(const Size(618, 1200));
  await windowManager.setSize(const Size(309, 600));
  await windowManager.setAspectRatio(0.54);
  await windowManager.setMaximizable(false);
  await windowManager.setTitle('FCalc');

  //3
  runApp(const FCalcApp());
}

class FCalcApp extends StatelessWidget {
  const FCalcApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) =>
      MaterialApp(home: Scaffold(body: CalculatorBody()));
}

Here is what the code above does:

  1. Initializes the Flutter and window manager internals.
  2. Sets window properties such as a size, aspect ratio and title.
  3. Starts the app.

Remember that all the window_manager methods are asynchronous. So you have to add awaits to wait until they finish working.

Preventing Window Maximization

setMaximumSize is effective only when changing window size, but users can still maximize a window using a system menu bar. You have to disable maximization by calling setMaximizable(false).

Note that the window_manager supports maximization disabling only on Windows. If you want that on macOS or Linux you have to change the platform-specific files in the macos or linux folders. Note they are Swift and C++, not the Dart source files! But, platforms other than Windows are out of the scope of this article.

Integrating with System Clipboard

The calculator display isn’t a plain editable text field but a read-only text. Its business logic updates it in a customized way — + and – don’t appear, so the built-in system copy-paste features don’t work out of the box. The keystroke listener is already there, and only the business logic is missing. Now, add the ability to insert many digits at a time to the Calculator class inside calculator.dart file:

void replaceDigits(String? possibleDigits) {
  print(possibleDigits);
  if (possibleDigits != null && int.tryParse(possibleDigits) != null) {
    _wasDigitJustAppended = true;
    displayNotifier.value = possibleDigits;
  }
}

If pasted data isn’t an integer, nothing happens. Next, fill the missing actions in CalculatorBody._onKey inside calculator_body.dart file:

} else if (event.isCopy()) {
  Clipboard.setData(ClipboardData(text: _calculator.displayNotifier.value));
  return KeyEventResult.handled;
} else if (event.isPaste()) {
  Clipboard.getData(Clipboard.kTextPlain)
      .then((data) => _calculator.replaceDigits(data?.text));
  return KeyEventResult.handled;
}

Finally, press Alt+Enter to import the Clipboard service. Note that class is already in the Flutter standard library. That’s because mobile platforms also have the clipboard. Keep in mind the getData method is asynchronous so you need to process the result in then callback. You can’t use await here because the onKey method is synchronous.

Polishing the Project

The last part of the app is the AC button. Keystroke listener is already there. First, add an action to Calculator inside calculator.dart file:

void clear() {
  _pendingOperation = null;
  _operand = null;
  _wasDigitJustAppended = false;
  displayNotifier.value = '0';
}

Here we reset the state, the pending operation and digits to initial values. Next, bind the method in CalculatorBody._onKey inside calculator_body.dart file:

} else if (event.isClear()) {
  _calculator.clear();
  return KeyEventResult.handled;
} else if (event.character == '+') {

Finally, add the Tile to the GridView:

Tile('AC', (_) => _calculator.clear()),

That’s all. You have a working calculator desktop app written in Flutter! You can run the app using Shift+F10.

Where to Go From Here

You can download the complete starter and final projects using the Download Materials button at the top or bottom of this article.

If you want to work further on this project, you can add support for more desktop platforms (Linux and macOS). You can also extend the calculator business logic by adding more arithmetic operations or fractional numbers support.

For further reading about the Flutter Desktop, check these: