Related
I'm beginner in flutter and programming, want To set counter that count images number when it scroll down and also tell remaining pages instead of hardcoded text('1/6'). here it's code
int counter=0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Center(
child: Text('Surah Yaseen' ' (1/6) ', style: TextStyle(fontSize: 30.0),
),
),
),
body: PageView(
scrollDirection: Axis.vertical,
allowImplicitScrolling: true,
children: [
Container(
child: Image.asset('images/1.jpg'),
),
Container(
child: Image.asset('images/2.jpg'),
),
Container(
child: Image.asset('images/3.jpg'),
),
Container(
child: Image.asset('images/4.jpg'),
),
Container(
child: Image.asset('images/5.jpg'),
),
Container(
child: Image.asset('images/6.jpg'),
)
],
),
);
}
}
Try this:
final controller = PageController(
initialPage: 0,
);
final _currentPageNotifier = ValueNotifier<int>(0);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Center(
child: Text('Surah Yaseen' ' (${_currentPageNotifier.value}/6) ', style: TextStyle(fontSize: 30.0),
),
),
),
body: PageView(
scrollDirection: Axis.vertical,
allowImplicitScrolling: true,
onPageChanged: (index) {
setState(() {
_currentPageNotifier.value = index+1;
});
},
controller: controller,
children: [
Container(
child: Image.asset('images/1.jpg'),
),
Container(
child: Image.asset('images/2.jpg'),
),
Container(
child: Image.asset('images/3.jpg'),
),
Container(
child: Image.asset('images/4.jpg'),
),
Container(
child: Image.asset('images/5.jpg'),
),
Container(
child: Image.asset('images/6.jpg'),
)
],
),
);
}
Like the title, i have created a button with Navigator.push() into a new page, the page auto generates a back button on the appBar, i appreciated that autogenerated back button but i want the back button to not displace my title's positioning, is that possible?
Below is my code for the button to enter this page:
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FeedTest();
},
),
);
This is my full code for the new page:
Widget build(BuildContext context) {
return ScrollConfiguration(
behavior: MyBehavior(),
child: SafeArea(
child: DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.grey[850],
title: Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'images/logo2.png',
isAntiAlias: true,
scale: 1.8,
fit: BoxFit.fitHeight,
alignment: Alignment.center,
)
]),
bottom: TabBar(
indicatorColor: Colors.white,
tabs: [
Tab(
text: 'Submit Feedback',
),
Tab(
text: 'Submit Testimony',
)
],
),
),
body: TabBarView(
children: [SubmitFeedback(), SubmitTestimony()],
),
),
),
),
);
}
P.S. Title image has been blurred for privacy purposes
centerTitle: true is used to make the title center in AppBar
AppBar(
centerTitle: true,
...
)
Output:
Use centerTitle: true like below.
AppBar(
centerTitle: true, // this is all you need
//Rest Code here
)
I upload the full code like below.
Widget build(BuildContext context) {
return ScrollConfiguration(
behavior: MyBehavior(),
child: SafeArea(
child: DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
centerTitle: true,
elevation: 0,
backgroundColor: Colors.grey[850],
title: Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'images/logo2.png',
isAntiAlias: true,
scale: 1.8,
fit: BoxFit.fitHeight,
alignment: Alignment.center,
)
]),
bottom: TabBar(
indicatorColor: Colors.white,
tabs: [
Tab(
text: 'Submit Feedback',
),
Tab(
text: 'Submit Testimony',
)
],
),
),
body: TabBarView(
children: [SubmitFeedback(), SubmitTestimony()],
),
),
),
),
);
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Viewer',
theme:
ThemeData(primaryColor: Colors.cyan, accentColor: Colors.tealAccent),
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: PreferredSize(
child: Container(
margin: EdgeInsets.fromLTRB(100, 0, 0, 0),
child: Row(
children: <Widget>[
//Icon(Icons.settings)
Text('Blah'),
TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.file_download)),
Tab(icon: Icon(Icons.settings))
],
),
],
),
),
preferredSize: Size.fromHeight(-8),
),
),
body: TabBarView(
children: [
Icon(Icons.search),
Icon(Icons.file_download),
Icon(Icons.settings),
],
),
),
),
);
}
}
I want to place the text on the blah part visible in the image.
Either way, I want to put a text in the left part of the tabbar.
I tried using row, but an overflow error occurred.
This occurred an error message.
How can I enter the text in that space?
Here is the code which will work for you
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hitomi Viewer',
theme:
ThemeData(primaryColor: Colors.cyan, accentColor: Colors.tealAccent),
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(-8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20),
child: Center(child: Text('Title'))),
SizedBox(
width: 50,
),
Flexible(
child: TabBar(
tabs: [
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.file_download)),
Tab(icon: Icon(Icons.settings)),
],
),
),
],
),
)),
body: TabBarView(
children: [
Icon(Icons.search),
Icon(Icons.file_download),
Icon(Icons.settings),
],
),
),
),
);
}
}
OutPut:
I fixed it by fixing the code as follows:
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hitomi Viewer',
theme:
ThemeData(primaryColor: Colors.cyan, accentColor: Colors.tealAccent),
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: PreferredSize(
child: Container(
margin: EdgeInsets.fromLTRB(100, 0, 0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
child: InkWell(
child: Text('Blah'),
),
margin: EdgeInsets.fromLTRB(10, 0, 80, 0),
),
TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.file_download)),
Tab(icon: Icon(Icons.settings))
],
),
),
],
),
),
preferredSize: Size.fromHeight(-8),
),
),
body: TabBarView(
children: [
Icon(Icons.search),
Icon(Icons.file_download),
Icon(Icons.settings),
],
),
),
),
);
}
}
Since your tabs property is takinig a List<Widget>, use the Text widget in the tabs property instead.
Check the code below:
TabBar(
tabs: <Widget>[
// put your text widget here
Text('Blah'),
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.file_download)),
Tab(icon: Icon(Icons.settings))
],
),
I'm want to display a tabbar as it is used with the appbar, but in the middle of the scaffold body. Is it possible?
I have this code, but the TabBarView breaks the ui. If I comment the TabBarView, the TabBars are displayed correctly. What is wrong with the code? In case it's possible to use it this way..
#override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
Text('Some other random content'),
TabBar(
controller: _tabController,
isScrollable: true,
tabs: <Widget>[
Tab(
child: Text(
'Posts',
style: TextStyle(
fontSize: 18.0,
color: Colors.black87,
),
),
),
Tab(
child: Text(
'Fotos',
style: TextStyle(
fontSize: 18.0,
color: Colors.black87,
),
),
),
],
),
TabBarView(
controller: _tabController,
children: <Widget>[
Center(
child: Text("User"),
),
Center(
child: Text("Email"),
),
],
),
],
),
);
}
Just Change ListView to Column and add SingleChildScrollView
SingleChildScrollView(
child: Column(
children: <Widget>[]
),
)
Hey i guess it's already too late but maybe it helps others.
If you just want to have your tabbar e.g. in the middle of the screen to divide your screen in 2 sections (top: content, bottom: tabbar) you can place your scaffold inside a column, e.g. following:
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
flex: 1,
child: Center(
child: Text("Header"),
),
),
Expanded(
flex: 1,
child: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
flexibleSpace: TabBar(
tabs: [
Tab(text: "First"),
Tab(text: "Second"),
Tab(text: "Third"),
],
),
),
body: TabBarView(
children: [
Center(child: Text("First screen")),
Center(child: Text("Second screen")),
Center(child: Text("Third screen")),
],
),
),
),
),
],
);
}
Let me know if this fits your needs / if you need further help :-)
the flutter document show a demo for SliverAppBar + TabBar + TabBarView with ListView use NestedScrollView, and it's a bit complex, so I wonder is there a simply and clear way to implement it. I tried this:
CustomScrollView
slivers:
SliverAPPBar
bottom: TabBar
TabBarView
children: MyWidget(list or plain widget)
got error:
flutter: The following assertion was thrown building Scrollable(axisDirection: right, physics:
flutter: A RenderViewport expected a child of type RenderSliver but received a child of type _RenderExcludableScrollSemantics.
flutter: RenderObjects expect specific types of children because they coordinate with their children during layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a RenderSliver does not understand the RenderBox layout protocol.
and
flutter: Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3497 pos 14: 'owner._debugCurrentBuildTarget == this': is not true.
HERE IS MY CODE:
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyScrollTabListApp());
}
class MyScrollTabListApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(title: "aa", home: MyScrollTabListHomePage());
}
}
class MyScrollTabListHomePage extends StatefulWidget {
#override
MyScrollTabListHomePageState createState() {
return new MyScrollTabListHomePageState();
}
}
class MyScrollTabListHomePageState extends State<MyScrollTabListHomePage>
with SingleTickerProviderStateMixin {
final int _listItemCount = 300;
final int _tabCount = 8;
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: _tabCount, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 240.0,
title: Text("Title"),
pinned: true,
bottom: TabBar(
controller: _tabController,
isScrollable: true,
tabs: List<Tab>.generate(_tabCount, (int i) {
return Tab(text: "TAB$i");
}),
),
),
TabBarView(
controller: _tabController,
children: List<Widget>.generate(_tabCount, (int i) {
return Text('line $i');
}),
),
],
),
);
}
}
and for the official demo, it use struct like this
DefaultTabController
NestedScrollView
headerSliverBuilder
SliverOverlapAbsorber
handle
SliverAppBar
TabBarView
CustomScrollView
SliverOverlapInjector
handle
SliverPadding
Use NestedScrollView, here is the working code.
#override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverAppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.call), text: "Call"),
Tab(icon: Icon(Icons.message), text: "Message"),
],
),
),
];
},
body: TabBarView(
children: [
CallPage(),
MessagePage(),
],
),
),
),
);
}
Here is an example for TabView with SilverAppBar
class SilverAppBarWithTabBarScreen extends StatefulWidget {
#override
_SilverAppBarWithTabBarState createState() => _SilverAppBarWithTabBarState();
}
class _SilverAppBarWithTabBarState extends State<SilverAppBarWithTabBarScreen>
with SingleTickerProviderStateMixin {
TabController controller;
#override
void initState() {
super.initState();
controller = new TabController(length: 3, vsync: this);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(
title: Text("Silver AppBar With ToolBar"),
pinned: true,
expandedHeight: 160.0,
bottom: new TabBar(
tabs: [
new Tab(text: 'Tab 1'),
new Tab(text: 'Tab 2'),
new Tab(text: 'Tab 3'),
],
controller: controller,
),
),
new SliverList(
new SliverFillRemaining(
child: TabBarView(
controller: controller,
children: <Widget>[
Text("Tab 1"),
Text("Tab 2"),
Text("Tab 3"),
],
),
),
],
),
);
}
}
Yeah. You can use NestedScrollView To Achieve Tabs. Here is Some Addition Code To That.
class AppView extends StatelessWidget {
final double _minValue = 8.0;
#override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: MyAppBar(),
drawer: DrawerDialog(),
body: DefaultTabController(
length: 3,
child: SafeArea(
child: NestedScrollView(
body: TabBarView(
children: [Text("Page 1"), Text("Page 2"), Text("Page 3")],
),
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) => [
SliverPadding(
padding: EdgeInsets.all(_minValue * 2.5),
sliver: SliverToBoxAdapter(
child: Text(
"Hiding Header",
style: textTheme.headline6,
textAlign: TextAlign.center,
),
),
),
SliverAppBar(
backgroundColor: Colors.grey[100],
pinned: true,
elevation: 12.0,
leading: Container(),
titleSpacing: 0.0,
toolbarHeight: 10,
bottom: TabBar(tabs: [
Tab(
child: Text(
"All",
style: textTheme.subtitle2,
),
),
Tab(
child: Text(
"Categories",
style: textTheme.subtitle2,
),
),
Tab(
child: Text(
"Upcoming",
style: textTheme.subtitle2,
),
),
]),
),
],
),
),
),
);
}
}
You can Also Implement it by Providing _tabController to Both TabBar() and TabBarView So It will bind.
And For the children of TabBarView if you're using ListView then give it physics: NeverScrollablePhysics() so it won't move, kindly not You have to give dynamic height to the Container of ListView So it will load all Children's.
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
expandedHeight: 50,
title: Column(
children: [
Row(
children: [
Text('Hello, User'),
Spacer(),
InkWell(
child: Icon(Icons.map_rounded),
),
],
),
],
),
),
SliverList(
delegate: SliverChildListDelegate([
_tabSection(context),
])),
],
));
}
Widget _tabSection(BuildContext context) {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
double mainAxisHeight = height > width ? height : width;
return DefaultTabController(
length: 2,
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Container(
height: 48,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
bottomLeft: Radius.circular(10))),
child: TabBar(
indicatorColor: Colors.white,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(color: Colors.white, width: 5.0),
insets: EdgeInsets.symmetric(horizontal: 40),
),
labelColor: Colors.white,
unselectedLabelColor: Colors.grey[300],
tabs: [
Tab(
iconMargin: EdgeInsets.only(top: 5),
text: "Tab Bar 1",
),
Tab(
iconMargin: EdgeInsets.only(top: 5),
text: "Tab bar 2",
),
]),
),
Container(
height: 200 * 6 // 200 will be Card Size and 6 is number of Cards
child: TabBarView(controller: _tabController, children: [
tabDetails(),
tabDetails(),
]))
]));
}
tabDetails() {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
double mainAxisHeight = height > width ? height : width;
return Container(
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.red[100],
Colors.red[200],
])),
child: ListView(
physics: NeverScrollableScrollPhysics(), // This will disable LitView'Scroll so only Scroll is possible by TabBarView Scroll.
children: [
SizedBox(height: 10),
Container(
height:140,
width: width,
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: 6,
itemBuilder: (BuildContext context, int indexChild) {
return Row(
children: [
MyListTile(
name: "Name",
),
SizedBox(width: 5),
],
);
},
),
),
SizedBox(height: 1000),
],
),
);
}
}
If you want to use CustomScrollView, you can make use of SliverToBoxAdapter:
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 2,
child: CustomScrollView(
slivers: [
SliverAppBar(
title: Text('SliverAppBar'),
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.call), text: "Call"),
Tab(icon: Icon(Icons.message), text: "Message"),
],
),
),
SliverToBoxAdapter(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: TabBarView(
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
],
),
),
),
],
),
),
);
}