Correct TabBarView usage - flutter

my code getting 32x tabs from JSON and putting them to Appbar as scrollable. Now I am looking for a way to execute a categoryListTile according to selection Tab and send correct id number to categoryListTile widget on another page.
unfortunately I cannot find a correct way to do this.
List<Tab> tabs = <Tab>[];
for (int i = 0; i < snapshot.data!.data!.length; i++) {
tabs.add(
Tab(
child: Text(' ${name?[i].name}'.toUpperCase()),
),
);
}
return DefaultTabController(
length: snapshot.data!.data!.length,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Image.asset("assets/images/logo.png",
fit: BoxFit.contain, height: 22),
bottom: TabBar(
indicatorColor: Colors.black,
isScrollable: true,
tabs: tabs),
),
body: TabBarView(
children: categoryListTile(name!, id!, context),
),
),
);
}
I am pretty sure this is completely wrong but how can I to do this

try replace body:
body: TabBarView(
children: [for (final tab in snapshot.data!.data!) categoryListTile(tab.name!, tab.id!, context)],
),

Related

DefaultTabController.of always return null

I have a flutter app with a DefaultTabController, at multiple places in the code I tried to get the associated TabController, but I go null.
TabController? c = DefaultTabController.of(context);
I have tried just after the widget creation and also at other places, but I always receive null.
If someone has an idea why and how to solve this ?
You need to make sure you are trying to access the DefaultTabController in a context that actually has a DefaultTabController. In many cases, this means adding an extra Builder widget:
Scaffold(
body: SafeArea(
child: DefaultTabController(
initialIndex: 0,
length: 3,
child: Builder( // Add this
builder: (context) {
return Column(
children: [
TabBar(
controller: DefaultTabController.of(context),
labelColor: Colors.black,
tabs: [
Tab(text: 'One'),
Tab(text: 'Two'),
Tab(text: 'Three'),
],
),
Expanded(child: Center(
child: OutlinedButton(
child: Text('Three'),
onPressed: (){
DefaultTabController.of(context)?.animateTo(2);
},
),
))
],
);
}
),
),
),
);

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:...);

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,
),
),
]),
);
}

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

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(),
);