How to detect first and second scroll in flutter - flutter

i want to detect my first and second scroll in flutter .when first scroll performed first list hide and category tab must show then on second scroll the appbar should be hide ,following code what i tried and its an example of collapsing toolbar and below image is the result what i want. iam a nube in flutter please help and sorry for my bad english
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: CustomSliverAppbar(),
);
}
}
class CustomSliverAppbar extends StatefulWidget {
#override
_CustomSliverAppbarState createState() => _CustomSliverAppbarState();
}
class _CustomSliverAppbarState extends State<CustomSliverAppbar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(
initialIndex: 0,
length: 2,
vsync: this,
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text(
"WhatsApp type sliver appbar",
),
centerTitle: true,
pinned: true,
floating: true,
bottom: TabBar(
indicatorColor: Colors.black,
labelPadding: const EdgeInsets.only(
bottom: 16,
),
controller: _tabController,
tabs: [
Text("TAB A"),
Text("TAB B"),
]),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
class TabA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scrollbar(
child: ListView.separated(
separatorBuilder: (context, child) => Divider(
height: 1,
),
padding: EdgeInsets.all(0.0),
itemCount: 30,
itemBuilder: (context, i) {
return Container(
height: 100,
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: CustomSliverAppbar(),
);
}
}
class CustomSliverAppbar extends StatefulWidget {
#override
_CustomSliverAppbarState createState() => _CustomSliverAppbarState();
}
class _CustomSliverAppbarState extends State<CustomSliverAppbar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(
initialIndex: 0,
length: 2,
vsync: this,
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text(
"WhatsApp type sliver appbar",
),
centerTitle: true,
pinned: true,
floating: true,
bottom: TabBar(
indicatorColor: Colors.black,
labelPadding: const EdgeInsets.only(
bottom: 16,
),
controller: _tabController,
tabs: [
Text("TAB A"),
Text("TAB B"),
]),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
class TabA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scrollbar(
child: ListView.separated(
separatorBuilder: (context, child) => Divider(
height: 1,
),
padding: EdgeInsets.all(0.0),
itemCount: 30,
itemBuilder: (context, i) {
return Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
),
);
}
} width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
),
);
}
}

Related

how to create ListView like given image

Blockquote
how to create list view like this how to create this type layout in flutter
you can copy the whole code in below
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late PageController controller;
double page = 0.0;
#override
void initState() {
super.initState();
controller = PageController(viewportFraction: 0.5)
..addListener(() {
setState(() {
page = controller.page!;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade100,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(26),
color: Colors.white,
),
child: Column(children: [
Text(
'head widgets',
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade500,
),
),
Expanded(
child: PageView.builder(
controller: controller,
itemCount: pages.length,
itemBuilder: (context, index) {
if (index == page) {
return Transform.scale(
scale: 1,
child: pages[index],
);
} else if (index < page) {
return Transform.scale(
scale: max(1 - (page - index), 0.75),
child: pages[index],
);
} else {
return Transform.scale(
scale: max(1 - (index - page), 0.75),
child: pages[index],
);
}
},
),
),
Text(
'indicator',
style: TextStyle(fontSize: 12),
)
]),
),
),
);
}
List<Widget> pages = [
FlutterLogo(
size: 100,
),
FlutterLogo(
size: 100,
),
FlutterLogo(
size: 100,
),
];
}
and the result

How to change TabBar indicator color when swiping (Flutter)

Is it possible to change the TabBar indicator programmatically when swiping?
I've tried using a builder to get the index but I haven't had any luck .. I'm sure there must be a way to do this but haven't figured it out yet
Color _indicatorColor(index) {
switch (index) {
case 0:
return Colors.purple;
break;
case 1:
return colorInfoLighter;
break;
case 2:
return Colors.pink;
break;
}
}
Widget _buildScreen() {
var index;
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: TabBar(
onTap: (_) {
setState(() {});
},
indicatorWeight: 4,
indicatorColor: _indicatorColor(index),
tabs: [
_requestedLabel(),
_completedLabel(),
_cancelledLabel(),
]),
body: Container(
child: TabBarView(children: [
_requestedTab(),
_completedTab(),
_cancelledTab(),
]),
),
);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: _buildScreen(),
);
}
Did you mean by changing tabs?
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({
Key key,
}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
final colors = [Colors.purple, Colors.green, Colors.pink];
Color indicatorColor;
TabController _controller;
#override
void initState() {
super.initState();
_controller = TabController(length: 3, vsync: this)
..addListener(() {
setState(() {
indicatorColor = colors[_controller.index];
});
});
indicatorColor = colors[0];
}
Widget _buildScreen() {
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: Container(
color: Colors.blue,
child: TabBar(
labelColor: Colors.black,
controller: _controller,
indicatorWeight: 4,
indicatorColor: indicatorColor,
tabs: [
Tab(
child: Container(
child: Text('A'),
),
),
Tab(
child: Text('B'),
),
Tab(
child: Text('C'),
),
]),
),
body: Container(
child: TabBarView(
controller: _controller,
children: [
Center(
child: Text('aa'),
),
Center(
child: Text('bb'),
),
Center(
child: Text('cc'),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: _buildScreen(),
);
}
}

SliverAppBar() not collapsing with ListView in Flutter

I'm trying to display tabs for each main tab (Nested Tab Bar) in SliverAppBar(). It's look like this:
See the image
See the GIF
The content of the exam tab it's in Container() widget (That the error in the image came from).
Now, with the Container() widget the SliverAppBar() will collapse when the user scroll the exam tab content (white screen in the image), everything is fine for now.
So, After I replaced the Container() with ListView.builder() to make the tab content scrollable, now I can't collapse SliverAppBar() from the tab content (white screen in the image). but I can from the SliverAppBar().
See this GIF after I added ListView.builder()
So, How I can make the SliverAppBar scrollable (collapsing ) with Listview?
Can anyone help me? please :(
This example (demo):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'SliverAppBar App Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: DefaultTabController(
length: 2,
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
child: SliverSafeArea(
top: false,
sliver: SliverAppBar(
pinned: true,
title: Text(widget.title),
expandedHeight: 500,
),
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(tabs: [Tab(text: 'Tab A'), Tab(text: 'Tab B')]),
Colors.blue,
),
pinned: false,
),
];
},
body: TabBarView(
children: <Widget>[
NestedTabs('A'),
NestedTabs('B'),
],
),
),
),
),
);
}
}
// This class is to handle the main tabs (Tab A & Tab B)
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar, this._color);
TabBar _tabBar;
final Color _color;
#override
double get minExtent => _tabBar.preferredSize.height;
#override
double get maxExtent => _tabBar.preferredSize.height;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new Container(
color: _color,
alignment: Alignment.center,
child: _tabBar,
);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return false;
}
}
class NestedTabs extends StatelessWidget {
final String mainTabName;
NestedTabs(this.mainTabName);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(20),
child: Container(
color: Colors.blue,
alignment: Alignment.bottomCenter,
child: TabBar(
tabs: [
Tab(text: 'Tab $mainTabName-1'),
Tab(text: 'Tab $mainTabName-2')
],
),
),
),
body: TabBarView(
children: [
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: 500,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
width: 200,
color: Colors.black45,
child: Center(child: Text('Index ${index}')));
},
),
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: 500,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
width: 200,
color: Colors.black45,
child: Center(child: Text('Index ${index}')));
},
)
],
),
);
}
}
Thank you :)
Use SliverList() instead of SliverFillRemaining for ListView

How to get shuch effect of AppBar title in Flutter?

How I can get such effect of AppBar title, sample:
The big title "Coffee shop" disappears when page scrolls and appears in appBar. Thanks.
probably you need SliverAppBar
You can also check this tutorial
An example based on the article:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MainCollapsingToolbar());
}
}
class MainCollapsingToolbar extends StatefulWidget {
#override
_MainCollapsingToolbarState createState() => _MainCollapsingToolbarState();
}
class _MainCollapsingToolbarState extends State<MainCollapsingToolbar> {
ScrollController _scrollController = ScrollController();
double offset = 0.0;
#override
void initState() {
super.initState();
_scrollController.addListener(() {
setState(() {
offset = _scrollController.offset;
});
});
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 200.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: (offset == 0) ? false : true,
title: Text("Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
labelColor: Colors.black87,
unselectedLabelColor: Colors.grey,
tabs: [
Tab(icon: Icon(Icons.info), text: "Tab 1"),
Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
],
),
),
pinned: true,
),
];
},
body: Center(
child: Text("Sample text"),
),
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);
final TabBar _tabBar;
#override
double get minExtent => _tabBar.preferredSize.height;
#override
double get maxExtent => _tabBar.preferredSize.height;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new Container(
child: _tabBar,
);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return false;
}
}

Disable TabView animation on Tab click event?

How can I disable TabView animation when Tab in TabBar clicked ?
I added
physics: NeverScrollableScrollPhysics()
for TabView but that doesn't apply for TabBar.
I'm using DefaultTabController.
Based on a very good answer on github about this issue, which achieves something similar to what your looking for (but with a bottomNavigationBar) here I share with you another workaround. It consists of combining a DefaultTabController with a PageView, a PageController and a simple index. Try this out.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tabs with no animation',
theme: ThemeData.dark(),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
PageController _pageController;
final int currentTab = 0;
#override
void initState() {
// TODO: implement initState
_pageController = PageController(initialPage: currentTab);
super.initState();
}
final List<Tab> myTabs = <Tab>[
Tab(text: 'One'),
Tab(
text: 'Two',
),
];
var tabs = [
TabOne(),
TabTwo(),
];
#override
Widget build(BuildContext context) {
var pageView = PageView(
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
children: tabs,
);
return DefaultTabController(
length: myTabs.length,
child: Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
automaticallyImplyLeading: false,
title: Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.grey.shade800,
),
width: 200,
height: 50,
child: TabBar(
onTap: (index) {
_pageController.jumpToPage(index);
},
unselectedLabelColor: Colors.white,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black),
tabs: myTabs,
),
),
),
),
body: pageView),
);
}
}
class TabOne extends StatelessWidget {
const TabOne({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text('Tab one')),
);
}
}
class TabTwo extends StatelessWidget {
const TabTwo({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text('Tab two')),
);
}
}
Doing so, you have a something identical to a TabBarView but without animation.
I don't think there's a way to disable the transition animation on TabBarView. As a workaround, you can use a Container that'll return different pages depending on the tab selected.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
tabController = TabController(length: 4, vsync: this);
}
var _homeScaffoldKey = Key("Scaffold Key");
var tabController;
var currentPage = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _homeScaffoldKey,
body: _getCustomContainer(),
bottomNavigationBar: new Material(
color: Colors.blue,
child: new TabBar(
isScrollable: true,
indicatorColor: Color.fromRGBO(255, 25, 255, 0.0),
controller: tabController,
onTap: (value) {
setState(() {
currentPage = value;
});
},
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
],
),
),
);
}
_getCustomContainer() {
switch (currentPage) {
case 0:
return page1();
case 1:
return page2();
case 2:
return page3();
case 3:
return page4();
}
}
page1() => Container(
color: Colors.redAccent,
child: Center(
child: Text("Page 1"),
),
);
page2() => Container(
color: Colors.greenAccent,
child: Center(
child: Text("Page 2"),
),
);
page3() => Container(
color: Colors.blueAccent,
child: Center(
child: Text("Page 3"),
),
);
page4() => Container(
color: Colors.yellowAccent,
child: Center(
child: Text("Page 4"),
),
);
}
Demo
Seems like this can be achieved using DefaultTabController easily as of 2022.
Here is my solution to this:
class _TabPageState extends State<TabPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
// when initializing the `TabController` set `animationDuration` as `zero`.
_tabController =
TabController(length: 3, vsync: this, animationDuration: Duration.zero);
}
#override
Widget build(BuildContext context) {
return Container(
color: ColorPalette.white,
child: SafeArea(
top: false,
child: DefaultTabController(
length: 3,
child: Builder(builder: (context) {
return Scaffold(
bottomNavigationBar: TabBar(
controller: _tabController, // set the tab controller of your `TabBar`
enableFeedback: false,
onTap: (index) {
setState(() {});
},
indicatorColor: Colors.transparent,
tabs: [
TabItem(
selectedIndex: _tabController.index,
index: 0,
assetName: Assets.tabHome),
TabItem(
selectedIndex: _tabController.index,
index: 1,
assetName: Assets.tabCare),
TabItem(
selectedIndex: _tabController.index,
index: 2,
assetName: Assets.tabProfile),
],
),
body: Center(
child: TabBarView(
controller: _tabController, // set the controller of your `TabBarView`
physics: const NeverScrollableScrollPhysics(),
children: const [
ParentHomePage(),
ParentCarePage(),
ParentAccountPage()
],
),
),
);
}),
),
),
);
}
}
You Can Fix It by Go to MaterialApp and type
theme:new ThemeData(
splashColor:Colors.blue,
highlightColor: Colors.blue
)
what it mean if your tab background color blue you will change splashColor and highlightColor to blue that mean the animation doesn't disabled but it doesn't appear because the animation splashcolor and highlight will be blue such as Tab Background , I Hope I Help You