Get Container take the remaining space of the screen below the Header - flutter

I got my page layout like this:
return new Scaffold(
appBar: _getAppBarWidget(_currentIndex),
body: return CustomScrollView(slivers: [
SliverPersistentHeader(
delegate: ProfileBar(expandedHeight: 200),
pinned: true,
),
SliverToBoxAdapter(
child: ProfileView()
),
]);,
bottomNavigationBar: BottomBar(),
);
and I want my ProfileView to take the whole rest of the screensize.
ProfileView() looks like this:
return Container(
color: Colors.green;
child: RaisedButton(
child: const Text('Something'),
textColor: Colors.white,
color: Colors.redAccent,
onPressed: () {}
)
);
But I just can't get my Container from ProfileView to take the whole rest of the screenheight that is remaining below the SliverPersistentHeader.
I tried a lot of different things but didn't succeed. (e.g. using Expended) Someone has an advice for this?
Edit: The only thing I succeeded in was hardcoding it. But this is not what I want.

To solve the issue you can use SliverFillRemaining instead of SliverToBoxAdapter
So your updated code will be
return new Scaffold(
appBar: _getAppBarWidget(_currentIndex),
body: return CustomScrollView(slivers: [
SliverPersistentHeader(
delegate: ProfileBar(expandedHeight: 200),
pinned: true,
),
SliverFillRemaining(
child: ProfileView()
),
]);,
bottomNavigationBar: BottomBar(),
);

Related

How do i evenly position widgets or items in SliverAppBar Flutter?

I have a SliverAppBar and i am trying to position three items in a row:
User Profile Picture
User Account Information
Notification bar widget
But whenever i try to add the User Account Information Widget in the row i either get a render flex error or it gets positions incorrectly and get out of sight.
This is what i've tried and i will give the code snippets my SliverAppBar.
Using a flexibleSpace with a FlexibleSpaceBar() widget and wrapping the title in a row where i then instantiate the 3 widgets.
HomeAccountPicture(),
HomeAccountDetails(),
NotificationsButtonWidget(),
as the child.
I made sure the respective widgets are just wrapped in 'Containers()`
This is my Sliver App Snippet
class HomeView extends GetView<HomeController> {
#override
Widget build(BuildContext context) {
controller.initScrollController();
return WillPopScope(
onWillPop: Helper().onWillPop,
child: Scaffold(
body: RefreshIndicator(
onRefresh: () async {
Get.find<LaravelApiClient>().forceRefresh();
controller.refreshHome(showMessage: true);
Get.find<LaravelApiClient>().unForceRefresh();
},
child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(),
controller: controller.scrollController,
shrinkWrap: false,
slivers: <Widget>[
SliverAppBar(
backgroundColor: Color(0xffFFFFFF),
expandedHeight: MediaQuery.of(context).size.height * 0.25,
elevation: 0.5,
//pinned: true,
floating: false,
iconTheme: IconThemeData(color: Get.theme.primaryColor),
centerTitle: true,
flexibleSpace: FlexibleSpaceBar(
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
HomeAccountPicture(),
HomeAccountDetails(),
NotificationsButtonWidget(),
],
),
),
automaticallyImplyLeading: false,
),
SliverToBoxAdapter(
child: Wrap(
children: [
BookingsListWidget(),
],
),
),
],
)),
),
);
}
}
This is my expectation
This is what i get

Flutter why do I get an appBar even though i didn't put any appBar command in my scaffold

Is there a way to modify the appbar that I get from pushedName or is there a way that I can remove the appbar? I've been searching for around 2 hours already and I can't find any answer relate of it. Some of question suggest to use the appBar command. Tried it already but for me they give me more appbar now. and they become double after I putting the appbar in my scaffold widget. This is the pic of the app bar now. (I even can't change my icon color in that app bar)
class _seller_profile_screenState extends State<seller_profile_screen> {
double tp = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
CustomScrollView(
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
slivers: [
SliverAppBar(
pinned: true,
stretch: true,
expandedHeight: 200,
flexibleSpace: LayoutBuilder(builder: (ctx, cons) {
tp = cons.biggest.height;
return FlexibleSpaceBar(
centerTitle: true,
background: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/cloud_background.jpg',
fit: BoxFit.cover,
),
SafeArea(
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(children: [
//
]),
),
)
],
),
);
})),
],
)
],
),
);
}
}
This is due to screen hierarchy. There was one screen before this so you get back button by default when you use snackbar. If you want to remove this then do like this:
Scaffold(
appBar:AppBar(
...
automaticallyImplyLeading: false,
),
body:...);

Is it possible to use BottomNavigatorBar without to use Scaffold`s Body

There are plenty Bottom Navigator Bar tutorial in internet but almost all of them suggesting to put the Navigate method into Scaffold's body.
Here is my final Navigate and it works if I put into Scaffold's body:
showPage(_selectedIndex)
but the problem is I am using on same page Tabbar and BottomNavigatorBar together. Here is the current situation (Scaffold's body)
body: TabBarView(
children: [
for (final tab in filteredList)
NewsView(
id: tab.id!,
),
],
),
unfortunately I could not find a way to put or integrate showPage(_selectedIndex)
P.S. the tabs generating dynamically from JSON.
The Scaffold Widget has a ButtonNavigationBar property besides de body. If it’s about navigation you can definitely add a button and pass the reference to the Class or Page you want to navigate to in its ‘onPressed () {}’ property. This is an example from the official documentation:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample Code'),
),
body: Center(
child: Text('You have pressed the button $_count times.'),
),
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
child: Container(height: 50.0),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
_count++;
}),
tooltip: 'Increment Counter',
child: const Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
Here’s the link https://api.flutter.dev/flutter/material/Scaffold-class.html
the final solution:
body: Center(
child: _selectedIndex != 0
? showPage(_selectedIndex)
: TabBarView(
children: [
for (final tab in filteredList)
NewsView(
id: tab.id!,
),
],
),
),

Create customized SliverPersistentHeader like Widget with Flutter

I have a Header that consists of:
1 - appBar (title + return button)
2 - row with a data picker)
3 - a row serving as a customized TabBar (with two Tabs)
4 - a row serving as a FilterBar (with a Button and a search field)
Then I have the "body" with a list of Cards that is scrollable.
I needed to retract/hide numbers 1-3 and keep only number 4 visible when I scroll down the list of cards. How could I build a customized Widget to help me with that?
Here is part of the code (it's too long to bring everything):
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor: Colors.blue,
title: 'List of Tasks',
elevation: 0.0,
pinned: true,
),
SliverPadding(
padding: EdgeInsets.all(15),
sliver: SliverToBoxAdapter(
child: DatePicker(
date: date,
onChange: (newDate) {
setState(() {});
},
),
),
),
SliverToBoxAdapter(
child: ActivitiesTabController(
pageController: _pageController,
currentTab: currentTab,
onChangedTab: (currentTab) {},
),
),
SliverToBoxAdapter(
child: Row(
children: [
SearchFilterBar(
taskId: taskId,
onChange: (floors, serviceName) {},
),
],
),
),
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return new Container(color: Colors.amberAccent, height: 150.0);
}),
),
],
));
}
I think you're referring to two app bars, where the first one can be scrolled away while the second one is persistent.
I think it would be something like this:
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(slivers: [
SliverAppBar(
title: Text('This hides'),
),
SliverAppBar(
title: Text('This is always shown'),
pinned: true,
primary: false,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(_, i) {
return ListTile(title: Text('Line $i'));
},
childCount: 150,
),
),
]),
);
}

Bottom overflow by 30px

I face a problem by wrapping TextField with new Expanded(). When try to search something in textfield its show me bottom overflow by 30px. Below is my code:
Widget build(BuildContext context) {
return new Scaffold(
body:
Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {
setState(() {
});
}),
new Flexible(
child: new TextField(
onChanged: (String value) {
onchange(value);
},
maxLines: 1,
autocorrect: true,
// decoration: const InputDecoration(helperText: "Search"),
style: new TextStyle(fontSize: 10.0, color: Colors.black),
),
),
_text != null ? IconButton(
icon: Icon(Icons.close), onPressed: (){
}) : new Container(),
IconButton(icon: Icon(Icons.bookmark_border), onPressed: () {}),
],
),
new Expanded(
child: FilstList(searchtext: _text,)
),
],
),
);
}
}
There are two solutions to this problem.
Add resizeToAvoidBottomPadding: false to your Scaffold
Scaffold(
resizeToAvoidBottomPadding: false,
body: ...)
Put your FilstList(searchtext: _text,) inside a scrollableView (like SingleChildScrollView or ListView)
Use Scaffold property "resizeToAvoidBottomPadding: false"
and "SingleChildScrollView" as parent of Scaffold body:
home: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Registration Page"),
),
body: SingleChildScrollView(
child: RegisterUser(),
)),
this will solve issue.
You should use resizeToAvoidBottomInset
Scaffold(
resizeToAvoidBottomInset: false, // set it to false
...
)
If you're having issues with overflow error, use SingleChildScrollView with it.
Scaffold(
resizeToAvoidBottomInset: false, // set it to false
body: SingleChildScrollView(child: YourBody()),
)
I faced a similar problem and fixed it in the following way:
You can wrap it with SingleChildScrollView or with a ListView.
Scaffold(
body: Container(
height: MediaQuery.of(context).size.height * .50,
child: SingleChildScrollView(
child: Column(
....
)
)
)
);
put resizeToAvoidBottomPadding as false in Scaffold:
Scaffold(
resizeToAvoidBottomPadding: false,
update
it is better solution:
remove Column and put instead it ListView
because if you run this app on smaller device bottom items will disappear and hide from the show screen and that will be bad for App users.
Use of resizeToAvoidBottomInset: false in your Scaffold is the best solution to that.
Do two way
NO1.
Scaffold(
resizeToAvoidBottomPadding: false, )
The problem is when you do this body content never gone top when you select input box..
Best practice
SingleChildScrollView widget
Use CustomScrollView with SliverToBoxAdapter:
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Form(....)
),
]
)
Use Scaffold and make "resizeToAvoidBottomInset" false.
Scaffold(
resizeToAvoidBottomInset: false,
........
)
Used SigleChildScrollView
sample code
Scaffold(
appBar: //AppBar
body: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,