How to push a widget outside of context? - flutter

My current screenstructure looks like this:
Scaffold(
body: Stack(
children: [
_buildOffstageNavigator(FeedScreen()),
_buildOffstageNavigator(Screen2()),
_buildOffstageNavigator(Screen3()),
],
),
bottomNavigationBar: buildBottomNavigationBar(),
)
the BottomNavigationBar is just a regular bar.
Each of those screens are wrapped with a OffStage() widget like this:
Widget _buildOffstageNavigator(Widget screenToBuild) {
return Offstage(
offstage: currentPage != screenToBuild,
child: TabNavigator(
navigatorKey: _navigatorKeys[screenToBuild],
screenToBuild: screenToBuild,
),
);
}
My intention with this was to ensure a BottomNavigationBar at all times.
However, there is one widget, that I want to push from FeedScreen() that I don't want the NavigationBar on, but the context makes it hard to hide this NavigationBar
This is the structure of the FeedScreen()
Scaffold(
appBar: buildAppBar(),
body: SingleChildScrollView(
key: PageStorageKey<String>("Feed"),
controller: _feedSC,
child: Column(
children: [
buildStoriesListView(),
buildPostsListView(posts)
],
),
),
)
So my question is: Is there a way to push this Widget "on top" of the stack and kind of ignore the context or do I just have to hide the bar in this case? How would you do that?
Thanks

You can wrap you Scaffold with a Navigator and use Navigator.of(context, rootNavigator: true).push(PageRouteBuilder(pageBuilder: (context, _, __) => Foo())); to push the Foo widget on top of everything.

Related

In Flutter, how to scroll both AppBar and nested Beamer

I'm using Beamer for navigation in Flutter, and I want the top AppBar to not change (or do transition animations) when you navigate between screens. To do this, I'm using a nested Beamer. The build method for the top level screen looks like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('some title')),
body: Beamer(
key: _beamerKey,
routerDelegate: routerDelegate,
),
);
}
The result with this is that the AppBar is fixed at the top of the view port. If child screens have ScrollViews then just their content scrolls. I want the AppBar to scroll too to maximize screen real estate on small screens. I have tried the following:
return Scaffold(
body: ListView(
children: [
AppBar(title: const Text('some title')),
Beamer(
key: _beamerKey,
routerDelegate: routerDelegate,
),
],
));
and
return Scaffold(
body: CustomScrollView(slivers: <Widget>[
const SliverAppBar(
title: Text('data'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
((context, index) => Beamer(
key: _beamerKey,
routerDelegate: routerDelegate,
)),
childCount: 1)),
]),
);
In both cases I get an error _AssertionError ('package:flutter/src/widgets/overlay.dart': Failed assertion: line 728 pos 12: 'constraints.biggest.isFinite': is not true.)
What am I doing wrong?
Here's an example using a list of text fields in case it's not clear what it should look like (the app bar just scrolls along with everything else under it):

Flutter Modal Bottom Sheet with Navigator does not pop as expected

I a working with ModalBottomSheet and I love the package. However I am encountering an issue when trying to navigate with in a ModalBottomSheet.
Here is a ScreenVideo for a better understanding.
As you can see the View is presented as a ModalBottomSheet. But when popping it, it is not simply dismissing to the bottom but instead it is popping to some empty screen with a MaterialPage Pop animation.
I changed my code so I can push with a MaterialPageRoute-Animation inside that ModalBottomSheet. Before that everything was working as expected.
Here is my Page:
class _AboutScreenState extends State<AboutScreen> {
#override
Widget build(BuildContext context) {
return Material(
color: AppColors.primary,
child: Navigator(
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context2) => Builder(
builder: (context) => CupertinoPageScaffold(
backgroundColor: AppColors.secondary,
resizeToAvoidBottomInset: false,
child: SafeArea(
child: Padding(
padding: EdgeInsets.all(sidePadding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButtonWithExpandedTouchTarget(
onTapped: () {
Navigator.pop(context);
},
svgPath: 'assets/icons/down.svg',
),
],
),
Text(
'About',
style: AppTextStyles.montserratH2SemiBold,
),
...
RoundedCornersTextButton(
title: 'Impressum',
onTap: () {
Navigator.pop(context);
},
textColor: AppColors.primary,
backgroundColor: AppColors.secondary,
borderColor: AppColors.primary,
),
],
),
),
)),
),
),
),
);
}
}
I was simply following this example. What am I missing here? With the code above I can push inside the ModalSheet as expected with a MaterialPageRoute Animation but popping the first screen brings up the issue...
Let me know if you need any more info! Any help is appreciated :)
I think you are popping with the wrong context. The example is popping with rootContext, which is from the top-most widget in the hierarchy. You are popping from with context, defined at your lowest builder in the hierarchy.
I believe you are using the incorrect context. rootContext, which is from the top-most widget in the hierarchy, is what makes the sample pop. You're popping from your lowest builder in the hierarchy, which is dictated by context.

Refresh Indicator not working with NestedScrollView

#override
Widget build(BuildContext context) {
super.build(context);
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
key: _scaffoldKeyProfilePage,
body: DefaultTabController(
length: 2,
child:RefreshIndicator(
onRefresh: _onRefresh,
child: NestedScrollView(
headerSliverBuilder: (context, _) {
return [
SliverList(
delegate: SliverChildListDelegate(
[ BuildMainProfile(
....//
),
Padding(
...//another design
),
];
},
// You tab view goes here
body: Column(
children: <Widget>[
TabBar(
tabs: [
Tab(text: 'A'),
Tab(text: 'B'),
],
),
Expanded(
child: TabBarView(
children: [
BuildPost(,
),
BuildWings()
],
),
),
],
),
),),
),
}
Refresh Indicator not working with NestedScrollView, is there any way to implement RefreshIndiactor?
I tried adding an empty ListView in Stack, Refresh indicator start showing but because of that my NestedScrollView doesnt scroll.
Did you try setting NestedScrollView widgets physics to AlwaysScrollableScrollPhysics()?
Please see the documentation for RefreshIndicator.
Refresh indicator does not show up
The RefreshIndicator will appear if its scrollable descendant can be
overscrolled, i.e. if the scrollable's content is bigger than its
viewport. To ensure that the RefreshIndicator will always appear, even
if the scrollable's content fits within its viewport, set the
scrollable's Scrollable.physics property to
AlwaysScrollableScrollPhysics:
ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: ... )
A RefreshIndicator can only be used with a vertical scroll view.
Please try to wrap 'body' of the NestedScrollView with RefreshIndicator widget if the headers won't change when refreshed but only the content change happens for 'body'.

How to add a drawer to SilverAppBar in flutter?

I have used SilverAppBar but don't know how to add a drawer to it. I just want an app bar with a drawer that hides on scrolling
Note that the Scaffold takes care of all of the major behavior associated with Material design.
If you add the drawer field to your Scaffold, it will automatically add a hamburger menu icon to the left hand side of your SilverAppBar in flutter.
Code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Drawer - Sliver AppBar'),
)],
),
drawer: Drawer(
child: Column(
children: <Widget>[
DrawerHeader(
child: Text(' I am Drawer'),
curve: SawTooth(12),
),
],
),
),
);
}

How can I put a SearchView on top of a ListView?

I'm new to flutter and am trying to stack a searchView on top of a ListView. I would Look something like this:
I don't know how to achieve this layout on flutter, i tried using a column(which crashes the app), used the a stack (which overlaps the widgets) and i finally tried to add a search widget a the first item of the ListView but that didn't result am looking for.
Widget build(BuildContext context) {
return new Scaffold(
drawer: _makeDrawer(),
appBar: new AppBar(
title: new Center(
child: new Text("translate"),
),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.people_outline), onPressed: () {})
],
),
body: _phraseListFutureBuilder(), // this part of the code renders the listview
);
}
FutureBuilder _phraseListFutureBuilder() {
return new FutureBuilder(
builder: (BuildContext context, AsyncSnapshot snapshot) {
return mPhrases.isEmpty
? new CircularProgressIndicator()
: _buildPhrases();
},
future: _fetchData());
}
A Column was the right choice, but you will also need an Expanded widget to specify which widget should fill the remaining space:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'Search'
),
),
Expanded(
child: _phraseListFutureBuilder(),
)
],
);