【Flutter】TabBar 改背景色

之前有提过要仿公司 某款产品的UI,用Flutter刚好试试手。首页登陆都做了,有几个坑记录一下。
这里展示的功能其实都应该从后端获取的,后端这一块目前没做,后面有空了补起来。
相对比较简单,主要涉及到以下几点:
1、TabBar上无法设置颜色和高度,标准库默认与AppBar颜色一致。
2、GridView的基本运用。

import 'package:flutter/material.dart';
import 'Pages/Workpage.dart' show WorkPages;
import 'Pages/Salespage.dart' show SalesPages;
import 'Pages/WareHousePage.dart' show WareHousePages;
import 'Pages/Purchasepage.dart' show PurchasePages;
import 'config/conf.dart' show GlobalVariable;

class HomePages extends StatefulWidget {
  @override
  _HomePagesState createState() => _HomePagesState();
}

class _HomePagesState extends State<HomePages> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: 4,
        child: Scaffold(
          appBar: AppBar(
              elevation: 0,
              centerTitle: true,
              automaticallyImplyLeading: true,
              actions: <Widget>[
                Image.asset('assets/images/temp_setting.png', width: 26.0, height: 26.0,),
                SizedBox(width: 5.0,)
              ],
              title: RichText(
                text: TextSpan(children: [
                  TextSpan(text: GlobalVariable.AppHomeTitle, style: TextStyle(fontSize: 20.0)),
                  TextSpan(text: GlobalVariable.AppHomeSubTitle, style: TextStyle(fontSize: 12.0))
                ]),
              ),

              //可以单独设置,固定高度为40H
              bottom: PreferredSize(
                preferredSize: Size.fromHeight(40),
                child: Material(
                  color: Colors.white,
                  child: TabBar(
                      labelPadding: EdgeInsets.all(10.0),
                      labelStyle: TextStyle(fontSize: 16.0),
                      unselectedLabelColor: Colors.black54,
                      labelColor: Colors.blue,
                    tabs: <Widget>[
                        Text('采购管理'),
                        Text('生产管理'),
                        Text('仓库管理'),
                        Text('销售管理'),
                    ],
                  ),
                )
              )),
          body: Container(
            color: Colors.white,
            child: TabBarView(
              children: <Widget>[
                PurchasePages(),
                WorkPages(),
                WareHousePages(),
                SalesPages(),
              ],
            ),
          )
        ));
  }
}

这里的bottom下没有直接TabBar,而且用PreferredSize来进行取代。如果直接用TabBar的话,颜色会与顶部一致,并且无法更改。

这里可以看到TabBar的属性,并没有任何颜色的属性? 那要如何改颜色?

 class TabBar extends StatefulWidget implements PreferredSizeWidget {
  /// Creates a material design tab bar.
  ///
  /// The [tabs] argument must not be null and its length must match the [controller]'s
  /// [TabController.length].
  ///
  /// If a [TabController] is not provided, then there must be a
  /// [DefaultTabController] ancestor.
  ///
  /// The [indicatorWeight] parameter defaults to 2, and must not be null.
  ///
  /// The [indicatorPadding] parameter defaults to [EdgeInsets.zero], and must not be null.
  ///
  /// If [indicator] is not null, then [indicatorWeight], [indicatorPadding], and
  /// [indicatorColor] are ignored.
  const TabBar({
    Key key,
    @required this.tabs,
    this.controller,
    this.isScrollable = false,
    this.indicatorColor,
    this.indicatorWeight = 2.0,
    this.indicatorPadding = EdgeInsets.zero,
    this.indicator,
    this.indicatorSize,
    this.labelColor,
    this.labelStyle,
    this.labelPadding,
    this.unselectedLabelColor,
    this.unselectedLabelStyle,
    this.dragStartBehavior = DragStartBehavior.start,
    this.onTap,
  }) : assert(tabs != null),
       assert(isScrollable != null),
       assert(dragStartBehavior != null),
       assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)),
       assert(indicator != null || (indicatorPadding != null)),
       super(key: key);
}

我们看到TabBar继承了PreferredSizeWidget,点进去看下,经过观察,我们可以使用它重新布局画面。

记住一定要在Material下,单独设置颜色

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/rendering.dart';

import 'basic.dart';
import 'framework.dart';

/// An interface for widgets that can return the size this widget would prefer
/// if it were otherwise unconstrained.
///
/// There are a few cases, notably [AppBar] and [TabBar], where it would be
/// undesirable for the widget to constrain its own size but where the widget
/// needs to expose a preferred or "default" size. For example a primary
/// [Scaffold] sets its app bar height to the app bar's preferred height
/// plus the height of the system status bar.
///
/// Use [PreferredSize] to give a preferred size to an arbitrary widget.
abstract class PreferredSizeWidget implements Widget {

  /// The size this widget would prefer if it were otherwise unconstrained.
  ///
  /// In many cases it's only necessary to define one preferred dimension.
  /// For example the [Scaffold] only depends on its app bar's preferred
  /// height. In that case implementations of this method can just return
  /// `new Size.fromHeight(myAppBarHeight)`;
  Size get preferredSize;
}

/// A widget with a preferred size.
///
/// This widget does not impose any constraints on its child, and it doesn't
/// affect the child's layout in any way. It just advertises a preferred size
/// which can be used by the parent.
///
/// See also:
///
///  * [AppBar.bottom] and [Scaffold.appBar], which require preferred size widgets.
///  * [PreferredSizeWidget], the interface which this widget implements to expose
///    its preferred size.
///  * [AppBar] and [TabBar], which implement PreferredSizeWidget.
class PreferredSize extends StatelessWidget implements PreferredSizeWidget {
  /// Creates a widget that has a preferred size.
  const PreferredSize({
    Key key,
    @required this.child,
    @required this.preferredSize,
  }) : super(key: key);

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.child}
  final Widget child;

  @override
  final Size preferredSize;

  @override
  Widget build(BuildContext context) => child;
}

其中一个界面代码如下,其他类似,结构都差不多


import 'package:flutter/material.dart';
import '../models/models.dart' show PurchaseData;


class PurchasePages extends StatelessWidget {
  final _purchasedata = PurchaseData.mock().demos;
  final int _itemLength = PurchaseData.mock().demos.length;

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
        itemCount: _itemLength,
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            childAspectRatio: 2/1.5),
        itemBuilder: (BuildContext context,int index){
          return InkWell(
            radius: 0.0,
            highlightColor:Colors.transparent,
            onTap: _purchasedata[index].onPressed,
            child: Padding(
              padding: EdgeInsets.only(top:20),
              child: Column(
                children: <Widget>[
                  Image.asset(_purchasedata[index].avater,width: 45.0,height: 45.0,),
                  SizedBox(height: 5.0,),
                  Text(_purchasedata[index].title),
                ],
              ),
            ),
          );
        });
  }
}

模拟数据文件,代码如下。 其实这边可以封装一下。目前没有做优化,优先把功能给先做出来。

/**
 * @Author: zhouge
 * @Description:
 * @Date: Created in 15:27 2020-10-18
 * @Modified By:
 **/
import 'package:flutter/material.dart';

// 构造函数
class BasicItem {
  final String title;
  final String avater;
  final bool isShowicon;
  final List<Widget> widget;
  final VoidCallback onPressed;

  BasicItem({
    this.isShowicon,
    this.widget,
    this.title,
    this.avater,
    this.onPressed,
  });
}

// 采购界面数据
class PurchaseData {
  final List<BasicItem> demos = [
    BasicItem(
        title: '采购收货',
        avater: 'assets/images/icon_nocome_alllot.png',
        isShowicon: true,
        onPressed: () {
          print('采购收货');
        }),
    BasicItem(
        title: '扫码收货',
        avater: 'assets/images/icon_scan_inapection.png',
        isShowicon: true,
        onPressed: () {
          print('扫码收货');
        }),
    BasicItem(
        title: '扫码入库',
        avater: 'assets/images/icon_purchase_in_store.png',
        isShowicon: true,
        onPressed: () {
          print('扫码入库');
        }),
    BasicItem(
        title: '采购仓退',
        avater: 'assets/images/icon_warehouse_return.png',
        isShowicon: true,
        onPressed: () {
          print('采购仓退');
        }),
    BasicItem(
        title: '来料检验',
        avater: 'assets/images/icon_exceed_patch_send.png',
        isShowicon: true,
        onPressed: () {
          print('来料检验');
        }),
    BasicItem(
        title: '平板检验',
        avater: 'assets/images/icon_iqc_check_pad.png',
        isShowicon: true,
        onPressed: () {
          print('平板检验');
        }),
    BasicItem(
        title: '快速收货',
        avater: 'assets/images/icon_fast_receipt_goods.png',
        isShowicon: true,
        onPressed: () {
          print('快速收货');
        }),
    BasicItem(
        title: '快速收货',
        avater: 'assets/images/icon_srm_fast_receipt_goods.png',
        isShowicon: true,
        onPressed: () {
          print('快速收货');
        }),
    BasicItem(
        title: '采购入库',
        avater: 'assets/images/icon_purchase_in_ware.png',
        isShowicon: true,
        onPressed: () {
          print('采购入库');
        }),
    BasicItem(
        title: '送货入库',
        avater: 'assets/images/icon_srm_scan_in_store.png',
        isShowicon: true,
        onPressed: () {
          print('送货入库');
        }),
  ];

  static PurchaseData mock() {
    return PurchaseData();
  }
}

大致长这个样子的,TabBar的背景颜色和AppBar已经区分开了

image.png

今天有空,先做到这里吧,毕竟业余时间太少,天天出差。
后面开始做功能,主要涉及到接口以及扫码功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341