之前有提过要仿公司 某款产品的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已经区分开了
今天有空,先做到这里吧,毕竟业余时间太少,天天出差。
后面开始做功能,主要涉及到接口以及扫码功能。