flutter/flutter

Overscrolling outer scrollview / SliverAppBar.stretch does not work in NestedScrollView

lalawila opened this issue · 23 comments

code sample
          DefaultTabController(
              length: 2,
              child: NestedScrollView(
                  physics: BouncingScrollPhysics(),
                  headerSliverBuilder: (context, innerScrolled) => <Widget>[
                    SliverOverlapAbsorber(
                      handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                      child: SliverAppBar(
                        pinned: true,
                        stretch: true, 
                        title: Text('username'),
                        expandedHeight: 325,
                        flexibleSpace: FlexibleSpaceBar(
                          stretchModes: <StretchMode>[
                            StretchMode.zoomBackground,
                            StretchMode.blurBackground,
                          ],
                          background: Image.asset('images/splash.png', fit: BoxFit.cover)
                        ),
                        bottom: 
                          TabBar(
                            tabs: <Widget>[
                              Text('test1'),
                              Text('test2')
                            ]
                          )
                      ),
                    )
                  ],
              body: TabBarView(
                  children: [
                    Builder( 
                      builder: (context) => CustomScrollView(
                          slivers: <Widget>[
                            SliverOverlapInjector(
                                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
                                SliverFixedExtentList(
                                    delegate: SliverChildBuilderDelegate(
                                        (_, index) => Text('not working'),
                                        childCount: 100),
                                    itemExtent: 25
                                  )
                          ],
                        ),
                    ),
                    Text('working')
                  ]
            )));

skiun-x5ux6

flutter doctor -v
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.15.1 19B88, locale en-CN)
    • Flutter version 1.12.13+hotfix.9 at /Users/lalawila/flutter
    • Framework revision f139b11009 (6 days ago), 2020-03-30 13:57:30 -0700
    • Engine revision af51afceb8
    • Dart version 2.7.2

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /Users/lalawila/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • Java binary at: /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home/bin/java
    • Java version Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
    ✗ Android license status unknown.
      Try re-installing or updating your Android SDK Manager.
      See https://developer.android.com/studio/#downloads or visit https://flutter.dev/setup/#android-setup for detailed instructions.

 
[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.2.1, Build version 11B53
    • CocoaPods version 1.8.0

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/setup/#android-setup for detailed instructions).

[✓] VS Code (version 1.43.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.9.0

[✓] Connected device (1 available)
    • iPhone 11 • 0BFEAC24-164A-4F59-B67D-EBDBF1A499D1 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-2 (simulator)

! Doctor found issues in 2 categories.

Issue also exist on

flutter doctor -v
[✓] Flutter (Channel dev, v1.18.0, on Mac OS X 10.15.4 19E266, locale en-GB)
    • Flutter version 1.18.0 at /Users/taha/Code/flutter_dev
    • Framework revision 14f3a36aba (2 days ago), 2020-04-03 17:06:01 -0700
    • Engine revision 09bc1fc45e
    • Dart version 2.8.0 (build 2.8.0-dev.20.0 e736495eb7)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at /Users/taha/Code/sdk
    • Platform android-29, build-tools 29.0.3
    • ANDROID_HOME = /Users/taha/Code/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_212-release-1586-b4-5784211)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.4, Build version 11E146
    • CocoaPods version 1.9.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 3.6)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 45.0.1
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build
      1.8.0_212-release-1586-b4-5784211)

[✓] VS Code (version 1.43.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.9.0

[✓] Connected device (4 available)
    • Taha’s iPhone • 00008020-001059882212002E • ios            • iOS 13.4
    • macOS         • macOS                     • darwin-x64     • Mac OS X
      10.15.4 19E266
    • Chrome        • chrome                    • web-javascript • Google Chrome
      80.0.3987.149
    • Web Server    • web-server                • web-javascript • Flutter Tools

• No issues found!

Thanks for filing this!

The reason the stretch does not happen is because the _NestedScrollViewCoodinator currently prioritizes the inner scrollable for any overscroll from the user drag. I am thinking we can add a flag like, NestedScrollView.stretchHeaderSlivers, which will flip that to send overscroll to the outer scrollable. That part should be easy.

The _NestedScrollViewCoordinator.createOuterBallisticScrollActivity will need to be refactored since it currently assumes that the outer scrollable will never overscroll, which may or may not be as easy.

I am moving the milestone once last time. I'm currently working on a related issue (#63978) that should help the fix for this follow in short order. That issue is actually a regression in the same area of the codebase that will need changing to resolve this, which is why it's higher priority. :)

@Piinks Thank you for your attention

I've taken a crack at this a few different times and have not found a suitable solution yet. The NestedScrollView bases much more than I though on the assumption that the outer scroll view will never overscroll. I believe this will take a larger refactoring/re-design of the widget in order to support, maybe work we can schedule for in the new year. For now, I won't be actively working on this anymore.
I am un-assigning myself for now in case some one else would like to try solving this in the meantime. :)

Preview

ezgif com-gif-maker

complete runnable code sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: 2,
        child: Scaffold(
          body: NestedScrollView(
              physics: BouncingScrollPhysics(),
              headerSliverBuilder: (context, innerScrolled) => <Widget>[
                    SliverOverlapAbsorber(
                      handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                          context),
                      sliver: SliverAppBar(
                          pinned: true,
                          stretch: true,
                          title: Text('username'),
                          expandedHeight: 325,
                          flexibleSpace: FlexibleSpaceBar(
                              stretchModes: <StretchMode>[
                                StretchMode.zoomBackground,
                                StretchMode.blurBackground,
                              ],
                              background: Image.network(
                                  'https://i.imgur.com/QCNbOAo.png',
                                  fit: BoxFit.cover)),
                          bottom: TabBar(
                              tabs: <Widget>[Text('test1'), Text('test2')])),
                    )
                  ],
              body: TabBarView(children: [
                Center(
                  child: Builder(
                    builder: (context) => CustomScrollView(
                      slivers: <Widget>[
                        SliverOverlapInjector(
                            handle:
                                NestedScrollView.sliverOverlapAbsorberHandleFor(
                                    context)),
                        SliverFixedExtentList(
                            delegate: SliverChildBuilderDelegate(
                                (_, index) => Text('not working'),
                                childCount: 100),
                            itemExtent: 25)
                      ],
                    ),
                  ),
                ),
                Center(child: Text('working'))
              ])),
        ));
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 1.22.6, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.22.6 at /Users/tahatesser/Code/flutter_stable
    • Framework revision 9b2d32b605 (12 days ago), 2021-01-22 14:36:39 -0800
    • Engine revision 2f0af37152
    • Dart version 2.10.5

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/SDK
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/SDK
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.4)
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.19.0

[!] Connected device
    ! No devices available

! Doctor found issues in 2 categories.
[✓] Flutter (Channel master, 1.26.0-18.0.pre.156, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.26.0-18.0.pre.156 at /Users/tahatesser/Code/flutter_master
    • Framework revision 45508985b1 (8 hours ago), 2021-02-02 22:46:04 -0500
    • Engine revision 2c144c3eeb
    • Dart version 2.12.0 (build 2.12.0-282.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/SDK
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/SDK
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.19.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 11.1 20C69 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 88.0.4324.96

• No issues found!

@TahaTesser is there a way that the body behaves like the FlexibleSpaceBar where it doesn't scroll away from the bottom of the AppBar?

Seem like this will not be solved in the the near future.
Why don't we do this:

we put the NestedScrollView in another NestedScrollView,
and user the outer NestedScrollView's header to provider the expand effect.

just a thought, maybe I'll try to implement it. tbd.

@TahaTesser When TabBarView children has child widget which is Started to SingleChildScrollView, zoombackground does not triggered. Why Scrollable widget in tab index, zoombackground is not triggered?

This is pain :(

Seem like this will not be solved in the the near future.
Why don't we do this:

we put the NestedScrollView in another NestedScrollView,
and user the outer NestedScrollView's header to provider the expand effect.

just a thought, maybe I'll try to implement it. tbd.

I have tried it without success, did you succeed?

Here is an issue I've opened today #82150

Please have a look at it. If only the SliverAppBar stretch works with NestedScrollView... Certainly, there are things to tweak and correct with NestedScrollView.

UPDATED

For anyone who needs a quick but imperfect hack badly, see this repo and apply the changes to your NestedScrollView file: https://github.com/himalaya-nuts/sliver_app_bar_stretch

Have a play at this demo web app (resize to phone screen size for best result): https://himalaya-nuts.github.io/sliver_app_bar_stretch

With the changes above, the SliverAppBar does stretch, and the effect is somewhat acceptable to me. But this is JUST a quick hack, optimal effect requires extensive refactoring. Some limitations apply:

  1. The body scroll view must have BouncingScrollPhysics, when the SliverAppBar background stretches, so bouces the body scroll view.
  2. SliverAppBar and body scroll physics does not connect seamlessly. As a result, the SliverAppBar won't stretch by carried momentum (when you quick fling down then not touching the screen), your fingertip has to be touching the screen when stretching the SliverAppBar.

@himalaya-nuts

Would you mind showing it with a video or GIF?

Thanks for notifying!

I will test it but I am not able to do that in a few days. So, it will be really good to see a video. (or even a live web demo)

@yasinarik I spent some time to wrap it up and updated my comment above, you can check the demo web app there. Cheers.

@himalaya-nuts Thanks a lot. I really appreciate it. You've spent quite a lot time.

Currently, I am working another part of an app and can't wait to get back to this part to try it out.

Any news about this issue?

I tried a workaround and it works good.
Just build a NotificationListener and get the body's overscroll extent, then you can change the SliverAppBar's expandHeight to yourExpandHeight + overscrollExtent, it will have a zoom stretch effect.(if you need other effect you can do them by yourself)
Now the body will still show the effect of overscroll, but this can be hide through Transform.translate, don't forget use a OverflowBox to make sure the body can be displayed correctly.
Maybe customize a scroll physics can avoid transform, but I don't think it neccesary

NestedScrollView(
            headerSliverBuilder: (context, innerBoxIsScrolled) => _buildHeader(
              context: context,
              innerBoxIsScrolled: innerBoxIsScrolled,
            ),
            body: NotificationListener(
              onNotification: (ScrollNotification notification) {
                if (notification.metrics.pixels < 0) {
                  _stretchExtent = -notification.metrics.pixels;
                }
                return false;
              },
              child: _buildBody(),
            ),
          ),
return LayoutBuilder(
      builder: (context, constraints) {
        return Transform.translate(
            offset: Offset(0, -_stretchExtent),
            child: OverflowBox(
              minHeight: constraints.maxHeight + _store.stretchExtent,
              maxHeight: constraints.maxHeight + _store.stretchExtent,
              alignment: Alignment.topCenter,
              child: TabBarView(
                controller: _tabController,
                children: [
                  xxx
                ],
              ),
            ),
          );
      },
    );

Update

@Piinks I'm sure I have solved this problem perfectly. :)

Fixed by:

  1. Override the applyUserOffset method of _NestedScrollCoordinator to allow over-scroll the top of _outerPosition.
  2. Override the unnestOffset, nestOffset, _getMetrics methods of _NestedScrollCoordinator to fix the mapping between _innerPosition and _outerPosition to _NestedScrollPosition.

Web demo 👉 Click Here

For more information, see: nested_scroll_view_plus

That's awesome @idootop! Would you be interested in submitting a PR? Or publishing it as a package?

That's awesome @idootop! Would you be interested in submitting a PR? Or publishing it as a package?

I've created a package for anyone who is in dire need of this new feature:

Pub

https://pub.dev/packages/nested_scroll_view_plus

💡 Usage

import 'package:nested_scroll_view_plus/nested_scroll_view_plus.dart';

// Step 1: Replace `NestedScrollView` with `NestedScrollViewPlus`
NestedScrollViewPlus(
  headerSliverBuilder: (context, innerScrolled) => <Widget>[
    // ... insert your header sliver widgets here
  ],
  body: CustomScrollView(
    // Step 2: [🚨IMPORTANT] Set the physics of `CustomScrollView` to `AlwaysScrollableScrollPhysics`
    physics: const BouncingScrollPhysics(
      parent: AlwaysScrollableScrollPhysics(),
    ),
    slivers: <Widget>[
      // ... insert your body sliver widgets here
    ],
  ),
);

Example usage:

  1. Replace NestedScrollView with NestedScrollViewPlus
  2. [🚨IMPORTANT] Set the physics of CustomScrollView to AlwaysScrollableScrollPhysics

That's it!

For additional examples, please visit the scroll_master repository. It includes features such as pull-to-refresh for NestedScrollView, combined scrolling for scrollview and tabview, and more.

⭕️ For Older Flutter Versions

If you are using an older version of Flutter, please follow these steps to install the appropriate branch from the old git repository.

dependencies:
  custom_nested_scroll_view:
    git:
      url: https://github.com/idootop/custom_nested_scroll_view.git
      # Choose the branch based on your local Flutter version
      ref: flutter-3.7

The different branches support the following Flutter versions:

Git branch Supported flutter versions
flutter-3.7 >=3.7.0-13.0.pre
flutter-3.4 >=3.4.0-27.0.pre <3.7.0-13.0.pre
flutter-3.4-pre >=3.4.0-17.0.pre <3.4.0-27.0.pre
flutter-3.0 >=2.12.0-4.0.pre <3.4.0-17.0.pre
flutter-2.x <2.12.0-4.0.pre

For more details, please visit the old documentation for CustomNestedScrollView.

@idootop fix sounds good. I'll try to manually create that fix to have control of code to be able to compare if flutter launches some official updates.

Reproducible on the latest master and stable channels.

Code Sample

import 'package:flutter/material.dart';

void main() => runApp(const AppBarApp());

class AppBarApp extends StatelessWidget {
  const AppBarApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
          colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
      home: SafeArea(
          child: DefaultTabController(
              length: 2,
              child: NestedScrollView(
                  physics: BouncingScrollPhysics(),
                  headerSliverBuilder: (context, innerScrolled) => <Widget>[
                        SliverOverlapAbsorber(
                          handle:
                              NestedScrollView.sliverOverlapAbsorberHandleFor(
                                  context),
                          sliver: SliverAppBar(
                              pinned: true,
                              stretch: true,
                              title: Text('username'),
                              expandedHeight: 325,
                              flexibleSpace: FlexibleSpaceBar(
                                  stretchModes: <StretchMode>[
                                    StretchMode.zoomBackground,
                                    StretchMode.blurBackground,
                                  ],
                                  background: Image.asset(
                                      'assets/images/img.jpg',
                                      fit: BoxFit.cover)),
                              bottom: TabBar(tabs: <Widget>[
                                Text('test1'),
                                Text('test2')
                              ])),
                        )
                      ],
                  body: Scaffold(
                    body: TabBarView(children: [
                      Builder(
                        builder: (context) => CustomScrollView(
                          slivers: <Widget>[
                            SliverOverlapInjector(
                                handle: NestedScrollView
                                    .sliverOverlapAbsorberHandleFor(context)),
                            SliverFixedExtentList(
                                delegate: SliverChildBuilderDelegate(
                                    (_, index) => Text('not working'),
                                    childCount: 100),
                                itemExtent: 25)
                          ],
                        ),
                      ),
                      Text('working')
                    ]),
                  )))),
    );
  }
}

Screen record

untitled.webm

stable, master flutter doctor -v

[!] Flutter (Channel stable, 3.16.9, on macOS 14.2.1 23C71 darwin-arm64, locale
    en-NG)
    • Flutter version 3.16.9 on channel stable at
      /Users/damilolaalimi/sdks/flutter
    ! Warning: `dart` on your path resolves to
      /opt/homebrew/Cellar/dart/3.1.5/libexec/bin/dart, which is not inside your
      current Flutter SDK checkout at /Users/damilolaalimi/sdks/flutter.
      Consider adding /Users/damilolaalimi/sdks/flutter/bin to the front of your
      path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 41456452f2 (3 weeks ago), 2024-01-25 10:06:23 -0800
    • Engine revision f40e976bed
    • Dart version 3.2.6
    • DevTools version 2.28.5
    • If those were intentional, you can disregard the above warnings; however
      it is recommended to use "git" directly to perform update checks and
      upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/damilolaalimi/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /Users/damilolaalimi/Library/Android/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      17.0.6+0-17.0.6b802.4-9586694)

[!] Android Studio (version unknown)
    • Android Studio at /Users/damilolaalimi/Downloads/Android Studio
      Preview.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    ✗ Unable to determine Android Studio version.
    • Java version OpenJDK Runtime Environment (build
      17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.86.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.78.0

[✓] VS Code (version 1.83.1)
    • VS Code at /Users/damilolaalimi/Downloads/Visual Studio Code.app/Contents
    • Flutter extension version 3.78.0

[✓] Connected device (5 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554                        •
      android-arm64  • Android 14 (API 34) (emulator)
    • Damilola’s iPhone (mobile)  • 00008110-001964480AE1801E            • ios
      • iOS 17.1.1 21B91
    • iPhone 15 Pro (mobile)      • 79E44FCE-BEA4-4C4B-9C1C-EFBD9964E172 • ios
      • com.apple.CoreSimulator.SimRuntime.iOS-17-2 (simulator)
    • macOS (desktop)             • macos                                •
      darwin-arm64   • macOS 14.2.1 23C71 darwin-arm64
    • Chrome (web)                • chrome                               •
      web-javascript • Google Chrome 121.0.6167.160

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 2 categories.
[!] Flutter (Channel master, 3.20.0-4.0.pre.62, on macOS 14.2.1 23C71 darwin-arm64, locale en-NG)
    • Flutter version 3.20.0-4.0.pre.62 on channel master at /Users/damilolaalimi/fvm/versions/master
    ! Warning: `dart` on your path resolves to /opt/homebrew/Cellar/dart/3.1.5/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/damilolaalimi/fvm/versions/master. Consider adding /Users/damilolaalimi/fvm/versions/master/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 950e0025c4 (4 hours ago), 2024-02-09 00:38:30 -0500
    • Engine revision f6dddb257a
    • Dart version 3.4.0 (build 3.4.0-116.0.dev)
    • DevTools version 2.32.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/damilolaalimi/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /Users/damilolaalimi/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[!] Android Studio (version unknown)
    • Android Studio at /Users/damilolaalimi/Downloads/Android Studio Preview.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    ✗ Unable to determine Android Studio version.
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.86.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.78.0

[✓] VS Code (version 1.83.1)
    • VS Code at /Users/damilolaalimi/Downloads/Visual Studio Code.app/Contents
    • Flutter extension version 3.78.0

[✓] Connected device (5 available)
    • sdk gphone64 arm64 (mobile)     • emulator-5554             • android-arm64  • Android 14 (API 34) (emulator)
    • Damilola’s iPhone (mobile)      • 00008110-001964480AE1801E • ios            • iOS 17.1.1 21B91
    • macOS (desktop)                 • macos                     • darwin-arm64   • macOS 14.2.1 23C71 darwin-arm64
    • Mac Designed for iPad (desktop) • mac-designed-for-ipad     • darwin         • macOS 14.2.1 23C71 darwin-arm64
    • Chrome (web)                    • chrome                    • web-javascript • Google Chrome 121.0.6167.160

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 2 categories.