How to make Flutter animation like this? - flutter

Any code example is welcome, thanks!

TabBar does this animation by default...
You can look at its source code from the IDE or here to see how it's done.
This page has documentation, video, and examples if you want to use it directly in your app.

Here is the code sample.
You can use TabBar widget.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this, initialIndex: 0);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text("Demo"),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
tabs: [
Tab(
text: "Wellbeing",
),
Tab(
text: "Cleaning",
),
Tab(
text: "Self-care",
),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
Center(child: Text("Wellbeing")),
Center(child: Text("Cleaning")),
Center(child: Text("Self-care")),
],
),
);
}
}

Related

How to use tabBar controller in flutter?

import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:whatsapp_clone/chatScreen.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin{
late TabController _tabcontroller;
#override
void initState(){
super.initState();
_tabcontroller=TabController(length: 4, vsync: this, initialIndex: 1);
}
#override
void dispose(){
_tabcontroller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff075E54),
title: const Text('Whatsapp Clone'),
actions: [IconButton(onPressed: (){}, icon: const Icon(Icons.search)),
PopupMenuButton(onSelected: (value){print(value);},
itemBuilder: (BuildContext context){return [
PopupMenuItem(child: Text('New Group'),value: 'New Group'),
PopupMenuItem(child: Text('New Broadcast'),value: 'New Broadcast'),
PopupMenuItem(child: Text('Whatsapp web'),value: 'Whatsapp web'),
PopupMenuItem(child: Text('Starred messages'),value: 'Starred messages'),
PopupMenuItem(child: Text('Settings'),value: 'Settings')
];
}
),
],
bottom: TabBar(
controller: _tabcontroller,
tabs: const [
Tab(icon: Icon(Icons.camera_alt)),
Tab(text:'CHAT'),
Tab(text: 'STATUS'),
Tab(text: 'CALLS')
],
indicatorColor: Colors.white,
),
),
body: TabBarView(controller: _tabcontroller,
children: const [
Text('camera'),
ChatPage(),
Text('status'),
Text('calls')
],
),
);
}
}
I want to show the chatscreen which is at 1 index, when opening the app, and i have given the initial index to 1 also, but whenever i open my app, although the chat tabbar was selected but the content was showing from first screen. how can i solve this problem

Bottom navigation bar item underline selected icon

in-app bottom bar I want to add an underline for specifically selected icon. Is there any way for BottomNavigationBarItem or do I need to use a different widget?
class CustomAppBottomBar extends StatefulWidget {
const CustomAppBottomBar({Key? key}) : super(key: key);
#override
State<CustomAppBottomBar> createState() => _CustomAppBottomBarState();
}
class _CustomAppBottomBarState extends State<CustomAppBottomBar> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
showUnselectedLabels: true,
showSelectedLabels: true,
type: BottomNavigationBarType.fixed,
selectedItemColor: RJDriverColors.primary,
unselectedItemColor: RJDriverColors.bottomBarSecondary,
selectedFontSize: 12,
unselectedFontSize: 12,
currentIndex: _currentIndex,
onTap: (value) {
setState(() {
_currentIndex = value;
});
},
Try using 'TabBar' and use onTap as onChanged since they are both of type ValueChanged<int>
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late final TabController controller;
#override
void initState() {
controller = TabController(length: 4, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
bottomNavigationBar: TabBar(
controller: controller,
unselectedLabelColor: Colors.grey,
labelColor: Colors.blue,
onTap: (index) {},
tabs: const [
Tab(icon: Icon(Icons.menu_rounded)),
Tab(icon: Icon(Icons.piano)),
Tab(icon: Icon(Icons.car_rental_rounded)),
Tab(icon: Icon(Icons.settings_rounded)),
],
),
);
}
}
Using Tabbar with DefaultTabController you can get your desired result. I'm sharing a reference code you can customize it as per your need.
return DefaultTabController(
length: 4,
child: Scaffold(
body: TabBarView(
children: [
Center(
child: Text("1st Screen"),
),
Center(
child: Text("2nd Screen"),
),
Center(
child: Text("3rd Screen"),
),
Center(
child: Text("4th Screen"),
),
],
),
bottomNavigationBar: TabBar(
labelColor: Colors.red,
tabs: [
Tab(child: Icon(Icons.more_vert_sharp),),
Tab(child: Icon(Icons.local_play_sharp),),
Tab(child: Icon(Icons.directions_car),),
Tab(child: Icon(Icons.home),),
]),
),
);

flutter, RenderBox was not laid out: RenderRepaintBoundary#4de33 relayoutBoundary=up14 NEEDS-PAINT

I use tabBar,
I want to change appBar title when a tab is selected, but I get a error.
code that I get error.
Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.clear, color: Colors.black),
onPressed: () {
Navigator.pop(context);
},
),
title: TabBarView(
children: [Text("Album"), Text("사진"), Text("동영상")],
),
backgroundColor: Colors.white,
),
bottomNavigationBar: TabBar(
tabs: [
Tab(text: "앨범"),
Tab(text: "사진"),
Tab(text: "동영상"),
],
labelColor: Colors.black,
indicatorColor: Colors.black,
unselectedLabelColor: Colors.black26,
),
),
If I get rid of appBar title, I don't get error.
How to solve this problem?
You can add TabController and add a listener so that whenever you are switching the Tab, the setState() kicks in and the appBar title change.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
TabController _controller;
final List<Tab> _tab = [new Tab(text: "First",), Tab(text: "Second",), Tab(text: "Third",)];
var _currentTab;
#override
void initState() {
// TODO: implement initState
super.initState();
_controller = new TabController(length: _tab.length, vsync: this);
_currentTab = _tab[0];
_controller.addListener(_selectedTab);
}
void _selectedTab() {
setState(() {
_currentTab = _tab[_controller.index];
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Text(_currentTab.text),
),
bottomNavigationBar: TabBar(controller: _controller,tabs: _tab),
);
}
}

Dynamic number of tabs

I have design like above , my tabbar is inside BottomNavigationBar and i want place the tabbar in my BottomNavigationBar menu. The problem is , i don't want have nested scaffold and i don't want use TabController because my tabs is dynamic , tabs length can be decrease or increase depending of user adding it. If i use TabController and define it inside initState , the tabs can't be increase/decrease because in initState only once define the value.
How can i do this ?
My expectation similiar in below example , when i adding tab and tabMenu it will increase . But get this error
The following assertion was thrown building TabBar(dirty, dependencies: [_InheritedTheme,
_LocalizationsScope-[GlobalKey#a56a4]], state: _TabBarState#fb337):
Controller's length property (2) does not match the number of tabs (3) present in TabBar's tabs
property.
The relevant error-causing widget was:
TabBar
Dummy Example
class TaskScreen extends StatefulWidget {
#override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with SingleTickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
#override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(Tab(
text: '1',
));
_tabMenu.add(Text('1'));
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: colorPallete.primaryColor,
padding: EdgeInsets.only(top: sizes.statusBarHeight(context)),
child: TabBar(
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}
use TickerProviderStateMixin instead of SingleTickerProviderStateMixin
and change TabController on changing tabs number;
add isScrollable: true when you don't have space for all your tabs
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: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return TaskScreen();
}
}
class TaskScreen extends StatefulWidget {
#override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with TickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
#override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(
Tab(
text: '1',
),
);
_tabMenu.add(
Text('1'),
);
_tabController =
TabController(length: _tab.length, vsync: this);
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: Colors.blue,
padding: EdgeInsets.only(top: 10),
child: TabBar(
// isScrollable: true,
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}

How, using Flutter, to create a widget that includes a TabBar and a (Custom) BarWidget?

Can find many examples of how to create a tabbed Flutter application using the AppBar. Everything is clear here. But how to add TabBar and (CustomX) BarWidget to widget (Custom) BarWidget? Those. create widget "tab inside tab", pictured below:
I can add a TabBar to the widget, but I don't know how add (CustomX) BarWidget:
The code:
class ElementTabbedPage extends StatefulWidget {
//ElementTabbedPage({Key key}) : super(key: key);
IGUIBridge _element;
ElementTabbedPage(this._element);
#override
_ElementTabbedPageState createState() => _ElementTabbedPageState();
}
class _ElementTabbedPageState extends State<ElementTabbedPage> with TickerProviderStateMixin {
List<String> _tabsContainer = ['P1', 'P2', 'P3'];
TabController _tabController;
#override
void initState() {
super.initState();
_tabController =
new TabController(vsync: this, length: _tabsContainer.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget build(context) {
print ('_ElementTabbedPageState.build->${widget._element.name()}');
return
Container(
child: Column(
children: <Widget>[
TabBar(
controller: _tabController,
isScrollable: true,
tabs: _tabsContainer
.map((x) => Container(
width: 60.0,
child: Tab(text: x,
//icon: Icon(Icons.favorite),
),
)).toList(),
),
//PanelBarWidget(tabController: _tabController, tabsContainer: _tabsContainer),
]
)
);
}
}
class PanelBarWidget extends StatefulWidget {
const PanelBarWidget({
Key key,
#required TabController tabController,
#required List<String> tabsContainer,
})
: _tabController = tabController,
_tabsContainer = tabsContainer,
super(key: key);
#override
_PanelBarWidgetState createState() => new _PanelBarWidgetState();
final TabController _tabController;
final List<String> _tabsContainer;
}
class _PanelBarWidgetState extends State<PanelBarWidget> {
#override
Widget build(BuildContext context) {
return new TabBarView(
controller: widget._tabController,
children: widget._tabsContainer.map(createView).toList());
}
Container createView(x) {
List<String> list = ["A 11", "A 12", "A 13"];
return Container(child:
Text(x),
);
}
}
The problem can be solved as follows:
import 'package:flutter/material.dart';
import 'dart:async';
import '../manageables/IManageable.dart';
import '../singletons/GuiAdapter.dart';
import '../bridge/IGUIBridge.dart';
class ElementTabbedPage extends StatefulWidget {
//ElementTabbedPage({Key key}) : super(key: key);
IGUIBridge _element;
ElementTabbedPage(this._element);
#override
_ElementTabbedPageState createState() => _ElementTabbedPageState();
}
class _ElementTabbedPageState extends State<ElementTabbedPage>
with TickerProviderStateMixin {
List<String> _tabsContainer = ['P1', 'P2', 'P3'];
TabController _tabController;
#override
void initState() {
super.initState();
_tabController =
new TabController(vsync: this, length: _tabsContainer.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget build(context) {
print('_ElementTabbedPageState.build->${widget._element.name()}');
return Column(children: <Widget>[
TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.black38,
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(8), color: Colors.black38),
tabs: _tabsContainer
.map((x) => Container(
width: 60.0,
child: Tab(
text: x,
//icon: Icon(Icons.favorite),
),
))
.toList(),
),
Container(
child: Expanded(
child: PanelBarWidget(
tabController: _tabController, tabsContainer: _tabsContainer),
),
)
]);
}
}
class PanelBarWidget extends StatefulWidget {
const PanelBarWidget({
Key key,
#required TabController tabController,
#required List<String> tabsContainer,
}) : _tabController = tabController,
_tabsContainer = tabsContainer,
super(key: key);
#override
_PanelBarWidgetState createState() => new _PanelBarWidgetState();
final TabController _tabController;
final List<String> _tabsContainer;
}
class _PanelBarWidgetState extends State<PanelBarWidget> {
#override
Widget build(BuildContext context) {
return new TabBarView(
controller: widget._tabController,
children: widget._tabsContainer.map(createView).toList());
}
Container createView(x) {
return Container(
color: Colors.lightGreen,
child: Center(
child: Text(x),
),
);
}
}
But maybe can exists a different solution?