Flutter 在滚动 ListView 上显示和隐藏容器

Dol*_*rma 4 dart flutter flutter-layout

如何ContainerListView向下滚动时显示动画并在向上滚动时隐藏它。

我附上的视频并不是我想要的确切实现,只是为了给您一个想法。

在此处输入图片说明

示例视频

https://imgur.com/a/auEzJQk


编辑:

每次向下滚动时,我都需要显示Container,每次向上滚动时,我都想隐藏它。它不应该依赖于ListView.

Cop*_*oad 12

不确定我是否正确回答了您的问题,这是您要实现的目标吗?

截屏:

在此处输入图片说明


代码:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Height of your Container
  static final _containerHeight = 100.0;

  // You don't need to change any of these variables
  var _fromTop = -_containerHeight;
  var _controller = ScrollController();
  var _allowReverse = true, _allowForward = true;
  var _prevOffset = 0.0;
  var _prevForwardOffset = -_containerHeight;
  var _prevReverseOffset = 0.0;

  @override
  void initState() {
    super.initState();
    _controller.addListener(_listener);
  }

  // entire logic is inside this listener for ListView
  void _listener() {
    double offset = _controller.offset;
    var direction = _controller.position.userScrollDirection;

    if (direction == ScrollDirection.reverse) {
      _allowForward = true;
      if (_allowReverse) {
        _allowReverse = false;
        _prevOffset = offset;
        _prevForwardOffset = _fromTop;
      }

      var difference = offset - _prevOffset;
      _fromTop = _prevForwardOffset + difference;
      if (_fromTop > 0) _fromTop = 0;
    } else if (direction == ScrollDirection.forward) {
      _allowReverse = true;
      if (_allowForward) {
        _allowForward = false;
        _prevOffset = offset;
        _prevReverseOffset = _fromTop;
      }

      var difference = offset - _prevOffset;
      _fromTop = _prevReverseOffset + difference;
      if (_fromTop < -_containerHeight) _fromTop = -_containerHeight;
    }
    setState(() {}); // for simplicity I'm calling setState here, you can put bool values to only call setState when there is a genuine change in _fromTop
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("ListView")),
      body: Stack(
        children: <Widget>[
          _yourListView(),
          Positioned(
            top: _fromTop,
            left: 0,
            right: 0,
            child: _yourContainer(),
          )
        ],
      ),
    );
  }

  Widget _yourListView() {
    return ListView.builder(
      itemCount: 100,
      controller: _controller,
      itemBuilder: (_, index) => ListTile(title: Text("Item $index")),
    );
  }

  Widget _yourContainer() {
    return Opacity(
      opacity: 1 - (-_fromTop / _containerHeight),
      child: Container(
        height: _containerHeight,
        color: Colors.red,
        alignment: Alignment.center,
        child: Text("Your Container", style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white)),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 通常过于复杂 (2认同)

小智 11

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    const double HEIGHT = 96;
    final ValueNotifier<double> notifier = ValueNotifier(0);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: const Text('Test')),
        body: Stack(
          children: [
            NotificationListener<ScrollNotification>(
              onNotification: (n) {
                if (n.metrics.pixels <= HEIGHT) {
                  notifier.value = n.metrics.pixels;
                }
                return false;
              },
              child: ListView.builder(
                itemCount: 42,
                itemBuilder: (context, index) {
                  return Container(
                    height: 64,
                    padding: const EdgeInsets.all(16),
                    alignment: Alignment.centerLeft,
                    child: Text('Item $index'),
                  );
                },
              ),
            ),
            HideableWidget(height: HEIGHT, notifier: notifier),
          ],
        ),
      ),
    );
  }
}

class HideableWidget extends StatelessWidget {
  final double height;
  final ValueNotifier<double> notifier;

  HideableWidget({@required this.height, @required this.notifier});

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<double>(
      valueListenable: notifier,
      builder: (context, value, child) {
        return Transform.translate(
          offset: Offset(0, value - height),
          child: Container(
            height: 80,
            color: Colors.red,
          ),
        );
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明