Closed Shamik07 closed 3 years ago
import 'package:flutter/material.dart';
import 'package:sticky_and_expandable_list/sticky_and_expandable_list.dart';
import 'mock_data.dart';
class ExampleTabLayoutCustomSectionAnimation extends StatefulWidget {
@override
_ExampleTabLayoutCustomSectionAnimationState createState() =>
_ExampleTabLayoutCustomSectionAnimationState();
}
class _ExampleTabLayoutCustomSectionAnimationState
extends State<ExampleTabLayoutCustomSectionAnimation> {
var sectionList = MockData.getExampleSections(10, 10);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: Container(color: Colors.red),
),
body: ExpandableListView(
builder: SliverExpandableChildDelegate<String, ExampleSection>(
sectionList: sectionList,
itemBuilder: (context, sectionIndex, itemIndex, index) {
String item = sectionList[sectionIndex].items[itemIndex];
return ListTile(
leading: CircleAvatar(
child: Text("$index"),
),
title: Text(item),
);
},
sectionBuilder: (context, containerInfo) => _SectionWidget(
section: sectionList[containerInfo.sectionIndex],
containerInfo: containerInfo,
onStateChanged: () {
//notify ExpandableListView that expand state has changed.
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {});
}
});
},
),
),
));
}
}
class _SectionWidget extends StatefulWidget {
final ExampleSection section;
final ExpandableSectionContainerInfo containerInfo;
final VoidCallback onStateChanged;
_SectionWidget(
{@required this.section,
@required this.containerInfo,
@required this.onStateChanged})
: assert(onStateChanged != null);
@override
__SectionWidgetState createState() => __SectionWidgetState();
}
class __SectionWidgetState extends State<_SectionWidget>
with SingleTickerProviderStateMixin {
static final Animatable<double> _halfTween =
Tween<double>(begin: 0.0, end: 0.5);
AnimationController _controller;
Animation _iconTurns;
Animation<double> _heightFactor;
@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
_iconTurns =
_controller.drive(_halfTween.chain(CurveTween(curve: Curves.easeIn)));
_heightFactor = _controller.drive(CurveTween(curve: Curves.easeIn));
if (widget.section.isSectionExpanded()) {
_controller.value = 1;
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
widget.containerInfo
..header = _buildHeader(context)
..content = _buildContent(context);
return ExpandableSectionContainer(
info: widget.containerInfo,
);
}
Widget _buildHeader(BuildContext context) {
return Container(
color: Colors.lightBlue,
child: ListTile(
title: Text(
widget.section.header,
style: TextStyle(color: Colors.white),
),
trailing: RotationTransition(
turns: _iconTurns,
child: const Icon(
Icons.expand_more,
color: Colors.white70,
),
),
onTap: _onTap,
),
);
}
void _onTap() {
widget.section.setSectionExpanded(!widget.section.isSectionExpanded());
if (widget.section.isSectionExpanded()) {
widget?.onStateChanged();
_controller.forward();
} else {
_controller.reverse().then((_) {
widget?.onStateChanged();
});
}
}
Widget _buildContent(BuildContext context) {
return SizeTransition(
sizeFactor: _heightFactor,
child: SliverExpandableChildDelegate.buildDefaultContent(
context, widget.containerInfo),
);
}
}
import 'dart:io';
import 'package:example/example_custom_section_animation.dart';
import 'package:example/example_tab_layout_custom_section_animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class TabLayoutView extends StatelessWidget {
const TabLayoutView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
ScrollController scrollController;
TabController tabController;
return DefaultTabController(
length: 5,
child: Scaffold(
body: new NestedScrollView(
controller: scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
new SliverAppBar(
pinned: true,
floating: true,
//forceElevated: true,
//forceElevated: innerBoxIsScrolled, for complete flat
forceElevated: !innerBoxIsScrolled,
elevation: 2,
backgroundColor: Colors.indigo,
title: _buildTitle(context),
bottom: new TabBar(
indicatorColor: Colors.amberAccent,
indicatorSize: TabBarIndicatorSize.label,
indicatorWeight: 5,
isScrollable: true,
tabs: <Tab>[
Tab(icon: Icon(Icons.music_note)),
Tab(icon: Icon(Icons.music_video)),
Tab(icon: Icon(Icons.camera_alt)),
Tab(icon: Icon(Icons.grade)),
Tab(icon: Icon(Icons.email)),
],
controller: tabController,
),
),
];
},
body: new TabBarView(
children: <Widget>[
ExampleTabLayoutCustomSectionAnimation(),
ExampleCustomSectionAnimation(),
ExampleTabLayoutCustomSectionAnimation(),
ExampleCustomSectionAnimation(),
ExampleTabLayoutCustomSectionAnimation(),
],
controller: tabController,
),
),
),
);
}
}
Widget _buildTitle(BuildContext context) {
/*var horizontalTitleAlignment =
Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;*/
var horizontalTitleAlignment = CrossAxisAlignment.center;
if(!kIsWeb){
horizontalTitleAlignment = Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;
}
return new InkWell(
//onTap: () => scaffoldKey.currentState.openDrawer(),
child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: horizontalTitleAlignment,
children: <Widget>[
const Text('Tab Layout'),
],
),
),
);
}
Hi! Apologies for creating this issue. There was nothing wrong with your package, It was just a flutter bug or wrong implementation of NestedScrollView on my part.
Here is the bug - https://github.com/flutter/flutter/issues/22393
Here is the fix -
import 'dart:io';
import 'package:example/example_custom_section_animation.dart';
import 'package:example/example_tab_layout_custom_section_animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class TabLayoutView extends StatelessWidget {
const TabLayoutView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
ScrollController scrollController;
TabController tabController;
return DefaultTabController(
length: 5,
child: Scaffold(
body: new NestedScrollView(
controller: scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverSafeArea(
top: false,
sliver: new SliverAppBar(
pinned: true,
floating: true,
//forceElevated: true,
//forceElevated: innerBoxIsScrolled, for complete flat
forceElevated: !innerBoxIsScrolled,
elevation: 2,
backgroundColor: Colors.indigo,
title: _buildTitle(context),
bottom: new TabBar(
indicatorColor: Colors.amberAccent,
indicatorSize: TabBarIndicatorSize.label,
indicatorWeight: 5,
isScrollable: true,
tabs: <Tab>[
Tab(icon: Icon(Icons.music_note)),
Tab(icon: Icon(Icons.music_video)),
Tab(icon: Icon(Icons.camera_alt)),
Tab(icon: Icon(Icons.grade)),
Tab(icon: Icon(Icons.email)),
],
controller: tabController,
),
),
),
),
];
},
body: new TabBarView(
children: <Widget>[
ExampleTabLayoutCustomSectionAnimation(),
ExampleCustomSectionAnimation(),
ExampleTabLayoutCustomSectionAnimation(),
ExampleCustomSectionAnimation(),
ExampleTabLayoutCustomSectionAnimation(),
],
controller: tabController,
),
),
),
);
}
}
Widget _buildTitle(BuildContext context) {
/*var horizontalTitleAlignment =
Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;*/
var horizontalTitleAlignment = CrossAxisAlignment.center;
if(!kIsWeb){
horizontalTitleAlignment = Platform.isIOS ? CrossAxisAlignment.center : CrossAxisAlignment.start;
}
return new InkWell(
//onTap: () => scaffoldKey.currentState.openDrawer(),
child: new Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: horizontalTitleAlignment,
children: <Widget>[
const Text('Tab Layout'),
],
),
),
);
}
Sorry!
Thank you for you feedback ^_^
I am trying to implement the ExampleCustomSectionAnimation in a TabLayout
But as soon as I scroll and the AppBar collapses the header no longer remains sticky and gets under the AppBar. This AppBar is in the TabLayout Main view
But if give another AppBar in the ExampleCustomSectionAnimation list view - In Red over here
The header becomes sticky again
I want the headers to remain sticky without the additional AppBar (Red),
Thanks for the package, Love it!
The issue can be easily replicated by placing the ExampleCustomSectionAnimation provided in the sample in a TabBarView
MainTabLayout