Flutter - TextField focus changes TabBar selected index - flutter

I have a Scaffold, within it I have a TabBar, TabBarView and a TextField.
The TabBar has 3 tabs (e.g. tabs A, B and C), the TabBarView has 3 views and this TextField is at the last tab (tab C).
Everything is working, but whenever I put the focus on the TextField to type something, the TabBar is changed from tab C to tab A. Very annoying. This should not happen. The TabBarView remains unchanged.
I created the controller in the initState. like this:
#override
void initState() {
super.initState();
widget._tabBarController =
new TabController(length: 3, vsync: this);
}
Any idea why it happens?
Code:
class AtendimentoOrtoWidget extends StatefulWidget {
TabController _tabBarController;
#override
_AtendimentoOrtoWidgetState createState() => _AtendimentoOrtoWidgetState();
}
class _AtendimentoOrtoWidgetState extends State<AtendimentoOrtoWidget>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
widget._tabBarController =
new TabController(length: 3, vsync: this);
}
#override
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: new DefaultTabController(
length: 3,
child: new Scaffold(
resizeToAvoidBottomPadding: false,
appBar: new AppBar(
toolbarOpacity: 0.5,
automaticallyImplyLeading: true,
backgroundColor: Colors.white,
elevation: 2.0,
title: new TabBar(
controller: widget._tabBarController,
unselectedLabelColor: Colors.black,
indicatorColor: Colors.black,
labelColor: Colors.black,
// indicatorWeight: 0.0,
isScrollable: true,
labelStyle: new TextStyle(
fontSize: 16.0,
fontFamily: 'Caecilia',
fontWeight: FontWeight.w700),
tabs: <Widget>[
new Tab(
text: "TAB A",
),
new Tab(
text: "TAB B",
),
new Tab(
text: "TAB C",
)
],
),
),
backgroundColor: Colors.white,
body: new TabBarView(
controller: widget._tabBarController,
children: <Widget>[
new Container(),
new Container(),
new TextField()
],
))));
}
}

I tried it. Check the below code. If you still facing the same issue then share your implementation.
import 'package:flutter/material.dart';
class TabScreen extends StatefulWidget {
#override
_TabScreenState createState() => _TabScreenState();
}
class _TabScreenState extends State<TabScreen> with SingleTickerProviderStateMixin {
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalObjectKey<ScaffoldState>('TabScreen');
TabController tabController;
#override
void initState() {
super.initState();
tabController = new TabController(length: 3, vsync: this);
}
#override
void dispose() {
super.dispose();
tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Tab Demo"),
),
backgroundColor: Colors.white,
body: Column(
children: <Widget>[
TabBar(
controller: tabController,
tabs: <Widget>[
Tab(
child: Container(
child: new Text(
'A',
style: TextStyle(color: Colors.black),
),
),
),
Tab(
child: Container(
child: Text(
'B',
style: TextStyle(color: Colors.black),
),
),
),
Tab(
child: Container(
child: Text(
'C',
style: TextStyle(color: Colors.black),
),
),
)
],
),
Flexible(
child: TabBarView(
controller: tabController,
children: <Widget>[
Placeholder(),
Placeholder(),
ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(labelText: "Name"),
),
),
],
),
],
))
],
),
);
}
}

Related

Tab Bar Tab width customize | Flutter?

Default the Tabar Tab width are equal.
How i can change each tabbar tab width differently ?
I tried this but not work
TabBar(
controller: _navController,
tabs: [
Expanded(
flex: 30,
child: IconButton(
icon: SvgPicture.asset("assets/svg/home.svg",height: height * .02,),
onPressed: () { },
)),
Expanded(
flex: 40,
child: Center(
child: IconButton(
icon: SvgPicture.asset("assets/svg/user.svg",height: height * .02,),
onPressed: () { },
),
)),
Expanded(
flex: 20,
child: Center(
child: IconButton(
icon: SvgPicture.asset("assets/svg/settings.svg",height: height * .02,),
onPressed: () { },
),
)),
Expanded(
flex: 10,
child: Container()),
],
),
Expecting Result
To have different sizes in tab bar you have to add isScrollable: true. Please try this example
class MyTabbedPage extends StatefulWidget {
const MyTabbedPage({Key? key}) : super(key: key);
#override
State<MyTabbedPage> createState() => _MyTabbedPageState();
}
class _MyTabbedPageState extends State<MyTabbedPage>
with SingleTickerProviderStateMixin {
List<Widget> myTabs = [
SizedBox(
width: 20.0,
child: Tab(text: 'hello'),
),
SizedBox(
width: 70,
child: Tab(text: 'world'),
),
];
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: myTabs.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: myTabs,
isScrollable: true,
),
),
body: TabBarView(
controller: _tabController,
children: myTabs.map((Widget tab) {
final String label = "Test";
return Center(
child: Text(
'This is the $label tab',
style: const TextStyle(fontSize: 36),
),
);
}).toList(),
),
);
}
}

How to use multiple tab for single page in Flutter

I create Tab Bar for my project. It includes two tabs and these each tabs are represent two pages.
Here is the code
import 'package:flutter/material.dart';
class TabView extends StatefulWidget {
#override
_TabViewState createState() => _TabViewState();
}
class _TabViewState extends State<TabView> with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade300,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(
16.0,
),
),
child: TabBar(
controller: _tabController,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(
16.0,
),
color: Colors.grey.shade900,
),
labelColor: Colors.white,
unselectedLabelColor: Colors.grey.shade900,
tabs: [
Tab(
text: 'One',
),
Tab(
text: 'Two',
),
],
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
Center(
child: Text(
'Page One',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
),
Center(
child: Text(
'Page Two',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
],
),
),
),
);
}
}
Here is output
I want to use the tab bar for a single page to change a widget state.
Example
I want use the tab bar to change the color of the container in page one from red to blue and I don't want to switch to page two
How can I do it?
TabBar is not quite suitable for this purpose, although it can be adapted. I suggest you to use CupertinoSegmentedControl from cupertino package. Here is docs, and here is code example:
enum _Tab { one, two }
class MyWidget extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
_Tab _selectedTab = _Tab.one;
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: 16),
CupertinoSegmentedControl<_Tab>(
selectedColor: Colors.black,
borderColor: Colors.black,
pressedColor: Colors.grey,
children: {
_Tab.one: Text('One'),
_Tab.two: Text('Two'),
},
onValueChanged: (value) {
setState(() {
_selectedTab = value;
});
},
groupValue: _selectedTab,
),
SizedBox(height: 64),
Builder(
builder: (context) {
switch (_selectedTab) {
case _Tab.one:
return Center(
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
);
case _Tab.two:
return Center(
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
}
},
),
],
);
}
}
Also take a look at CupertinoSlidingSegmentedControl.
for your requirement don't use TabBarView at all, directly use container, change it's color value as per selectedtab index
class Tabscreenstate extends State<Tabscreen> with TickerProviderStateMixin {
int selectedTabIndex = 0;
TabController tabController;
#override
void initState() {
tabController = TabController(length: 2, vsync: this);
tabController.addListener(() {
setState(() {
selectedTabIndex = tabController.index;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
tabbar(),
Container(color:selectedTabIndex == 0 ? Colors.red : Colors.green),
],
);
}
Widget tabbar() => TabBar(
controller: tabController,
onTap: (value) {
setState(() {
selectedTabIndex = value;
});
},
tabs: [
Text("tab one"),
Text("tab two"),
],
);
}

Flutter how to create clickable tabs

How to create basic design like from sketch from image. First container with list of tabs is static, and containers above it is dynamic, and contain text - Text for tab 1 if tab 1 is clicked, or Text for tab 2 if tab 2 is clicked. Also text for Tab1 or Tab2 must be underline if we click on it.
Something like this:
Using a GestureDetector widget to tell when a user taps on the tabs and then updating the state with setState is maybe the most simple way of doing this.
Here is a very basic example of using a stateful widget and setState to update the page. You can approach this problem with any state management strategy, though.
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: Scaffold(body: MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String selectedTab;
static const String TAB_1 = 'Tab 1';
static const String TAB_2 = 'Tab 2';
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
setState(() => selectedTab = TAB_1);
},
child: Container(
padding: const EdgeInsets.all(12.0),
child: Text(TAB_1),
decoration: selectedTab == TAB_1
? BoxDecoration(border: Border(bottom: BorderSide()))
: null,
),
),
GestureDetector(
onTap: () {
setState(() => selectedTab = TAB_2);
},
child: Container(
padding: const EdgeInsets.all(12.0),
child: Text(TAB_2),
decoration: selectedTab == TAB_2
? BoxDecoration(border: Border(bottom: BorderSide()))
: null,
),
)
],
),
),
Container(height: 20.0),
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 5),
borderRadius: BorderRadius.circular(12.0)),
child: Center(child: Text(textForTab(selectedTab))),
),
)
],
);
}
String textForTab(String tabId) {
switch (tabId) {
case TAB_1:
return 'Text for Tab 1';
case TAB_2:
return 'Text for Tab 2';
default:
return 'Select Tab';
}
}
}
You can do it using TabBar widget.
class CustomTabBar extends StatefulWidget {
#override
_CustomTabBarState createState() => _CustomTabBarState();
}
class _CustomTabBarState extends State<CustomTabBar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Tab Demo',
),
),
body:
Column(
children: [
Container(
height: 45,
child: TabBar(
controller: _tabController,
indicator: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.blue,width: 2,style:
BorderStyle.solid)),
),
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
tabs: [
// first tab
Tab(
text: 'Home',
),
// second tab
Tab(
text: 'Profile',
),
],
),
),
// tab bar view
Expanded(
child: TabBarView(
controller: _tabController,
children: [
// first tab widget
Center(
child: Text(
'Home',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
// Second tab widget
Center(
child: Text(
'Profile',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
],
),
);
}
}
I'm not sure I understand you completely.
But if you want to implement a TabBar, you can use flutter TabBar() documented here:
https://flutter.dev/docs/cookbook/design/tabs
Or there is a package you can use:
https://pub.dev/packages/tabbar

how to add tabbar without appbar in flutter

i have tried to recreate this design but failed to add TabBar and TabBarView below image inside the body .
Try this
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo>
with TickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = new TabController(length: 2, vsync: this);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Column(
children: <Widget>[
Image.asset("path"),
Container(child:
Column(
children: <Widget>[
Container(
height: 60,
margin: EdgeInsets.only(left: 60),
child: TabBar(
tabs: [
Container(
width: 70.0,
child: new Text(
'Tab1',
style: TextStyle(fontSize: 20),
),
),
Container(
width: 75.0,
child: new Text(
'Tab2',
style: TextStyle(fontSize: 20),
),
)
],
unselectedLabelColor: const Color(0xffacb3bf),
indicatorColor: Color(0xFFffac81),
labelColor: Colors.black,
indicatorSize: TabBarIndicatorSize.tab,
indicatorWeight: 3.0,
indicatorPadding: EdgeInsets.all(10),
isScrollable: false,
controller: _tabController,
),
),
Container(
height: 100,
child: TabBarView(
controller: _tabController,
children: <Widget>[
Container(
child: Text("login"),
),
Container(
child: Text("sign up"),
)
]),
))
],
),
],
)
);
}
You can easily create TabBar without AppBar. Just use Container as parent.
please check this.
Expanded(
child: DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new PreferredSize(
preferredSize:
Size.fromHeight(MediaQuery.of(context).size.height),
child: new Container(
height: 50.0,
child: new TabBar(
labelColor: Colors.black,
isScrollable: true,
tabs: [
Tab(
text: "Tab 1",
),
Tab(
text: "Tab 2",
),
Tab(
text: "Tab 3",
),
],
),
),
),
body: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
),
)
I've put on a simple example, have a look and see if it can help you:
First define a Statefull widget and add some definition regarding your tab
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
Define the state for your widget
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
TabController _tabController;
final List<Tab> tabs = [
Tab(
///Give keys so you can make it easier to retrieve content to display, if you have to read the data from a remote resource ...
key: ObjectKey(1),
text: 'Products',
),
Tab(
key: ObjectKey(2),
text: 'Feature',
),
Tab(
key: ObjectKey(3),
text: 'Shipping Info',
),
Tab(
key: ObjectKey(4),
text: 'Reviews',
),
];
///Build the widget for each tab ...
Widget _setDisplayContainer(key) {
if (key == ObjectKey(1)) {
return Text("Content for tab 1");
} else if (key == ObjectKey(2)) {
return Text("Content for tab 2");
} else if (key == ObjectKey(3)) {
return Text("Content for tab 3");
}
return Text("Content for tab 4");
}
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: tabs.length);
}
...
}
After this your build method should look something like this
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height * .4),
child: SafeArea(
child: Column(
children: <Widget>[
Container(
child: Expanded(
flex: 4,
child: Stack(fit: StackFit.loose, children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/car.jpeg'),
fit: BoxFit.cover,
)),
),
Container(
height: 40,
color: Colors.orangeAccent,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.arrow_back,
color: Colors.white, size: 20),
Row(
children: <Widget>[
Icon(
Icons.search,
color: Colors.white,
size: 20,
),
Icon(Icons.menu, color: Colors.white, size: 20),
],
)
],
),
),
]),
),
),
Container(
child: TabBar(
unselectedLabelColor: const Color(0xffacb3bf),
indicatorColor: Color(0xFFffac81),
labelColor: Colors.black,
indicatorSize: TabBarIndicatorSize.tab,
indicatorWeight: 3.0,
indicatorPadding: EdgeInsets.all(10),
tabs: tabs,
controller: _tabController,
labelStyle: TextStyle(color: Colors.orangeAccent, fontSize: 12),
onTap: (index) {},
),
),
],
),
),
),
body: TabBarView(
controller: _tabController,
children:
tabs.map((tab) => _setDisplayContainer(tab.key)).toList()));
}
Hope this helps.

Set elevation under AppBar and under TabBarView

I have two tab. I want elevation bottom of Appbar and elevation bottom of TabBarView. How can I do this?
Here is my Code,
class MyOrder extends StatefulWidget {
#override
_MyOrderState createState() => _MyOrderState();
}
class _MyOrderState extends State<MyOrder> with SingleTickerProviderStateMixin{
var strTitle = Translations.globalTranslations.myOrders;
TabController _tabController;
#override
void initState() {
_tabController = new TabController(length: 2, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
elevation: 1.0,
leading: new IconButton(
icon: Image.asset('images/keyboard_backspace.png', width: 24.0, height: 24.0,),
onPressed: () => Navigator.of(context).pop(),
),
title: Text(strTitle,textAlign: TextAlign.left , style: UIUtills().getTextStyle(
fontName: AppFontName.appFontSemiBold,
fontsize: 20,
color: AppColor.redColor),),
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: AppColor.redColor),
bottom: TabBar(
indicatorColor: AppColor.redColor,
labelColor: AppColor.blackColor,
labelStyle: UIUtills().getTextStyle(
fontName: AppFontName.appFontSemiBold,
fontsize: 16,
color: AppColor.blackColor),
tabs: [
new Tab(text:Translations.globalTranslations.pastOrder),
new Tab(text: Translations.globalTranslations.upComing)
],
controller: _tabController,
indicatorSize: TabBarIndicatorSize.tab),
),
body: TabBarView(
children: [
PastOrder(),
UpComingOrder(),
],
controller: _tabController,),
);
}
}
As per my code layout looks like,
https://i.stack.imgur.com/D9BND.png
I want to design my layout like this,
https://i.stack.imgur.com/tPv8A.png
Try this one
ScreenShot https://imgur.com/Fz95DEr
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 8.0, // top bar
leading: InkWell(
onTap: () {},
child: Icon(
Icons.keyboard_arrow_left,
color: Colors.red,
),
),
backgroundColor: Colors.white,
title: Text(
"My Order",
style: TextStyle(color: Colors.red),
),
),
body: Scaffold(
body: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
elevation: 8.0, // bottom bar
bottom: PreferredSize(
child: TabBar(
labelColor: Colors.black,
indicatorColor: Colors.red,
tabs: <Widget>[
Tab(
text: "Past Order",
),
Tab(
text: "Upcoming",
),
],
),
preferredSize: Size.fromHeight(0.0),
),
backgroundColor: Colors.white,
),
body: TabBarView(
children: <Widget>[
Container(
color: Colors.white,
child: Center(
child: Text("Past Order"),
),
),
Container(
color: Colors.white,
child: Center(
child: Text("Upcoming"),
),
),
],
),
),
),
),
);
}
}