Closed jimmyff closed 3 years ago
Hi @jimmyff
can you please provide your flutter doctor -v
and flutter run --verbose
?
Running your code doesn't seem to produce errors Dartpad Gist
Thank you
Hey @TahaTesser, it definetly causes an erorr, I just created a new project to test it. I've included the app code below.
In order to get the error:
This should create the red screen of death.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tab state error',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: ExampleErrorScreen(),
);
}
}
class ExampleErrorScreen extends StatefulWidget {
ExampleErrorScreen();
@override
_ExampleErrorScreenState createState() => _ExampleErrorScreenState();
}
class _ExampleErrorScreenState extends State<ExampleErrorScreen>
with SingleTickerProviderStateMixin {
TabController _tabController;
int selectedTab = 0;
@override
initState() {
super.initState();
_tabController = TabController(initialIndex: 0, length: 3, vsync: this);
_tabController.addListener(tabChange);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
tabChange() {
if (_tabController.indexIsChanging == false)
setState(() {
selectedTab = _tabController.index;
});
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraint) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: Colors.amberAccent,
expandedHeight: 400,
floating: false,
actions: <Widget>[
if (_tabController.index == 1)
IconButton(
icon: Icon(Icons.access_time),
onPressed: () => print('pressed'),
),
if (_tabController.index == 2)
IconButton(
icon: Icon(Icons.ac_unit),
onPressed: () => print('pressed'),
)
],
pinned: true,
bottom: TabBar(
controller: _tabController,
isScrollable: true,
tabs: [
Tab(
text: '1',
icon: Icon(Icons.access_alarm),
),
Tab(
text: '2',
icon: Icon(Icons.account_balance),
),
Tab(
text: '3',
icon: Icon(Icons.business),
),
]),
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.only(bottom: 96),
centerTitle: true,
title: Text(
'test',
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
),
),
),
),
];
},
body: TabBarView(controller: _tabController, children: [
CustomScrollView(
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
CustomScrollView(
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
CustomScrollView(
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
]),
),
);
});
}
}
[✓] Flutter (Channel master, v1.15.4-pre.155, on Mac OS X
10.14.6 18G1012, locale en-GB)
• Flutter version 1.15.4-pre.155 at
/Users/jimmyff/flutter-sdk
• Framework revision 2078cc4d5f (6 days ago), 2020-02-25
01:02:26 -0500
• Engine revision 888a62cf22
• Dart version 2.8.0 (build 2.8.0-dev.10.0 73f6d15665)
Checking Android licenses is taking an unexpectedly long time.. [✓] Android toolchain - develop for Android devices (Android
SDK version 28.0.3)
• Android SDK at /Users/jimmyff/Library/Android/sdk
• Android NDK location not configured (optional; useful for
native profiling support)
• Platform android-28, build-tools 28.0.3
• Java binary at: /Applications/Development/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_202-release-1483-b49-5587405)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.3.1, Build version 11C504
• CocoaPods version 1.6.1
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Development/Android
Studio.app/Contents
• Flutter plugin version 40.2.2
• Dart plugin version 191.8593
• Java version OpenJDK Runtime Environment (build
1.8.0_202-release-1483-b49-5587405)
[!] IntelliJ IDEA Ultimate Edition (version 2017.2)
• IntelliJ at /Applications/Development/IntelliJ IDEA.app
✗ Flutter plugin version 15.1 - the recommended minimum
version is 16.0.0
• Dart plugin version 172.3317.48
• For information about installing plugins, see
https://flutter.dev/intellij-setup/#installing-the-plugin
s
[✓] Connected device (1 available)
• Pixel 3 • 8B5X140C0 • android-arm64 • Android 10 (API 29)
! Doctor found issues in 1 category.
Hi @jimmyff
Can you please add key: UniqueKey(),
to NestedScrollView
in your sample code from the comment and run the app again and see if it fixes the issue for you? It fixes the issue for me
Thank you
@TahaTesser yes that fixed the issue - but why does this fix it? They UniqueKey isn't stored in the widget state so surely it would be recreated each build?
Hi @jimmyff
You can find a lot of information here and UniqueKey
probably solves the position.minScrollExtent != null && position.pixels != null': is not true.
assertion in your case.
Given the related issue is still open. I feel safe to close this issue if you disagree please write in the comments and I will reopen it Thank you
@TahaTesser using UnqiueKey seems to cause some strange side affects: for example on TabBarView swiping to the side tabs makes the scroll position jump back up to the top. Also if I change the parent scaffold it makes the scroll position jump back to the top.
It solves my initial problem but creates a few new problems, am I doing something wrong with the UniqueKey? I've tried storing in in state for the widget but this doesn't help.
@jimmyff
I looked at your code sample and noticed that if we pass controller
property to each CustomScrollView
, then the red screen goes away and you are able to go back to tab 1 from tab 3 without any issues.
body: TabBarView(controller: _tabController, children: [
CustomScrollView(
controller: _scrollController,
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
CustomScrollView(
controller: _scrollController,
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
CustomScrollView(
controller: _scrollController,
slivers: <Widget>[SliverToBoxAdapter(child: Container())],
),
]),
where _scrollController
is defined as var _scrollController = ScrollController();
.
Closing, as this is now working as expected. If you disagree, write in comments and I'll reopen it.
@darshankawar Initially getting the red screen . Fixed the issue with help of your code. Now how to hide the silver app bar title and bottom navigation bar when tab bar view (list view ) content scroll up and down. Thanks.
@rashmisridar This issue has been closed for a while Can you please file a new issue with all the details
@TahaTesser Sure
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v
and a minimal reproduction of the issue.
I spent the afternoon tracking down a bug, however I have created a reproducable example of it. This error is triggered when changing state during a tab change callback when the TabBarView contains multiple CustomScrollViews. The error:
package:flutter/src/widgets/nested_scroll_view.dart': Failed assertion: line 590 pos 14: 'position.minScrollExtent != null && position.pixels != null': is not true.
The error only occurs if you move tabs to a tab that is not immedatley ajecent to another tab. (eg: going from tab 1 -> 3, or 3 -> 1. ) The reason I need to update the state on tab change is so I can change the action bar buttons.
The error seems to be caused by the CustomScrollView in the middle (that is getting jumped over). If I change this to a Container() the error goes away.
Here is the Widget that reproduces the problem:
Screenshots demonstrating the issue:
This is what you will see when you run the code:
After sliding to the right (or using Tab button 2)
From 2, after sliding to the right (or using Tab button 3)
But then if you go back to the first tab using the Tab buttons you will trigger the error: