之前有提過要仿公司 某款產(chǎn)品的UI,用Flutter剛好試試手旅东。首頁登陸都做了灭抑,有幾個(gè)坑記錄一下。
這里展示的功能其實(shí)都應(yīng)該從后端獲取的抵代,后端這一塊目前沒做腾节,后面有空了補(bǔ)起來。
相對(duì)比較簡單荤牍,主要涉及到以下幾點(diǎn):
1案腺、TabBar上無法設(shè)置顏色和高度,標(biāo)準(zhǔn)庫默認(rèn)與AppBar顏色一致参淫。
2救湖、GridView的基本運(yùn)用。
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))
]),
),
//可以單獨(dú)設(shè)置涎才,固定高度為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('生產(chǎn)管理'),
Text('倉庫管理'),
Text('銷售管理'),
],
),
)
)),
body: Container(
color: Colors.white,
child: TabBarView(
children: <Widget>[
PurchasePages(),
WorkPages(),
WareHousePages(),
SalesPages(),
],
),
)
));
}
}
這里的bottom下沒有直接TabBar鞋既,而且用PreferredSize來進(jìn)行取代。如果直接用TabBar的話耍铜,顏色會(huì)與頂部一致邑闺,并且無法更改。
這里可以看到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,點(diǎn)進(jìn)去看下伴挚,經(jīng)過觀察靶衍,我們可以使用它重新布局畫面。
記住一定要在Material下茎芋,單獨(dú)設(shè)置顏色
// 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;
}
其中一個(gè)界面代碼如下颅眶,其他類似,結(jié)構(gòu)都差不多
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),
],
),
),
);
});
}
}
模擬數(shù)據(jù)文件田弥,代碼如下涛酗。 其實(shí)這邊可以封裝一下。目前沒有做優(yōu)化,優(yōu)先把功能給先做出來商叹。
/**
* @Author: zhouge
* @Description:
* @Date: Created in 15:27 2020-10-18
* @Modified By:
**/
import 'package:flutter/material.dart';
// 構(gòu)造函數(shù)
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,
});
}
// 采購界面數(shù)據(jù)
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: '來料檢驗(yàn)',
avater: 'assets/images/icon_exceed_patch_send.png',
isShowicon: true,
onPressed: () {
print('來料檢驗(yàn)');
}),
BasicItem(
title: '平板檢驗(yàn)',
avater: 'assets/images/icon_iqc_check_pad.png',
isShowicon: true,
onPressed: () {
print('平板檢驗(yàn)');
}),
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();
}
}
大致長這個(gè)樣子的燕刻,TabBar的背景顏色和AppBar已經(jīng)區(qū)分開了
今天有空,先做到這里吧剖笙,畢竟業(yè)余時(shí)間太少卵洗,天天出差。
后面開始做功能枯途,主要涉及到接口以及掃碼功能忌怎。