Skip to content

Instantly share code, notes, and snippets.

@Aaron009
Last active December 27, 2019 12:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aaron009/2df9288d77b219a9afa718d306a39862 to your computer and use it in GitHub Desktop.
Save Aaron009/2df9288d77b219a9afa718d306a39862 to your computer and use it in GitHub Desktop.
When I scroll to the second page, the tab does not switch automatically? When I click on the tab item, the page view below does not switch automatically? Why?
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(body: TestNestedScroll()),
);
}
}
class TestNestedScroll extends StatefulWidget {
@override
_TestNestedScrollState createState() => _TestNestedScrollState();
}
class _TestNestedScrollState extends State<TestNestedScroll>
with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return getTop();
// return getNestedScroll();
}
Widget getTop() {
List<Widget> expandedList = [];
for (var i = 0; i < 100; ++i) {
expandedList.add(Text('Expanded Text xxxxxxxxxx'));
}
return DefaultTextStyle(
style: TextStyle(fontSize: 30, color: Colors.blue),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: MediaQuery.of(context).padding.top, // Status bar color
color: Colors.grey,
),
Text('this is Text'),
Flexible(
child:SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: expandedList,
),
)
),
],
),
);
}
Widget getNestedScroll() {
XCTabBar tabBar = createTabBar(
viewList: [
Center(child: Text('page view1')),
Center(child: Text('page view2')),
Center(child: Text('page view3')),
],
provider: this,
tabStrings: 'tab item1,tab item2,tab item3',
);
return NestedScrollView(
body: tabBar.getTabView(),
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: getTop(),
),
SliverPersistentHeader(
floating: true,
pinned: true,
delegate: _SliverAppBarDelegate(
maxHeight: 44.0,
minHeight: 44.0,
child: Container(
color: Colors.white,
child: tabBar,
)
),
),
];
},
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max((minHeight ?? kToolbarHeight), minExtent);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return child;
}
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
// return maxHeight != oldDelegate.maxHeight ||
// minHeight != oldDelegate.minHeight ||
// child != oldDelegate.child;
return true;
}
}
//----------------------------------------------------------------------------------------------------------------------------
XCTabBar createTabBar({@required List<Widget> viewList, @required TickerProvider provider, List<Widget> tabList, String tabStrings}) {
if(tabList == null && tabStrings != null) {
tabList = tabStrings.split(',').map((item) {
return Text(
'$item',
style: TextStyle(fontSize: 15),
);
}).toList();
}
return XCTabBar(viewList, tabList, TabController(vsync: provider, length: tabList.length));
}
class XCTabBar extends StatefulWidget {
final TabController tabController;
final List<Widget> viewList;
final List<Widget> tabList;
XCTabBar(this.viewList, this.tabList, this.tabController) {
print('XCTabBar Constructor');
}
@override
State<StatefulWidget> createState() {
print('XCTabBar createState');
return XCTabBarState();
}
TabBarView getTabView() {
return TabBarView(
children: viewList,
controller: tabController,
);
}
}
class XCTabBarState extends State<XCTabBar> with SingleTickerProviderStateMixin {
Color selectColor, unselectedColor;
TextStyle selectStyle, unselectedStyle;
List<Widget> _tabList;
TabController _tabController;
@override
void initState() {
super.initState();
_tabList = widget.tabList;
_tabController = widget.tabController;
selectColor = Colors.black;
unselectedColor = Color.fromARGB(255, 117, 117, 117);
selectStyle = TextStyle(fontSize: 18, color: selectColor, fontWeight: FontWeight.bold);
unselectedStyle = TextStyle(fontSize: 18, color: selectColor);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 0.0, bottom: 0.0),
child: TabBar(
tabs: _tabList,
isScrollable: true,
controller: _tabController,
indicatorColor: selectColor,
labelColor: selectColor,
labelStyle: selectStyle,
unselectedLabelColor: unselectedColor,
unselectedLabelStyle: unselectedStyle,
indicatorSize: TabBarIndicatorSize.label,
),
);
}
}
@Aaron009
Copy link
Author

Aaron009 commented Dec 27, 2019

I put a fixed Container on the SliverToBoxAdapter and it becomes slidable. Why is this?

class _TestNestedScrollState extends State<TestNestedScroll>
    with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return getTop();
//      return getNestedScroll();
  }

  Widget getTop() {
    List<Widget> expandedList = [];
    for (var i = 0; i < 100; ++i) {
      expandedList.add(Text('Expanded Text xxxxxxxxxx'));
    }

    return DefaultTextStyle(
      style: TextStyle(fontSize: 30, color: Colors.blue),
      child: Column(
          children: <Widget>[
              Container(
                height: MediaQuery.of(context).padding.top, // Status bar color
                color: Colors.grey,
              ),
              Text('this is Text'),
              Expanded(
                  child:SingleChildScrollView(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: expandedList,
                    ),
                  )
              ),
          ],
      ),
    );
  }

  Widget getNestedScroll() {
    XCTabBar tabBar = createTabBar(
      viewList: [
        Center(child: Text('page view1')),
        Center(child: Text('page view2')),
        Center(child: Text('page view3')),
      ],
      provider: this,
      tabStrings: 'tab item1,tab item2,tab item3',
    );

    return NestedScrollView(
      body: tabBar.getTabView(),
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverToBoxAdapter(
            child: getTop(),
          ),
          SliverPersistentHeader(
            floating: true,
            pinned: true,
            delegate: _SliverAppBarDelegate(
                maxHeight: 44.0,
                minHeight: 44.0,
                child: Container(
                  color: Colors.white,
                  child: tabBar,
                )
            ),
          ),
        ];
      },
    );
  }
}

This code runs, only the SingleChildScrollView area will scroll, the other parts are fixed, but when I put getTop in the SliverToBoxAdapter, it gave various errors. The error is as follows.

Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible children (using Flexible rather than Expanded). This will allow the flexible children to size themselves to less than the infinite remaining space they would otherwise be forced to take, and then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum constraints provided by the parent.

════════ (2) Exception caught by rendering library ════════════════════════
RenderBox was not laid out: RenderFlex#3ee20 relayoutBoundary=up2 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1687 pos 12: 'hasSize'
The relevant error-causing widget was: 
  SliverToBoxAdapter file:///C:/Users/Client/Desktop/flutter_xxxx/lib/main.dart:72:11
══════════════════════════════════════════════════════

════════ (3) Exception caught by rendering library ═════════════════════════════════════════════════
The method 'debugAssertIsValid' was called on null.
Receiver: null
Tried calling: debugAssertIsValid()
The relevant error-causing widget was: 
  NestedScrollView file:///C:/Users/Client/Desktop/flutter_xxxx/lib/main.dart:68:12
═══════════════════════

════════ (4) Exception caught by rendering library ═══════════
The getter 'visible' was called on null.
Receiver: null
Tried calling: visible
The relevant error-causing widget was: 
  NestedScrollView file:///C:/Users/Client/Desktop/flutter_xxxx/lib/main.dart:68:12
════════════════════════════════════════════════════════════════════════════════════

Seems prompting me to change "extension" to "flexible". Column plus mainAxisSize: MainAxisSize.min.

I followed the above prompt and it was run without reporting any errors, but the "This is text" text component was not pinned and sliding.

image-20191227193926364

Question one:

I want the content in the red box to always be pinned to the top, not sure why it is now sliding.

Question two:

image-20191227194212778

When I scroll to the second page, the tab does not switch automatically? When I click on the tab item, the page view below does not switch automatically? Why?
But I run on dartpad.dev, there is no such problem。

The complete code:
https://dartpad.dev/2df9288d77b219a9afa718d306a39862

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment