I have 3 tabs that have a dynamic gridview, but my problem is that when I tested it on a physical device, in one of them the end of the gridview looked complete, but in another smaller device (720 x 1280) the last row of the gridview The text was not visible, so my thought was to add a padding at the bottom but of course, on the small device it looks fine
And adding this padding to the GridView.Builder...:
padding: EdgeInsets.only(right: 20.0, left: 20.0, bottom: 100),
but in the other higher resolution devices, this makes the padding at the bottom not look the same and here the padding is bigger "
How can I do this dynamic padding so that it is the same and the gridview is completely visible on all devices?
Also, I want to add that my TabBarViews are inside a container of 500 height and I don't know if that could be a problem, because I feel that it is static and I am not liking anything, I would like the container to only take until the end of the screen from the beginning (below the tabs), and I don't know how to do it either.
Also, I have seen that testing things always pointed out that the column under the safearea and the scaffold had "hasSize" problems and I always got many height exceptions while trying to fix it, in the shop_scree_page.dart, I don't know much about design and maybe I'm putting things very wrong.
shop_scree_page.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:plantsapp/screens/all_tab.dart';
import 'package:plantsapp/screens/indoor_page.dart';
import 'package:plantsapp/screens/outdoor_tab.dart';
import 'package:plantsapp/screens/top_tab.dart';
import 'package:plantsapp/services/authentication_service.dart';
class ShopScreen extends StatefulWidget {
@override
_ShopScreenState createState() => _ShopScreenState();
}
class _ShopScreenState extends State<ShopScreen>
with SingleTickerProviderStateMixin {
TabController _tabController;
PageController _pageController;
GlobalKey<ScaffoldState> _drawerKey = GlobalKey();
@override
void initState() {
super.initState();
_tabController = TabController(initialIndex: 0, length: 4, vsync: this);
_pageController = PageController(initialPage: 0, viewportFraction: 0.8);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
List<Widget> containers = [
new TopTab(),
new OutdoorTab(),
new IndoorTab(),
new AllTab(),
];
AuthenticationService authServ = new AuthenticationService();
return Scaffold(
key: _drawerKey,
drawer: new Drawer(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.logout),
backgroundColor: Colors.black,
onPressed: () {
//context.read<AuthenticationService>()
authServ.signOut();
},
),
drawerEnableOpenDragGesture: false,
body: SafeArea(
child: Column(
children: <Widget>[
//ICONOS MENU Y CART
Container(
margin: EdgeInsets.only(top: 20),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu, size: 30.0, color: Colors.grey),
onPressed: (() => _drawerKey.currentState.openDrawer()),
),
Spacer(),
IconButton(
icon: Icon(Icons.add),
color: Colors.black,
iconSize: 32,
onPressed: () {
Navigator.pushNamed(context, 'createplantpost');
}),
IconButton(
icon: Icon(Icons.shopping_cart),
color: Colors.black,
onPressed: () {}),
],
),
),
),
SizedBox(height: 20.0),
//TITULO "TOP PICKS"
Expanded(
child: Container(
width: double.infinity,
child: SingleChildScrollView(
child: Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.only(left: 20.0),
child: Text(
'Top Picks',
style: TextStyle(
fontSize: 24.0, fontWeight: FontWeight.w600),
),
),
),
_tabs(),
_tabsView(containers),
],
),
),
),
),
],
),
),
);
}
Widget _tabs() {
return TabBar(
controller: _tabController,
indicatorColor: Colors.transparent,
labelColor: Colors.black,
unselectedLabelColor: Colors.grey.withOpacity(0.6),
labelPadding: EdgeInsets.symmetric(horizontal: 35.0),
isScrollable: true,
tabs: <Widget>[
Tab(
child: Text('Top',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
))),
Tab(
child: Text('Outdoor',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
))),
Tab(
child: Text('Indoor',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
))),
Tab(
child: Text('All',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
))),
],
);
}
Widget _tabsView(containers) {
final size = MediaQuery.of(context).size;
return Container(
height: 500,
child: TabBarView(
physics: NeverScrollableScrollPhysics(),
controller: _tabController,
children: containers
),
);
}
}
outdoor_tab.dart
import 'package:flutter/material.dart';
import 'package:plantsapp/models/plant_model.dart';
import 'package:plantsapp/providers/products_provider.dart';
import 'package:plantsapp/screens/plant_screen.dart';
import 'package:plantsapp/widgets/snapshots_alerts.dart';
class OutdoorTab extends StatefulWidget {
const OutdoorTab({Key key}) : super(key: key);
@override
_OutdoorTabState createState() => _OutdoorTabState();
}
class _OutdoorTabState extends State<OutdoorTab> {
@override
Widget build(BuildContext context) {
ProductsProvider productsProvider = new ProductsProvider();
return Scaffold(
body: streamBuilderCards(productsProvider),
);
}
Widget streamBuilderCards(ProductsProvider productsProvider) {
final size = MediaQuery.of(context).size;
return StreamBuilder(
stream: productsProvider.getPostOutdoor(context),
builder:
(BuildContext context, AsyncSnapshot<List<PlantModel>> snapshot) {
if (snapshot.hasError) {
return snapshotMsgError(snapshot);
}
if (!snapshot.hasData) {
return snapshotCircularProgressIndicator();
}
List<PlantModel> posts = snapshot.data;
return GridView.builder(
padding: EdgeInsets.only(
right: 20.0, left: 20.0, bottom: 100),
itemCount: posts.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
childAspectRatio: 0.60),
itemBuilder: (context, index) => ItemCard(plants: posts[index]),
);
},
);
}
}
class ItemCard extends StatelessWidget {
final PlantModel plants;
final Function press;
const ItemCard({
Key key,
this.press,
this.plants,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PlantScreen(plant: plants),
),
);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 198,
width: 175,
decoration: BoxDecoration(
//color: Colors.blueAccent,
borderRadius: BorderRadius.circular(16)),
child: Hero(
tag: plants.imageUrl,
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: (plants.imageUrl == null)
? Image(
image: AssetImage('assets/images/no-image.png'),
fit: BoxFit.cover)
: FadeInImage(
image: NetworkImage(plants.imageUrl),
placeholder:
AssetImage('assets/images/image-loading.gif'),
fit: BoxFit.cover,
), /*Image(
image: NetworkImage(plants.imageUrl),
fit: BoxFit.cover,
)*/
),
) //Image.asset(plants.imageUrl),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Text(
plants.name,
style: TextStyle(color: Colors.grey),
overflow: TextOverflow.ellipsis,
),
),
Text(
'\$${plants.price}',
style: TextStyle(fontWeight: FontWeight.bold),
)
],
),
);
}
}
You can do that with dynamic padding by screen size. For Exp:
var screenHeight = MediaQuery.of(context).size.height;
var screenWidth = MediaQuery.of(context).size.width;
padding: EdgeInsets.only(right: screenWidth * 0.2, left: screenWidth * 0.2, bottom: screenHeight * 0.15)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.