Skip to content

SliverAppBar snap broken animation #137901

@feduke-nukem

Description

@feduke-nukem

Is there an existing issue for this?

Steps to reproduce

  1. Add SliverAppBar pinned: true, floating: true, snap:true
  2. Add some any EditableText
  3. Scroll down so appbar isn't visible
  4. Tap into EditableText to get focus and keyboard appeared
  5. Get broken animation

Expected results

Normal animation

Actual results

Animation is freezing or glitching

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: NestedScrollViewExample(),
    );
  }
}

class NestedScrollViewExample extends StatefulWidget {
  const NestedScrollViewExample({super.key});

  @override
  State<NestedScrollViewExample> createState() =>
      _NestedScrollViewExampleState();
}

class _NestedScrollViewExampleState extends State<NestedScrollViewExample> {
  @override
  Widget build(BuildContext context) {
    final List<String> tabs = <String>['Tab 1', 'Tab 2'];
    return DefaultTabController(
      length: tabs.length,
      child: Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverOverlapAbsorber(
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                  surfaceTintColor: Colors.transparent,
                  leading: IconButton(
                    onPressed: () {},
                    icon: const Icon(Icons.close),
                  ),
                  title: const Text('Books'),
                  pinned: true,
                  snap: true,
                  floating: true,
                  expandedHeight: 180.0,
                  forceElevated: innerBoxIsScrolled,
                  bottom: PreferredSize(
                    preferredSize: const Size.fromHeight(128),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 16.0),
                          child: TextField(
                            decoration: InputDecoration(label: Text('Input')),
                          ),
                        ),
                        TabBar(
                          // These are the widgets to put in each tab in the tab bar.
                          tabs: tabs
                              .map((String name) => Tab(text: name))
                              .toList(),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            children: tabs.map((String name) {
              return SafeArea(
                top: false,
                bottom: false,
                child: Builder(
                  builder: (BuildContext context) {
                    return CustomScrollView(
                      keyboardDismissBehavior:
                          ScrollViewKeyboardDismissBehavior.onDrag,
                      key: PageStorageKey<String>(name),
                      slivers: <Widget>[
                        SliverOverlapInjector(
                          handle:
                              NestedScrollView.sliverOverlapAbsorberHandleFor(
                                  context),
                        ),
                        SliverPadding(
                          padding: const EdgeInsets.all(8.0),
                          sliver: SliverFixedExtentList(
                            itemExtent: 48.0,
                            delegate: SliverChildBuilderDelegate(
                              (BuildContext context, int index) {
                                return ListTile(
                                  title: Text('Item $index'),
                                );
                              },
                              childCount: 30,
                            ),
                          ),
                        ),
                      ],
                    );
                  },
                ),
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

After research I've found out that the reason for such behaviour is a few things:

  1. If EditableText is focused it will call _scheduleShowCaretOnScreen(withAnimation: true); that will cause animation start of a RenderSliverFloatingPersistentHeader (by calling showOnScreen with provided Duration of 200 milliseconds).
    image
  2. After first step EditableText will handle software keyboard appearance and will call _scheduleShowCaretOnScreen(withAnimation: false); causing insta call of showOnScreen again but now with Duration.zero which leads to broken animation
    image

I've tried to add dummy additional check and it fixes problem:

image

Without fix:

untitled.webm

With fix:

fixed.webm

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[!] Flutter (Channel master, 3.17.0-1.0.pre.33, on macOS 13.4 22F66 darwin-arm64, locale en-RU)
    ! Upstream repository https://github.com/feduke-nukem/flutter is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to https://github.com/feduke-nukem/flutter to dismiss this error.
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.84.0)
[✓] Connected device (4 available)
[✓] Network resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: animationAnimation APIsa: text inputEntering text in a text field or keyboard related problemsf: material designflutter/packages/flutter/material repository.f: scrollingViewports, list views, slivers, etc.found in release: 3.13Found to occur in 3.13found in release: 3.17Found to occur in 3.17frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework teamwaiting for PR to land (fixed)A fix is in flight

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions