How to make scrolling page continue even when tabBarView reaches the top? Flutter - flutter

The code I ran was the code that was given by Griffins here: How To Move The TabBarView in the Center to The Top of the Page?
Everything is the same as the code given by Griffins.
However, when the tabBar was scrolled to the top and locked there, the content under each widget stopped scrolling too.
I want the content of the widget page to continue scrolling to its end, even when the tabBar is locked at the top.
Even if pinned and floating of SliverPersistentHeader was declared false, all it does is just to make the tabBar scrolled up, the content of the tabBarView still ends at the similar position. This is occurring for both tabBarViews.
So I'm suspecting it has something to do with the sliverfillremaining taking up the remaining height. Is there a way to overcome this? and show all the content of the tabBar?

Solved.
I changed the SliverFillRemaining to
SliverToBoxAdapter(
child: AnimatedBuilder(
animation: tabController.animation,
builder: (ctx, child) {
if (tabController.index == 0) {
return Page1();
} else
return Page2();
}),
)

Related

Flutter, in nested scrollview (consisting of header and tabview ) the scrolling should not happen if the tabview has less or no data

I have a header widget and then a tab view. I have been able to make them scroll as one using a nestedscrollview. But I want the scrolling to not happen if tab view data is not present.
Disable scroll if total child length < scroll height:
NestedScrollView(
physics: (sumHeight>scrollHeight) ? AlwaysScrollableScrollPhysics() : NeverScrollableScrollPhysics()
)

Killing flutter gesture

I am trying to stop a gesture from continuing if a certain criteria is met.
The scenario is the user is swiping a tab bar and if they go to the next tab and the condition is true it should disable further swiping. I have tried to put the tab bar in a stack with an Absorb pointer container on top but if they don't let go of the original gesture (i.e. they got to the new tab but didnt let go of the screen) it still allows them to drag through it.
is there anyway to stop the original swipe gesture?
i found this cancel method but i have no idea how to access it
https://api.flutter.dev/flutter/gestures/Drag/cancel.html
In your case there is no need to handle gesture out of the TabBarView simply change the ScrollPhysics.
Here a code example:
final isDisable = ValueNotifier(false);
tabController.animation?.addListener(() {
//The scrolling will be disabled if the second tab is displayed so you can
//add your own logic, may be just checking tabController.index
if (tabController.animation!.value == 1.0) {
isDisable.value = true;
}
});
return Scaffold(
body: ValueListenableBuilder(
valueListenable: isDisable,
builder: (context, bool value, child) => TabBarView(
controller: tabController,
// changing the physics to NeverScrollableScrollPhysics will disable scrolling
physics: value
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
children: children,
),
),
);

How can I make a SliverAppBar that is similar to Google News?

I want a standard AppBar when the app starts, however, once the user begins scrolling I want the app bar to slide up and off the screen. However, when that happens, the status bar (on iOS) doesn't have a background. I don't want to set a constant background directly to the status bar using something like flutter_statusbarcolor because that leaves a solid color, which isn't a widget.
The only solution I have right now is to just keep the AppBar pined.
However, what I really want to do is what Google News does. The AppBar slides up almost all the way, however, it stays under the app bar with some opacity.
How Google News does it:
Is there any way to do this with Flutter and SliverAppBar without doing it a hacky way? The only thing I'm thinking is doing it with a stack, however, how would I know how to keep it under the status bar, as Android already has some opacity under the status bar.
Scroll widgets in flutter have controllers that inform what's going on with the scroll. You can get how much the sliver has been scrolled and change it's opacity, content and size accordingly. It's not going to be simple though, but take a look at ScrollController, used by the CustomScrollView.
I used OrientationBuilder widget to listen to changes in orientation, as when there are changes to the orientation the status bar hight can change.
Then I used FlutterStatusbarManager package to get the height of the status bar. FlutterStatusbarManager.getHeight is a future so it needed to be wrapped with a FutureBuilder
Here is the full example code
import 'package:flutter/material.dart';
import 'package:flutter_statusbar_manager/flutter_statusbar_manager.dart';
class FixedStatusbarBackground extends StatelessWidget {
final Widget child;
const FixedStatusbarBackground({Key key, this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
child,
OrientationBuilder(
builder: (context, Orientation orientation) => FutureBuilder<double>(
future: FlutterStatusbarManager.getHeight,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Container(
height: snapshot.data,
color: Theme.of(context)
.appBarTheme
.color
.withOpacity(.7) //Colors.white.withOpacity(.7),
);
} else {
return Container();
}
}),
),
],
);
}
}
The child widget that is passed in is the entire CustomScrollView.

BottomSheet always appear in expanded state, it's always in full height. Why is this happen? What's the possible cause of this?

I want to show a bottom sheet after the user tap on the FAB button. At first, it was working properly but I didn't know why it suddenly started to appear in full height/expanded state mode all the time.
I've tried with all type of bottom sheet listed in the document. It has the same problem.
// _scaffoldKey.currentState
// .showBottomSheet((context) => AccountView());
showModalBottomSheet(
context: context, builder: (context) => AccountView());
In the AccountView is a ListView, Currently, there's only one item. The bottom sheet height should only be equaled to the height of the ListTile. But it appears in full height instead.
You can use shrinkWrap: true, property in ListView or you can put AccountView() in a container and give it height.
Turn out I need to set shrinkWrap in the column to true.
Column(
shrinkWrap: true,
...
)

The efficient way to implement a vertically translating widget on user drag

I want to translate a widget vertically as the user drags. I tried implementing it using two options:
AnimationController
Value notifier.
So when I use the animation controller the scroll is not very smooth and the widget is being scroll after a delay even when the duration of the animation is 1 milliseconds.
When I implement it using value notifier it is much better but still not as smooth as the ListView scroll. Is there a better way to scroll\translate a widget on user drag?
I found a better solution for this. Although it can be achieved using Gesture detector but that is not as smooth. Flutter has another wonderful widget for this and that is DraggableScrollableSheet.
If you want container for a Scrollable list that responds to drag gestures by resizing the scrollable until a limit is reached, and then scrolling this is the widget you should be using.
DraggableScrollableSheet(
initialChildSize: .70,
minChildSize: .70,
builder: (BuildContext context, ScrollController scrollcontroller){
scrollcontroller.addListener((){
});
return Container(
child: ListView.builder(
controller: scrollcontroller,
itemCount: widget.songs.length,
itemBuilder: (BuildContext context, int index) {
return buildSongRow(widget.songs[index]);
})
);
})
The above list will be place at the 70 percent of the height of the screen initially. When you scroll up it drags the list up to the top and then the list scrolls as a normal listview. When you reach the top while scrolling, the list drags down to the initial position(70 percent of height).