How can I create a line under the SliverAppBar in flutter? - flutter

I would like to add a line under the appbar as in image two.
How can I make this line in flutter?
The image one is the app now and the image two is the line under the sliverAppBar
*already tried to use a container and a divider
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: SvgPicture.asset(
'assets/icons/home_icon.svg',
color: Colors.black,
),
onPressed: () {}
),
actions: [
IconButton(
icon: SvgPicture.asset(
'assets/icons/search_icon.svg',
color: Colors.black,
),
onPressed: () {
}
),
IconButton(
icon: SvgPicture.asset(
'assets/icons/shopping_bag_icon.svg',
color: Colors.black,
),
onPressed: () {},
),
IconButton(
icon: SvgPicture.asset(
'assets/icons/profile_icon.svg',
color: Colors.black,
),
onPressed: () {}
),
],
floating: true,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item #$index')),
childCount: 1000,
),
),
],
),
);
}
}
more txt for the stack valid my questions

There is a 'bottom' attribute in the SliverAppBar Widget which takes a preferred size Widget, you can give it the following:
bottom: PreferredSize(
preferredSize: Size(double.infinity, 5),
child: Divider(color: Colors.black),
),

A contribution to omar hatem answer, the property "size" should be "preferredSize"
bottom: PreferredSize(
preferredSize: Size(double.infinity, 5),
child: Divider(color: Colors.black),
),

In my case, I needed more control over my line under the app bar sliver so I ended up implementing like so:
SliverPersistentHeader(
pinned: true,
delegate: MySliverElevationDelegate(
child: Material(
//elevation: 4.0,
child: Container(
color: Colors.black,
),
),
),
)
Cheers!

Related

Custom widget of app bar with a humburger menu as ElevatedButton with a Drawer doesn't work OnPressed

I am facing a problem with my custom app bar. I would like it to have a drawer but it doesn't work. I just don't know how to make it being able to open.
It is a custom app bar widget named Pasek (which stands for top bar in my language).
It has a logo picture which on click moves you to the first page of the app.
Next to it there is humburger menu with a drawer but I do not know why it doesn't work. I click on it and nothing happens.
Any ideas?
class Pasek extends StatelessWidget with PreferredSizeWidget {
#override
Size get preferredSize => Size.fromHeight(50.0);
const Pasek({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return AppBar(
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 35.0),
child: ElevatedButton(
child: Icon(Icons.menu, color: Colors.white),
onPressed: () {
Scaffold(
endDrawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.black,
),
child: Text(
'Menu',
style: TextStyle(
color: Colors.pink,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.message),
title: Text('Messages'),
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profile'),
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
);
},
)),
],
backgroundColor: Colors.black,
title: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => FirstPage(),
),
);
}, // Image tapped
child: Image.asset(
'images/logo.png',
fit: BoxFit.scaleDown,
height: 30,
width: 200,
),
));
}
}

Reduce space between Tabbar and Listtile

I want to reduce the space between Tabbar and listtile. I wrote them in two different files so i'll add both the codes. tried adding padding but no use.
main.dart
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
home: DefaultTabController(
length: 4,
child: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
pinned: true,
floating: true,
systemOverlayStyle: SystemUiOverlayStyle.dark,
title: const Text(
"WhatsApp",
style: TextStyle(letterSpacing: 1.0),
),
backgroundColor: colour,
actions: [
MaterialButton(
minWidth: 1.0,
onPressed: () {},
child: const Icon(
Icons.search,
color: Colors.white,
)),
MaterialButton(
minWidth: 1.0,
onPressed: () {},
child: const Icon(
Icons.more_vert,
color: Colors.white,
))
],
bottom: const TabBar(
dragStartBehavior: DragStartBehavior.start,
indicatorColor: Colors.white,
tabs: [
Tab(
iconMargin: EdgeInsets.only(left: 1.0, right: 1.0),
icon: Icon(Icons.photo_camera),
),
Tab(child: Text("CHATS")),
Tab(child: Text("STATUS")),
Tab(child: Text("CALLS"))
]))
],
body: const TabBarView(
dragStartBehavior: DragStartBehavior.start,
children: [Camera(), Chats(), Status(), Calls()]),
),
));
}
}
chats.dart
class _ChatsState extends State<Chats> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.only(top: 1.0),
child: ListView.separated(
itemBuilder: (context, index) => ListTile(
title: Text("Person $index"),
subtitle: Text("your message is this"),
trailing: Text("$hr:$mi $ti"),
leading: MaterialButton(
padding: EdgeInsets.all(1.0),
height: 1.0,
minWidth: 1.0,
elevation: 0,
onPressed: () {},
shape: CircleBorder(),
child: CircleAvatar(
radius: 25.0,
backgroundImage: AssetImage('assets/images/images.jfif'),
),
),
),
separatorBuilder: (context, index) {
return Divider();
},
itemCount: 50),
),
floatingActionButton: FloatingActionButton(
backgroundColor: colour,
onPressed: () {},
child: Icon(Icons.chat_rounded),
),
);
}
}
try padding: EdgeInsets.zero inside ListView.separated, not inside ListTile

How to change positions of icons in AppBar in flutter?

I am trying to reposition my "compass" icon near the "search" icon from the App bar. Everytime i try to make a change in the container with higher value 55 for example "padding: const EdgeInsets.symmetric(horizontal: 50)," i get error stack over flow. Also when i try to change the logo(png) the allingment, nothing happens. Help please!
Image
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[Colors.pink[400], Colors.blue[400]]
),
),
),
title: Row(
children: [
Container(
alignment: Alignment.center,
height: 40,
child: SizedBox(
child: Image.asset(
'assets/images/logox.png',
)
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: SizedBox(
child: Icon(
Icons.explore_rounded,
))),
// Container(child: Icon(Icons.explore_rounded)),
],
),
actions: [
GestureDetector(
onTap: () {
// authMethods.signOut();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => SearchScreen(),
));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.search)),
)
],
),
drawer: MainDrawer(),
//body: Body(),
bottomNavigationBar: GradientBottomNavigationBar(
fixedColor: Colors.white,
backgroundColorStart: Colors.pink[400],
backgroundColorEnd: Colors.blue[400],
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.wallet_membership), title: Text('QUA')),
BottomNavigationBarItem(
icon: Icon(Icons.help), title: Text('Help')),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.pink,
elevation: 50,
hoverColor: Colors.red,
autofocus: true,
onPressed: () {
print('hi');
},
child: Icon(
Icons.comment,
),
tooltip: 'Pick Image',
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
}
There is actions property in AppBar widget which is mainly used to put icons in AppBar. And in your case centerTitle is used to align your image to center
Output
Full code
class MyHomePage extends StatefulWidget {
final Function onItemPressed;
MyHomePage({
Key key,
this.onItemPressed,
}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[Colors.pink[400], Colors.blue[400]]),
),
),
centerTitle: true,
title: Container(
alignment: Alignment.center,
height: 40,
child: SizedBox(
child: Image.asset(
'assets/logo.png',
)),
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.explore_rounded),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.search),
)
],
),
);
}
}
Material appbar has an actions property, you can use that to put search and compass icon together. In order to achieve the same remove
Container(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: SizedBox(
child: Icon(
Icons.explore_rounded,
))),
from its current position and add it into the actions property just above the search button.

How to make a top tab bar with CupertinoSliverNavigationBar Flutter

I use CupertinoSliverNavigationBar, how can I add a tab bar below the title that is fixed to scroll?
My current code :
class SearchView extends StatefulWidget {
#override
_SearchViewState createState() => _SearchViewState();
}
class _SearchViewState extends State<SearchView> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
CupertinoSliverNavigationBar(
backgroundColor: Colors.white,
border: Border.all(width: 0.0, color: const Color(0xFFFFFFFF)),
leading: Material(
child: GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Icon(
IconData(
0xe904,
fontFamily: 'icomoon',
),
color: Colors.black,
size: 25.0,
),
),
),
largeTitle: Text('Discover'),
)
];
},
body: Scaffold(
backgroundColor: Colors.white,
body: Container(),
),
),
);
}
}
Like on the attached picture :
Of course, if there is a solution that works without the Cupertino widgets, but that still respects the design, I'm interested.
You can use NeverScrollableScrollPhysics to ensure that the height of the CupertinoSliverNavigationBar remains fixed:
CupertinoPageScaffold(
child: CustomScrollView(
physics: const NeverScrollableScrollPhysics(), // add
slivers: [
CupertinoSliverNavigationBar(
middle: Text(
testNumber,
style: const TextStyle(
color: CupertinoColors.systemPink
),
),
largeTitle: const CircleAvatar(
backgroundColor: CupertinoColors.systemGreen,
child: Text("1"),
),
),
SliverFillRemaining(
child: PageView.builder(
itemBuilder: (context, index) {
return Text("$index");
},
),
)
],
)
);

Flutter: Create a rectangle that fills the title area of the app bar

In Flutter I want to create an app bar that looks as follows:
I've easily managed to add the 2 icons on the left and right, but I am struggling to create a rectangle in the middle.
I've tried the following code:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: IconButton(
icon: Image.asset('assets/images/maps.png'),
onPressed: () => {},
),
title: Expanded( // The bit that's not working. A rectangle that fills the middle area.
child: Container(
color: Colors.blue,
),
),
actions: <Widget>[
IconButton(
icon: Image.asset('assets/images/search.png'),
onPressed: () => {},
),
],
),
);
but I get the following exception:
Expanded widgets must be placed inside Flex widgets.
Expanded(no depth, flex: 1, dirty) has no Flex ancestor at all.
Thanks for the help.
You can achieve this by setting the centerTile attribute of the AppBar to true
Like this
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
leading: IconButton(
icon: Icon(
Icons.location_on,
color: Colors.grey,
),
onPressed: () => {},
),
title: Container(
padding: EdgeInsets.all(10),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Icon(Icons.refresh),
Expanded(
child: Center(
child: Text("London"),
),
),
Opacity(child: Icon(Icons.refresh), opacity: 0,),
],
),
decoration: BoxDecoration(
color: Colors.grey, borderRadius: BorderRadius.circular(10)),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: Colors.grey,
),
onPressed: () => {},
),
],
),
);
}
}
The output:
An alternative solution (inspired by #Josteve Adekanbi answer), to create a rectangle that fills the title area is:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: ...
title: Container(
width: double.infinity,
height: 40,
child: Container(
color: Colors.blue,
),
),
actions: ...
),
);