0

我已经实现了NestedScrollView,这就是我的结果。

滚动前:

在此处输入图像描述

滚动后:

在此处输入图像描述

问题是:

  1. Before Scrolled 部分中,如何使默认Live Button值位于中间AppBar
  2. After Scrolled 部分中,当用户滚动到顶部时,Live Button会从中心(默认)移动到右侧(旁边Chat Button)。
  3. After Scrolled 部分中,当用户滚动到顶部时,不应该与,title重叠,而是应该在 的右边,应该在 的左边,应该在 的左边。Back ButtonLive ButtonChat Buttontitle prefixBack Buttontitle suffixLive ButtonLive ButtonChat Button

这是我的构建代码AppBar

Widget _customAppBar(EventEntity event) {
    return SliverAppBar(
      expandedHeight: 200 + _appBarHeight,
      floating: false,
      pinned: true,
      leading: _buildNavButton(), // Back Button (Left)
      actions: <Widget>[
        // Live Button (Right)
        event?.status != null &&
            event.status == EventStatus.LIVE
            ? Center(child: LiveLabel(),)
            : Container(),
        // Chat Button (Right)
        HelpButton(),
      ],
      flexibleSpace: FlexibleSpaceBar(
        centerTitle: true,
        title: Text(
          widget.event.name.trim(),
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 24,
          ),
          overflow: TextOverflow.ellipsis,
          maxLines: 1,
          textAlign: TextAlign.center,
        ),
        background: Hero(
          tag: '--${widget.visibilityFilter} __${widget.event.id}',
          child: DinoNetworkImage(
            imageUrl: widget.event.image,
            fit: BoxFit.contain,
          ),
        ),
      ),
    );
  }

这是build方法:

Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: SafeArea(
        top: true,
        bottom: false,
        child: Stack(
          fit: StackFit.expand,
          children: <Widget>[
            NestedScrollView(
              headerSliverBuilder: (BuildContext context,
                  bool innerBoxIsScrolled) {
                return <Widget>[
                  _customAppBar(widget.event),
                ];
              },
              body: SingleChildScrollView(
                ....
              ),
            ),
            ....
          ],
        ),
      ),
    );
  }

如何使我的代码发生这种情况?

4

1 回答 1

0

我通过使用ScrollControllerVisibility小部件解决了这个问题,这是我的代码:

// Init variable
ScrollController _controller = ScrollController();
var _showLiveButton = false;
var _hideLiveButton = true;
var _isScrolledDone = false;


// Function for handler scrolled
void _listener() {
    if (_controller.offset / 160 > 1) {
      setState(() {
        _showLiveButton = true;
        _hideLiveButton = false;
        _isScrolledDone = true;
      });
    } else {
      setState(() {
        _showLiveButton = false;
        _hideLiveButton = true;
        _isScrolledDone = false;
      });
    }
}

// Don't forget to init and dispose the controller
@override
  void initState() {
    super.initState();
    _controller.addListener(_listener);
  }

  @override
  void dispose() {
    _controller.removeListener(_listener);
    super.dispose();
  }

Widget _buildLiveButtonAfterScrolled(EventEntity event) {
    if (event?.status != null && event.status == EventStatus.LIVE) {
      return Center(
        child: Visibility(
          visible: _showLiveButton,
          child: LiveLabel(),
        ),
      );
    } else {
      return Container();
    }
  }

  Widget _buildDefaultLiveButton(EventEntity event) {
    if (event?.status != null && event.status == EventStatus.LIVE) {
      return Expanded(
        child: Padding(
          padding: EdgeInsets.only(
            left: MediaQuery.of(context).size.width / 8,
          ),
          child: Center(
            child: Visibility(
              visible: _hideLiveButton,
              child: LiveLabel(),
            ),
          ),
        ),
      );
    } else {
      return Container();
    }
  }

  Widget _buildTitleAppBar() {
    if (_isScrolledDone) {
      return Container(
        margin: EdgeInsets.only(
          left: MediaQuery.of(context).size.width / 7,
          right: MediaQuery.of(context).size.width / 3.3,
        ),
        child: Text(
          widget.event.name.trim(),
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 24,
          ),
          overflow: TextOverflow.ellipsis,
          maxLines: 1,
          textAlign: TextAlign.start,
        ),
      );
    } else {
      return Text(
        widget.event.name.trim(),
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 24,
        ),
        overflow: TextOverflow.ellipsis,
        maxLines: 1,
        textAlign: TextAlign.center,
      );
    }
  }

  Widget _customAppBar(EventEntity event) {
    return SliverAppBar(
      expandedHeight: 200 + _appBarHeight,
      floating: false,
      pinned: true,
      leading: _buildNavButton(),
      actions: <Widget>[
        _buildDefaultLiveButton(event),
        _buildLiveButtonAfterScrolled(event),
        HelpButton(),
      ],
      flexibleSpace: FlexibleSpaceBar(
        centerTitle: true,
        title: _buildTitleAppBar(),
        background: Hero(
          tag: '--${widget.visibilityFilter} __${widget.event.id}',
          child: DinoNetworkImage(
            imageUrl: widget.event.image,
            fit: BoxFit.contain,
          ),
        ),
      ),
    );
  }

Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: SafeArea(
        top: true,
        bottom: false,
        child: Stack(
          fit: StackFit.expand,
          children: <Widget>[
            NestedScrollView(
              controller: _controller, // <--- Don't forget to add it
              headerSliverBuilder: (BuildContext context,
                  bool innerBoxIsScrolled) {
                return <Widget>[
                  _customAppBar(widget.event),
                ];
              },
              body: SingleChildScrollView(
                ....
              ),
            ),
            ....
          ],
        ),
      ),
    );
  }

于 2020-06-14T11:07:59.000 回答