Flutter SliverAppbar в заголовке NestedScrollView не растягивается и не масштабируется, как в CustomScrollView

SliverAppbar будет растягиваться и увеличиваться, если он находится в customScrollView, но не в NestedScrollView. Только тело NestedScrollView имеет BouncingScrollPhysics, как может заголовок NestedScrollView также иметь BouncingScrollPhysics, чтобы он мог растягивать и масштабировать SliverAppBar.

Однако, если я добавляю scrollController в тело / внутренний scrollView, тогда заголовок SliverAppBar растягивается, но затем они становятся двумя отдельными видами прокрутки, и заголовок не прокручивается вверх при прокрутке тела. Проверьте запись экрана

      @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 3,
        child: NestedScrollView(
          physics: BouncingScrollPhysics(),
          controller: mainScroller,
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverAppBar(
                stretch: true,
                pinned: true,
                floating: false,
                elevation: 0,
                onStretchTrigger: () {
                  print('stretch');
                  return;
                },
                title: isFlexibleSpaceVisible ? null : Text(widget.name),
                expandedHeight: containerHeight - kToolbarHeight,
                flexibleSpace: FlexibleSpaceBar(
                  stretchModes: <StretchMode>[
                    StretchMode.zoomBackground,
                    StretchMode.blurBackground,
                  ],
                  collapseMode: CollapseMode.pin,
                  background: Container(
                    color: Theme.of(context).canvasColor,
                    child: Stack(
                      children: <Widget>[
                        Container(
                          height: headerImageHeight,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            color: kBackgroundColor,
                            image: DecorationImage(
                              fit: BoxFit.cover,
                              colorFilter: ColorFilter.mode(
                                Colors.black54,
                                BlendMode.darken,
                              ),
                              image: NetworkImage(
                                  'https://picsum.photos/seed/${Random().nextInt(100)}/${MediaQuery.of(context).size.width.toInt()}'),
                            ),
                          ),
                        ),
                        Container(
                          height: headerSpace,
                          margin: EdgeInsets.only(
                              top: headerImageHeight - bringImageUpMargin),
                          padding: EdgeInsets.only(left: 8, right: 8),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              Container(
                                decoration: BoxDecoration(
                                    color: Theme.of(context).canvasColor,
                                    shape: BoxShape.circle),
                                padding: EdgeInsets.all(6),
                                child: CircleAvatar(
                                  backgroundColor: kCardColor,
                                  backgroundImage: NetworkImage(
                                      'https://picsum.photos/seed/${Random().nextInt(100)}/200'),
                                  radius: profileImageRadius,
                                ),
                              ),
                              Expanded(
                                child: Container(
                                  margin: EdgeInsets.symmetric(
                                      horizontal: 4, vertical: 12),
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.end,
                                    crossAxisAlignment:
                                        CrossAxisAlignment.stretch,
                                    children: <Widget>[
                                      Text(
                                        widget.name,
                                        style: TextStyle(
                                            fontSize: 16,
                                            fontWeight: FontWeight.w700),
                                      ),
                                      SizedBox(height: 2),
                                      Wrap(
                                        alignment: WrapAlignment.spaceBetween,
                                        children: <Widget>[
                                          Container(
                                            padding: EdgeInsets.symmetric(
                                                horizontal: 6, vertical: 2),
                                            decoration: BoxDecoration(
                                                color: kPrimaryColor,
                                                borderRadius:
                                                    BorderRadius.circular(4)),
                                            child: Text(
                                              widget.skill,
                                              style: TextStyle(
                                                  fontSize: 12,
                                                  color: Colors.white),
                                            ),
                                          ),
                                          Container(
                                            padding: EdgeInsets.symmetric(
                                                vertical: 2, horizontal: 6),
                                            decoration: BoxDecoration(
                                                color: kCardColor,
                                                borderRadius:
                                                    BorderRadius.circular(4)),
                                            child: Text(
                                              '\$${widget.rate} / ${widget.per}',
                                              style: TextStyle(
                                                  color: kPrimaryColor,
                                                  fontSize: 12),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ],
                                  ),
                                ),
                              )
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
              SliverToBoxAdapter(
                child: Container(
                  padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  child: Column(
                    children: <Widget>[
                      Row(
                        children: <Widget>[
                          Container(
                              width: 22,
                              height: 18,
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(4),
                                color: kSecondaryColor,
                              ),
                              child: Icon(
                                Icons.star,
                                color: Colors.white,
                                size: 14,
                              )),
                          SizedBox(
                            width: 6,
                          ),
                          Text('Do you recommend ${widget.name} ?'),
                        ],
                      ),
                      Row(
                        children: <Widget>[
                          Expanded(
                            child: OutlineButton(
                              highlightedBorderColor: kSecondaryColor,
                              color: kSecondaryColor,
                              borderSide: BorderSide(color: kSecondaryColor),
                              textColor: kSecondaryColor,
                              onPressed: () => null,
                              child: Text('NO'),
                            ),
                          ),
                          SizedBox(
                            width: 8,
                          ),
                          Expanded(
                            child: RaisedButton(
                              onPressed: () => null,
                              child: Text('YES'),
                            ),
                          ),
                        ],
                      )
                    ],
                  ),
                ),
              ),
              SliverPersistentHeader(
                pinned: true,
                delegate: SliverProfileTabs(),
              )
            ];
          },
          body: ProfileTabsView(data: widget),
        ),
      ),
    );
  }
}

person Hasan Ahmed    schedule 16.02.2020    source источник
comment
Физика отскока в настоящее время имеет связанную ошибку. У меня отключена физика отскока даже для iOS при использовании NestedScrollView и SliverAppBar. См. github.com/flutter/flutter/issues/29264#issuecomment-586074045   -  person Ted Henry    schedule 16.02.2020


Ответы (1)


Как упоминалось в комментарии, для этого есть открытая ошибка в GitHub.

Причина такого поведения обсуждалась в этой теме:

Причина, по которой растяжение не происходит, заключается в том, что _NestedScrollViewCoodinator в настоящее время отдает приоритет внутренней прокручиваемой прокрутке для любой прокрутки от перетаскивания пользователем. Я думаю, что мы можем добавить флаг, например NestedScrollView.stretchHeaderSlivers, который перевернет его, чтобы отправить перескрол во внешнюю прокручиваемую область. Эта часть должна быть легкой.

_NestedScrollViewCoordinator.createOuterBallisticScrollActivity необходимо будет отредактировать, так как в настоящее время предполагается, что внешняя прокрутка никогда не будет чрезмерной прокрутки, что может быть, а может и не быть таким простым.

И они упомянули, что это огромный рефакторинг и что нет подходящих решений пока нет:

Я пробовал это несколько раз и пока не нашел подходящего решения. NestedScrollView основывается на гораздо большем, чем я, на предположении, что внешний вид прокрутки никогда не будет прокручиваться слишком далеко. Я считаю, что для поддержки работы, которую мы сможем запланировать на новый год, потребуется более масштабный рефакторинг / переработка виджета. На данный момент я больше не буду активно над этим работать. Я пока не назначаю себя на случай, если кто-то еще захочет попытаться решить эту проблему тем временем. :)

Так как я не могу просмотреть запись вашего экрана, я просто опубликую примерное представление о том, как выглядит ошибка. Он был взят из ветки проблем GitHub.

Образец кода:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: 2,
        child: Scaffold(
          body: NestedScrollView(
              physics: BouncingScrollPhysics(),
              headerSliverBuilder: (context, innerScrolled) => <Widget>[
                    SliverOverlapAbsorber(
                      handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                          context),
                      sliver: SliverAppBar(
                          pinned: true,
                          stretch: true,
                          title: Text('username'),
                          expandedHeight: 325,
                          flexibleSpace: FlexibleSpaceBar(
                              stretchModes: <StretchMode>[
                                StretchMode.zoomBackground,
                                StretchMode.blurBackground,
                              ],
                              background: Image.network(
                                  'https://i.imgur.com/QCNbOAo.png',
                                  fit: BoxFit.cover)),
                          bottom: TabBar(
                              tabs: <Widget>[Text('test1'), Text('test2')])),
                    )
                  ],
              body: TabBarView(children: [
                Center(
                  child: Builder(
                    builder: (context) => CustomScrollView(
                      slivers: <Widget>[
                        SliverOverlapInjector(
                            handle:
                                NestedScrollView.sliverOverlapAbsorberHandleFor(
                                    context)),
                        SliverFixedExtentList(
                            delegate: SliverChildBuilderDelegate(
                                (_, index) => Text('not working'),
                                childCount: 100),
                            itemExtent: 25)
                      ],
                    ),
                  ),
                ),
                Center(child: Text('working'))
              ])),
        ));
  }
}

Выход:

введите описание изображения здесь

person MαπμQμαπkγVπ.0    schedule 23.03.2021