# Flutter 踩坑实录

2019-08-18  本文已影响0人  间歇性丶神经病患者

[TOC]

Another exception was thrown: A dismissed Dismissible widget is still part of the tree.

具体代码为

ListView.builder(
              itemBuilder: (context, index) {
                var item = _list[index];
                debugPrint('the key is ${index.toString()}');
                return Dismissible(
                  key: Key(item.id.toString()),
                  confirmDismiss: (DismissDirection direction) async {
                    final bool res = await showDialog(
                        context: context,
                        builder: (BuildContext context) {
                          return CupertinoAlertDialog(
                            title: Text(
                              "注意",
                              style: TextStyle(
                                  fontSize: 16, color: ColorConf.color000000),
                            ),
                            content: const Text("您是否要取消收藏这个文章呢?"),
                            actions: <Widget>[
                              FlatButton(
                                  onPressed: () {
                                    Navigator.of(context).pop(true);
                                    _deleteItem(item.id, item.originId, index);
                                  },
                                  child: Text(
                                    "是的",
                                    style: TextStyle(
                                        fontSize: 14,
                                        color: ColorConf.colorGreen),
                                  )),
                              FlatButton(
                                onPressed: () =>
                                    Navigator.of(context).pop(false),
                                child: Text(
                                  "CANCEL",
                                  style: TextStyle(
                                      fontSize: 14,
                                      color: ColorConf.color48586D),
                                ),
                              )
                            ],
                          );
                        });
                    return res;
                  },
                  background: Container(
                    padding: const EdgeInsets.only(right: 30),
                    alignment: Alignment.centerRight,
                    color: Colors.red,
                    child: Text(
                      '滑动取消收藏',
                      style:
                          TextStyle(fontSize: 16, color: ColorConf.colorFFFFFF),
                    ),
                  ),
                  child: Container(
                      child: Column(
                    children: <Widget>[
                      ProjectWidget.renderListViewCollectionItem(
                          _list[index], () {}),
                      Divider(),
                    ],
                  )),
                );
              },
              itemCount: _list.length)

具体表现为:删除了某个item后再去下拉更新数据,会报错,可能是因为key的问题,所以修改为:

  key: Key(UniqueKey().toString()),

表现良好

showModalBottomSheet 输入框被输入法遮挡

效果图:


微信图片_20190923141123.png 微信图片_20190923141130.png

主要是两个问题:

 /// 选择弹窗
  _showChooseDialog(BuildContext context) {
    showModalBottomSheet(
        backgroundColor: Colors.transparent,
        isScrollControlled: true,
        useRootNavigator: true,
        context: context,
        builder: (_) => ChooseDialog());
  }

showModalBottomSheet 高度

默认属性为高度为页面高度的1/2,这里设置为
isScrollControlled: true, 即dialog高度为页面高度的100%;

dialog可滚动且resizeToAvoidBottomPadding: true,

子布局添加

 @override
  Widget build(BuildContext context) {
    debugPrint(
        'MediaQuery.of(context).viewInsets.bottom is ${MediaQuery.of(context).viewInsets.bottom}');
    return Scaffold(
        backgroundColor: Colors.transparent,
        resizeToAvoidBottomPadding: true,
        body: Container(
          alignment: Alignment.bottomCenter,
          child: SingleChildScrollView(
            child: _initBody(context),
          ),
        ));
  }

页面滚动是因为原页面太高,滚动后会出现越界,这边添加滚动。
而为了让输入法顶出输入框,这边顶层布局修改为Scaffold,且添加:

 resizeToAvoidBottomPadding: true,
  /// This flag is deprecated, please use [resizeToAvoidBottomInset]
  /// instead.
  ///
  /// Originally the name referred [MediaQueryData.padding]. Now it refers
  /// [MediaQueryData.viewInsets], so using [resizeToAvoidBottomInset]
  /// should be clearer to readers.
  @Deprecated('Use resizeToAvoidBottomInset to specify if the body should resize when the keyboard appears')
  final bool resizeToAvoidBottomPadding;

折叠布局

import 'package:flutter/material.dart';
import 'package:flutter_shop_index/utils/ColorConf.dart';
import 'package:flutter_shop_index/utils/StyleConf.dart';
import 'package:flutter_swiper/flutter_swiper.dart';

import 'homeChild/HomeChildPage.dart';

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomePage();
  }
}

class _HomePage extends State<HomePage> with TickerProviderStateMixin {
  List<String> _title = [];
  List<String> _classImgList = [];
  TabController _tabController;

  @override
  void initState() {
    _title.clear();
    _title.add("热门推荐");
    _title.add("积分可换");
    _title.add("限时兑购");
    _title.add("新品上线");
    _title.add("品牌专区");
    _classImgList.clear();
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/20983/16/10753/6124/5c8a16aaE5d6b15d7/01e0e818a7505267.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/39401/17/2391/5859/5cc06fcfE2ad40668/28cda0a571b4a576.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/17169/3/4127/4611/5c2f35cfEd87b0dd5/65c0cdc1362635fc.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t17725/156/1767366877/17404/f45d418b/5ad87bf0N66c5db7c.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t16990/157/2001547525/17770/a7b93378/5ae01befN2494769f.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t16990/157/2001547525/17770/a7b93378/5ae01befN2494769f.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t18454/342/2607665324/6406/273daced/5b03b74eN3541598d.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t22228/270/207441984/11564/88140ab7/5b03fae3N67f78fe3.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/7068/29/8987/5605/5c120da2Ecae1cc3a/016033c7ef3e0c6c.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t16828/63/2653634926/5662/d18f6fa1/5b03b779N5c0b196f.png');
    _classImgList.add(
        'https://m.360buyimg.com/mobilecms/s120x120_jfs/t1/22262/9/1470/4527/5c120cd0E5d3c6c66/4792ec307a853e9f.png');
    _tabController =
        new TabController(length: _title.length, vsync: this, initialIndex: 0);

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    double statusBarHeight = MediaQuery.of(context).padding.top;
    double _bannerHeight = 190 + 10.0;
    double _classHeight = 190;
    double _pointHeight = 30;
    double _appBarHeight = _bannerHeight +
        _pointHeight +
        _classHeight -
        kToolbarHeight -
        statusBarHeight;
        _tabController.index=4;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: ColorConf.colorFFFFFF,
        centerTitle: true,
        title: Text(
          "积分商城",
          style: StyleConf.style2048586DBold,
        ),
        actions: <Widget>[
          IconButton(
            icon: ImageIcon(
              AssetImage(
                'images/iconSearch.png',
              ),
              color: ColorConf.color48586D,
            ),
            onPressed: () {},
          ),
          IconButton(
            icon: ImageIcon(
              AssetImage(
                'images/iconMore.png',
              ),
              color: ColorConf.color48586D,
            ),
            onPressed: () {},
          ),
        ],
      ),
      body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverOverlapAbsorber(
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                child: SliverAppBar(
                  backgroundColor: Color(0xfff1f1f1),
                  forceElevated: innerBoxIsScrolled,
                  bottom: PreferredSize(
                      child: Container(),
                      preferredSize: Size.fromHeight(_appBarHeight)),
                  flexibleSpace: Column(
                    children: <Widget>[
                      _initBanner(_bannerHeight),
                      _initPointBar(_pointHeight),
                      _initProClass(_classHeight),
                    ],
                  ),
                ),
              ),
              SliverPersistentHeader(
                delegate: _SliverAppBarDelegate(_initTabBar()),
                pinned: true,
              ),
            ];
          },
          body: _initTabBarView()),
    );
  }

  /// 初始化tab Menu
  /// 这个Widget 可用于bottom以及center中部菜单
  /// 可用于 [appBar]的[bottom]
  /// 可用于[body]的item
  Widget _initTabBarView() {
    return TabBarView(
      children: _title.map((e) => HomeChildPage()).toList(),
      controller: _tabController,
    );
  }

  /// 初始化tab Menu
  /// 这个Widget 可用于bottom以及center中部菜单
  /// 可用于 [appBar]的[bottom]
  /// 可用于[body]的item
  Widget _initTabBar() {
    return Stack(
      alignment: Alignment.center,
      children: <Widget>[
        Container(
          color: ColorConf.colorFFFFFF,
        ),
        _initTabItem(),
      ],
    );
  }

  /// 初始化每一个tabBar的每一个item ,主要用于[_initTabBar]
  Widget _initTabItem() {
    return TabBar(
      isScrollable: true,
      labelStyle: StyleConf.style1448586D,
      unselectedLabelStyle: StyleConf.style14A1A9B4,
      indicatorSize: TabBarIndicatorSize.label,
      indicator: BoxDecoration(
          image: DecorationImage(
              alignment: Alignment.bottomCenter,
              image: AssetImage(
                'images/IconLandscape.png',
              ))),
      labelColor: ColorConf.color48586D,
      unselectedLabelColor: ColorConf.color929292,
      tabs: _title
          .map((e) => Tab(
                child: Container(
                  child: Text(e),
                  padding: const EdgeInsets.only(
                    bottom: 0,
                  ),
                ),
              ))
          .toList(),
      controller: _tabController,
    );
  }

  /// 初始化banner
  Widget _initBanner(height) {
    return Expanded(
        child: Container(
      height: height,
      child: Swiper(
        itemBuilder: (BuildContext context, int index) {
          return Container(
            decoration: BoxDecoration(
                image: DecorationImage(
              fit: BoxFit.fill,
              repeat: ImageRepeat.noRepeat,
              image: NetworkImage(
                'https://m.360buyimg.com/mobilecms/s700x280_jfs/t1/51092/36/11835/138581/5d89eec9E161806d2/83a2e56cd03a6817.jpg!cr_1125x445_0_171!q70.jpg.dpg',
              ),
            )),
          );
        },
        itemCount: 3,
        pagination: new SwiperPagination(builder: SwiperPagination.dots),
      ),
    ));
  }

  /// 商品分类
  Widget _initProClass(height) {
    return Container(
      height: height,
      color: ColorConf.colorFFFFFF,
      padding: const EdgeInsets.only(top: 10, left: 14, right: 14, bottom: 10),
      child: GridView.builder(
          physics: NeverScrollableScrollPhysics(),
          itemCount: 10,
          shrinkWrap: true,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 5,
              mainAxisSpacing: 10,
              childAspectRatio: 0.75,
              crossAxisSpacing: 10),
          itemBuilder: (context, index) {
            return Column(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                Container(
                  height: 50,
                  margin: const EdgeInsets.only(bottom: 4),
                  padding: const EdgeInsets.all(3),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Image.network(
                    _classImgList[index],
                    scale: 0.5,
                  ),
                ),
                Expanded(
                    child: Text(
                  '调养优品',
                  style: StyleConf.style1248586D,
                ))
              ],
            );
          }),
    );
  }

  /// 积分栏
  Widget _initPointBar(height) {
    return Container(
      height: height,
      padding: const EdgeInsets.only(left: 14, right: 14, top: 4, bottom: 4),
      color: ColorConf.color18C8A1,
      child: Row(
        children: <Widget>[
          Text(
            '可用积分:12212120',
            style: StyleConf.style14FFFFFF,
          ),
          Expanded(
              child: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Text('兑换记录', style: StyleConf.style14FFFFFF),
              Icon(
                Icons.chevron_right,
                color: ColorConf.colorFFFFFF,
              )
            ],
          ))
        ],
      ),
    );
  }
}

/// SliverAppBar代理
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  final Stack _tabBar;

  _SliverAppBarDelegate(this._tabBar);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return _tabBar;
  }

  @override
  double get maxExtent => 41;

  @override
  double get minExtent => 41;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}

上一篇 下一篇

猜你喜欢

热点阅读