【问题标题】:TabBarView with dynamic height and padding具有动态高度和填充的 TabBarView
【发布时间】:2021-04-23 08:38:22
【问题描述】:

我有 3 个具有动态网格视图的选项卡,但我的问题是,当我在物理设备上对其进行测试时,其中一个网格视图的末端看起来很完整,但在另一个较小的设备 (720 x 1280) gridview的最后一行文本不可见,所以我的想法是在底部添加一个填充,但当然,在小型设备上它看起来不错

并将此填充添加到 GridView.Builder...:

padding: EdgeInsets.only(right: 20.0, left: 20.0, bottom: 100),

但是在其他更高分辨率的设备中,这使得底部的填充看起来不一样,这里的填充更大“

我怎样才能做这个动态填充,以便它是相同的,并且gridview在所有设备上都是完全可见的?

另外,我想补充一点,我的 TabBarViews 位于 500 高度的容器内,我不知道这是否有问题,因为我觉得它是静态的,我不喜欢任何东西,我想要容器只能从一开始(在选项卡下方)直到屏幕结束,我也不知道该怎么做。

另外,我看到测试的东西总是指出安全区域和脚手架下的列有“hasSize”问题,我在尝试修复它时总是遇到很多高度异常,在 shop_scree_page.dart 中,我没有对设计了解不多,也许我把事情搞错了。

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),
          )
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart tabbar ui-design


    【解决方案1】:

    您可以通过屏幕大小的动态填充来做到这一点。对于经验:

    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)
    

    【讨论】:

      猜你喜欢
      • 2019-07-05
      • 2013-07-27
      • 1970-01-01
      • 2011-05-01
      • 2012-07-19
      • 2018-08-04
      • 1970-01-01
      • 2012-12-13
      • 2012-06-14
      相关资源
      最近更新 更多