Skip to content

khlebobul/dynamic_island_pet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dynamic Island Pet Flutter app

Codacy Badge License: MIT

Example of interaction with Dynamic Island in a Flutter application

demo.mp4

I really like it when developers and designers add little details to an app. It shows that they really care about their user. In this article, I will discuss how to make your app a little cuter for the user with Dynamic Island and a little pet.

It has long been an axiom of mine that the little things are infinitely the most important.
Sir Arthur Conan Doyle, The Memoirs of Sherlock Holmes

About this project: How to work with Dynamic Island in the Flutter application

To see the work in action, download Knight's Graph ♞:

Usage

Scaffold(
      backgroundColor: Colors.white,
      body: Stack(
        children: [
          if (_hasDynamicIsland && _isInForeground)
            DynamicIsland(
              animationDuration: const Duration(milliseconds: 2000),
              startOffset: -1.0,
              endOffset: 1.0,
              reverse: false,
              child: Image.asset(
                'assets/dash.png',
                height: 15,
                width: 15,
              ),
            ),
        ],
      ),
    );

Define the model

final dynamicIslandModels = [
          'iPhone15,2', // iPhone 14 Pro
          'iPhone15,3', // iPhone 14 Pro Max
          'iPhone15,4', // iPhone 15
          'iPhone15,5', // iPhone 15 Plus
          'iPhone16,1', // iPhone 15 Pro
          'iPhone16,2', // iPhone 15 Pro Max
          'iPhone17,1', // iPhone 16 Pro
          'iPhone17,2', // iPhone 16 Pro Max
          'iPhone17,3', // iPhone 16
          'iPhone17,4', // iPhone 16 Plus
        ];

It is better to use a separate padding for each model

final deviceModel = await DeviceInfo.getDeviceModel();
    return switch (deviceModel) {
      // iPhone 14 ❌
      // iPhone 14 Plus ❌
      'iPhone15,2' => 13.0, // iPhone 14 Pro ✅
      'iPhone15,3' => 13.0, // iPhone 14 Pro Max ✅
      'iPhone15,4' => 13.0, // iPhone 15 ✅
      'iPhone15,5' => 13.0, // iPhone 15 Plus ✅
      'iPhone16,1' => 13.0, // iPhone 15 Pro ✅
      'iPhone16,2' => 13.0, // iPhone 15 Pro Max ✅
      'iPhone17,1' => 16.5, // iPhone 16 Pro ✅
      'iPhone17,2' => 16.0, // iPhone 16 Pro Max ✅
      'iPhone17,3' => 13.0, // iPhone 16 ✅
      'iPhone17,4' => 13.0, // iPhone 16 Plus ✅
      _ => 13.0,
    };

Display conditions

bool _hasDynamicIsland = false; // check if the device has a dynamic island
bool _isInForeground = true; // check if the app is in the foreground

void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this); // add the observer
    _checkForDynamicIsland(); // check if the device has a dynamic island
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this); // remove the observer
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    setState(() {
        // check if the app is in the foreground
      _isInForeground = state == AppLifecycleState.resumed;
    });
  }

  Future<void> _checkForDynamicIsland() async {
    final hasDynamicIsland = await DeviceInfo.hasDynamicIsland();
    setState(() {
      _hasDynamicIsland = hasDynamicIsland;
    });
  }