kouroku
kouroku

Reputation: 31

When using BackdropFilter in ListView, BackdropFilter is disabled at the timing of the stretching overscroll effect

In Android's Material3 environment, the ListView's ScrollBehavior is by default the StretchingOverscrollIndicator.

Therefore, when using a blur Container(Like Neumorphism / Glassmorphism design) with BackdropFilter as a ListView item, I have noticed that the blur disappears when over scrolling in Android environment.

The following is a code that can reproduce issue.

Stack(
  children: [
    Text('a' * 10000),
    ListView.separated(
      itemCount: 2,
      itemBuilder: (context, index) => ClipRect(
        child: BackdropFilter(
          filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
          child: Container(
            height: 100,
            color: Colors.transparent,
          ),
        ),
      ),
      separatorBuilder: (context, index) => const Divider(),
    ),
  ],
)

Full code(main.dart)

*Reproducible issue in outside of the Android environment.

import 'dart:ui';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true,
      ),
      /* For non-Android devices, the same phenomenon can be observed by activating the code below. */
      // builder: (context, child) => ScrollConfiguration(
      //   behavior: const ScrollBehaviorModified(),
      //   child: child!,
      // ),
      home: const MyHomePage(),
    );
  }
}

class ScrollBehaviorModified extends ScrollBehavior {
  const ScrollBehaviorModified();

  @override
  Widget buildOverscrollIndicator(
      BuildContext context, Widget child, ScrollableDetails details) {
    return StretchingOverscrollIndicator(
      axisDirection: details.direction,
      clipBehavior: Clip.hardEdge,
      child: child,
    );
  }

  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        PointerDeviceKind.trackpad,
      };
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Stack(
        children: [
          Text('a' * 10000),
          ListView.separated(
            itemCount: 2,
            itemBuilder: (context, index) => ClipRect(
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
                child: Container(
                  height: 100,
                  color: Colors.transparent,
                ),
              ),
            ),
            separatorBuilder: (context, index) => const Divider(),
          ),
        ],
      ),
    );
  }
}

Since the blur disappears not only in the ListView, but also at the timing of the screen transition animation, I think the problem is related to shaders.

Is there a workaround for this issue?

I am looking for a solution other than disabling the ListView's StretchingOverscrollIndicator if possible. (This is because the issue of blur disappearing also occurs in animations during screen transitions.)


Added

I found the same Issue in the Flutter project on GitHub.

https://github.com/flutter/flutter/issues/138940

It works fine in Flutter 3.13 and seems to cause problems in Flutter 3.16 and later.

So, as a temporary solution, I will use Flutter 3.13 and wait for the above Issue on GitHub to be resolved.

Upvotes: 3

Views: 317

Answers (0)

Related Questions