Flutter 中的“过度滚动”嵌套 ListView

问题描述 投票:0回答:1

我有以下代码来演示我遇到的问题。我有一个嵌套的

ListView
,我希望当用户到达子项的末尾或开始时,子项的滚动“投降”到父项的滚动。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Scroll example',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: ListView(
            children: [
              for (int i = 0; i < 10; i++) ListItem(),
              SizedBox(
                height: 120,
                child: ListView(
                  shrinkWrap: true,
                  children: [
                    for (int i = 0; i < 10; i++) ListItem2(),
                  ],
                ),
              ),
              for (int i = 0; i < 10; i++) ListItem(),
            ],
          ),
        ));
  }
}

class ListItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('Item'),
      tileColor: Colors.blue,
    );
  }
}

class ListItem2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('Item',
          style: TextStyle(
            color: Colors.red,
          )),
    );
  }
}

我还录制了该问题的演示:https://www.youtube.com/watch?v=fmaR9rYMGd4

另外,这里有一个它按照我期望的方式在 Web 上的 Flutter 中工作的示例:

https://www.youtube.com/watch?v=cLxyPpb94M4

输出

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.4, on macOS 13.5 22G74 darwin-arm64, locale en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.88.1)
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!
flutter
1个回答
0
投票

您只需要使用 ScrollControllerNotificationListener 并使用一些 scrollExtentsoffsets

查看下面的代码。它会完成这项工作。希望这对您的用例有所帮助。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  ScrollController controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scroll example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: ListView(
          controller: controller,
          children: [
            for (int i = 0; i < 10; i++) ListItem(),
            Container(
              height: 120,
              child: NotificationListener<OverscrollNotification>(
                onNotification: (OverscrollNotification value) {
                  if (value.overscroll < 0 &&
                      controller.offset + value.overscroll <= 0) {
                    if (controller.offset != 0) controller.jumpTo(0);
                    return true;
                  }
                  if (controller.offset + value.overscroll >=
                      controller.position.maxScrollExtent) {
                    if (controller.offset !=
                        controller.position.maxScrollExtent) {
                      controller.jumpTo(controller.position.maxScrollExtent);
                    }
                    return true;
                  }
                  controller.jumpTo(controller.offset + value.overscroll);
                  return true;
                },
                child: ListView.builder(
                  itemBuilder: (c, ii) => ListItem2(),
                  itemCount: 20,
                ),
              ),
            ),
            for (int i = 0; i < 10; i++) ListItem(),
          ],
        ),
      ),
    );
  }
}

class ListItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('Item'),
      tileColor: Colors.blue,
    );
  }
}

class ListItem2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('Item',
          style: TextStyle(
            color: Colors.red,
          )),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.