效果圖:
前言:
各位同學(xué)大家好 boss直聘APP相信大家都用過吧, 今天給大家?guī)硪粋€開源項目模仿了boss直聘中的一些經(jīng)典頁面的實(shí)現(xiàn) 希望能幫助到各位flutter的學(xué)習(xí)里逆。原生安卓 iOS 實(shí)現(xiàn)都比較的簡單我這里就不展開講泵喘,今天主要講解flutter版本如何實(shí)現(xiàn) 廢話不多說我正式開始 歧蒋。
準(zhǔn)備工作:
安裝flutter環(huán)境 如果只是跑安卓設(shè)備 win系統(tǒng)就行了 要是同時運(yùn)行安卓和iOS 就需要mac電腦了 配置環(huán)境變量這邊就不展開講了大家可以看我之前的文章
需要用到的三方庫
dio: ^3.0.9 網(wǎng)絡(luò)請求庫
toast: ^0.1.5 toast 庫
flutter_swiper: ^1.1.6 輪播圖庫
具體代碼實(shí)現(xiàn)
1歡迎頁面就做了一個3秒的倒計時然后跳轉(zhuǎn)到首頁
import 'dart:async';
import 'package:flutter/material.dart';
import 'routes/Routes.dart';
/**
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間:2020年3月28日20:34:48
*
*
*/
void main() => runApp(new App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
onGenerateRoute:onGenerateRoute,
theme: new ThemeData(
primaryIconTheme: const IconThemeData(color: Colors.white),
brightness: Brightness.light,
primaryColor: new Color.fromARGB(255, 0, 215, 198),
accentColor: Colors.cyan[300],
),
home: Scaffold(
body: MainPage(),
)
// home: new MainPage(title: 'Boss直聘'),
);
}
}
class MainPage extends StatefulWidget {
MainPage({Key key}) : super(key: key);
@override
_MainPageState createState() {
return _MainPageState();
}
}
class _MainPageState extends State<MainPage> {
@override
void initState() {
super.initState();
int count = 0;
const period = const Duration(seconds: 1);
print('currentTime='+DateTime.now().toString());
Timer.periodic(period, (timer) {
//到時回調(diào)
print('afterTimer='+DateTime.now().toString());
count++;
if (count >= 3) {
//取消定時器,避免無限回調(diào)
timer.cancel();
timer = null;
toLoing();
}
});
}
@override
void dispose() {
super.dispose();
}
void toLoing()async{
//Navigator.pushNamed(context, "/my");
Navigator.of(context).pushNamedAndRemoveUntil(
"/my", ModalRoute.withName("/my"));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
color: Colors.green,
child: Center(
child: Text("BOSS 直聘",style: TextStyle(
fontSize: 30,
color: Colors.white
),
),
),
);
}
}
這里的跳轉(zhuǎn)我們要用
Navigator.of(context).pushNamedAndRemoveUntil(
"/my", ModalRoute.withName("/my"));
這種路由跳轉(zhuǎn)來清除所有的 widget 這樣我們在回退到主頁再次點(diǎn)擊返回鍵就能退出正app
然后是主頁的代碼的實(shí)現(xiàn)
import 'package:flutter/material.dart';
import 'pages/chat_page.dart';
import 'pages/company_page.dart';
import 'pages/mine_page.dart';
import 'pages/job_page.dart';
import 'layout_type.dart';
class My extends StatefulWidget {
My({Key key, this.title}) : super(key: key);
final String title;
@override
_MyState createState() => new _MyState();
}
class _MyState extends State<My> {
LayoutType _layoutSelection = LayoutType.job;
Color _colorTabMatching({LayoutType layoutSelection}) {
return _layoutSelection == layoutSelection ? Colors.cyan[300] : Colors.grey;
}
BottomNavigationBarItem _buildItem(
{String icon, LayoutType layoutSelection}) {
String text = layoutName(layoutSelection);
return BottomNavigationBarItem(
icon: new Image.asset(
icon,
width: 35.0,
height: 35.0,
),
title: Text(
text,
style: TextStyle(
color: _colorTabMatching(layoutSelection: layoutSelection),
),
),
);
}
Widget _buildButtonNavBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
_buildItem(
icon: _layoutSelection == LayoutType.job
? "images/ic_main_tab_find_pre.png"
: "images/ic_main_tab_find_nor.png",
layoutSelection: LayoutType.job),
_buildItem(
icon: _layoutSelection == LayoutType.company
? "images/ic_main_tab_company_pre.png"
: "images/ic_main_tab_company_nor.png",
layoutSelection: LayoutType.company),
_buildItem(
icon: _layoutSelection == LayoutType.chat
? "images/ic_main_tab_contacts_pre.png"
: "images/ic_main_tab_contacts_nor.png",
layoutSelection: LayoutType.chat),
_buildItem(
icon: _layoutSelection == LayoutType.mine
? "images/ic_main_tab_my_pre.png"
: "images/ic_main_tab_my_nor.png",
layoutSelection: LayoutType.mine),
],
onTap: _onSelectTab,
);
}
void _onLayoutSelected(LayoutType selection) {
setState(() {
_layoutSelection = selection;
});
}
void _onSelectTab(int index) {
switch (index) {
case 0:
_onLayoutSelected(LayoutType.job);
break;
case 1:
_onLayoutSelected(LayoutType.company);
break;
case 2:
_onLayoutSelected(LayoutType.chat);
break;
case 3:
_onLayoutSelected(LayoutType.mine);
break;
}
}
Widget _buildBody() {
LayoutType layoutSelection = _layoutSelection;
switch (layoutSelection) {
case LayoutType.job:
return JobPage();
case LayoutType.company:
return CompanyPage();
case LayoutType.chat:
return ChatPage();
case LayoutType.mine:
return MinePage();
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody(),
bottomNavigationBar: _buildButtonNavBar(),
);
}
}
我們通過 BottomNavigationBar 來做底部的tab的切換 圖片資源存放在assets 下面的images 目錄下(沒有此目錄需要自己創(chuàng)建)
在body組件這里來添加對應(yīng)的要顯示的widget (包括首頁 職位 公司 消息 我的 )
Widget _buildBody() {
LayoutType layoutSelection = _layoutSelection;
switch (layoutSelection) {
case LayoutType.job:
return JobPage();
case LayoutType.company:
return CompanyPage();
case LayoutType.chat:
return ChatPage();
case LayoutType.mine:
return MinePage();
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody(),
bottomNavigationBar: _buildButtonNavBar(),
);
}
}
到此就實(shí)現(xiàn)了主要的tab切換 和widget 頁面的加載
然后我們對各個頁面你的widget 的UI布局和數(shù)據(jù)獲取的的實(shí)現(xiàn)進(jìn)行講解說明
職位模塊 具體代碼實(shí)現(xiàn)
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../bean/positioninfo.dart';
import '../network/servicepath.dart';
import '../utils/ToastUtil.dart';
/***
*
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間:2020年3月9日00:40:10
* 類說明:職位
*
*/
class JobPage extends StatefulWidget {
JobPage({Key key}) : super(key: key);
@override
_JobPageState createState() {
return _JobPageState();
}
}
class _JobPageState extends State<JobPage> {
List _getdata=[];
Data data=null ;
@override
void initState() {
super.initState();
getInfo();
}
@override
void dispose() {
super.dispose();
}
void getInfo() async {
getPositionInfo().then((value){
setState(() {
PositionInfo positionInfo=value;
String msg=positionInfo.msg;
int code =positionInfo.code;
if(code==200){
_getdata=positionInfo.data;
print(_getdata);
ToastUtil.showinfo(context, msg);
}else{
ToastUtil.showinfo(context, msg);
}
});
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("職位",style:
TextStyle(
color: Colors.white,
fontSize: 20
),),
centerTitle: true,
),
body: Container(
child: new ListView.builder(
itemCount: (_getdata == null) ? 0 : _getdata.length,
itemBuilder: (BuildContext context , int position){
/* data=_getdata[position];
return JobList(data);*/
return getItem(position);
//getItem(position);
}),
),
);
}
Widget getItem(int index){
data=_getdata[index];
return new Padding(padding: EdgeInsets.only(
top: 3.0,
left: 5.0,
right: 5.0,
bottom: 3.0
),
child: new SizedBox(
child: Card(
elevation: 0.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Row(
children: <Widget>[
new Padding(padding: EdgeInsets.only(
top: 10.0,
left: 10.0,
bottom: 5.0
),
child: new Text(data.name),
),
new Expanded(
child:Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Padding(padding: EdgeInsets.only(
right: 10.0
),
child: Text(
data.salary,
style: TextStyle(
color: Colors.red
),
),
)
],
)
),
],
),
new Container(
child: new Text(data.name+data.size,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 20.0,
color: Colors.grey
),
),
margin: EdgeInsets.only(
top: 5.0,
left: 10.0,
bottom: 5.0
),
),
new Divider(),
new Row(
children: <Widget>[
new Padding(padding: EdgeInsets.only(
top: 5.0,
left: 10.0,
right: 5.0,
bottom: 15.0,
),
child: new Text(
data.username+"|"+data.title,
style: TextStyle(
color: new Color.fromARGB(255, 0, 215, 198)
),
),
)
],
)
],
)
),
],
),
),
),
);
}
}
主要實(shí)現(xiàn)就是listview列表組件加載item item里面是嵌套了Card 組件在在外層里面分別人在用Row組件嵌套
Column 組件來實(shí)現(xiàn)這個item的布局
網(wǎng)絡(luò)請求的封裝
import 'package:bosszhiping_tab/bean/messageinfo.dart';
import 'package:dio/dio.dart';
import '../config/api.dart';
import '../bean/positioninfo.dart';
import '../bean/companyinfo.dart';
import '../bean/companydetails.dart';
import '../bean/back_info.dart';
/**
* 獲取主頁數(shù)據(jù)
*
*
*/
Future getPositionInfo()async{
try{
Dio dio=new Dio();
Response res= await dio.get(Api.POSITIONINFO);
PositionInfo positionInfo=PositionInfo.fromJson(res.data);
print(res.data.toString());
return positionInfo;
}catch(e){
return print(e);
}
}
/**
* 獲取消息數(shù)據(jù)
*
*
*/
Future getmessageinfo() async{
try{
Dio dio=new Dio();
Response response=await dio.get(Api.MESSAGEINFO);
MessageInfo messageInfo=MessageInfo.fromJson(response.data);
print(response.data.toString());
return messageInfo;
}catch(e){
return print(e);
}
}
/**
*
* 獲取公司信息數(shù)據(jù)
*
*/
Future getcompanyInfo()async{
try{
Dio dio=new Dio();
Response response=await dio.get(Api.COMPANY_INFO);
Company companyInfo=Company.fromJson(response.data);
print(response.data.toString());
return companyInfo;
}catch(e){
return print(e);
}
}
/***
*
* 公司詳細(xì)信息
*
*
*/
Future getcomanydetails(var data)async{
try{
Dio dio=new Dio();
Response response=await dio.get(Api.COMPAN_DETAILS,queryParameters: data);
print("comdetails ----- > "+response.data.toString());
Comdetails comdetails=Comdetails.fromJson(response.data);
return comdetails;
}catch(e){
print(e);
}
}
/**
*
*
* 提交職位信息
*
*/
Future addPositionInfo(var data)async{
try{
Dio dio=new Dio();
Response response=await dio.post(Api.ADD_POSITION_INFO,queryParameters: data);
print(response.data);
BackInfo backInfo=BackInfo.fromJson(response.data);
return backInfo;
}catch(e){
print(e);
}
}
網(wǎng)絡(luò)請求方法的調(diào)用
void initState() {
super.initState();
getInfo();
}
@override
void dispose() {
super.dispose();
}
void getInfo() async {
getPositionInfo().then((value){
setState(() {
PositionInfo positionInfo=value;
String msg=positionInfo.msg;
int code =positionInfo.code;
if(code==200){
_getdata=positionInfo.data;
print(_getdata);
ToastUtil.showinfo(context, msg);
}else{
ToastUtil.showinfo(context, msg);
}
});
});
}
然后我們刷新數(shù)據(jù) 顯示在listview的item組件里面的就OK了
剩下的一些界面我就把代碼貼出來給大家看看篇幅是太長了
公司模塊 具體代碼實(shí)現(xiàn)
import 'package:flutter/material.dart';
import '../bean/companyinfo.dart';
import '../network/servicepath.dart';
import '../utils/ToastUtil.dart';
import 'company/company_details.dart';
/**
*
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間:
* 類說明:公司信息
*
*
*
*/
class CompanyPage extends StatefulWidget {
CompanyPage({Key key}) : super(key: key);
@override
_CompanyPageState createState() {
return _CompanyPageState();
}
}
class _CompanyPageState extends State<CompanyPage> {
List getdata;
Data _data=null;
@override
void initState() {
super.initState();
getcompanyinfo();
}
void getcompanyinfo(){
getcompanyInfo().then((value){
setState(() {
Company company=value;
String msg=company.msg;
int code=company.code;
if(code==200){
getdata=company.data;
ToastUtil.showinfo(context, msg);
}else{
ToastUtil.showinfo(context, msg);
}
});
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("公司",style:
TextStyle(
color: Colors.white,
fontSize: 20
),),
centerTitle: true,
),
body: Container(
child: ListView.builder(
//itemCount: 3,
itemCount: (getdata==null)?0:getdata.length,
itemBuilder: (BuildContext context, int position){
return getItem(position);
}),
),
);
}
//公司信息 item 布局
Widget getItem(int index){
_data =getdata[index];
print(_data.hot);
return GestureDetector(
child: new Padding(
padding: const EdgeInsets.only(
top: 3.0,
left: 5.0,
right: 5.0,
bottom: 3.0
),
child: SizedBox(
child: new Card(
elevation: 0.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Padding(padding: const EdgeInsets.only(
top: 10.0,
left: 15.0,
right: 15.0,
bottom: 0.0
),
child: Image.network(_data.logo,
width: 50.0,
height: 100.0,
),
),
Expanded(
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Container(
child: Text(_data.name,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 15.0,
),
),
margin: const EdgeInsets.only(top: 10.0,bottom: 5.0),
),
new Padding(padding: const EdgeInsets.only(
top: 5.0,
left: 0.0,
right: 5.0,
bottom: 5.0,
),
child: Text(_data.location,
style: TextStyle(
fontSize: 13.0,
color: Colors.grey
),
),),
new Padding(padding: const EdgeInsets.only(
top: 5.0,
left: 0.0,
right: 5.0,
bottom: 5.0,
),
child: Text(
_data.type+"|"+_data.size+"|"+_data.employee,
style: TextStyle(
fontSize: 13.0,
color: Colors.grey
),
),),
new Divider(
height: 2.0,
color: Colors.black54,
),
Row(
children: <Widget>[
new Padding(padding: const EdgeInsets.only(
top: 5.0,
left: 0.0,
right: 5.0,
bottom: 15.0
),
child: Text("熱招"+_data.hot+"等"+_data.count+"個職位",
style: TextStyle(
fontSize: 13.0,
color: Colors.grey
),
),
),
new Expanded(child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Padding(padding: const EdgeInsets.only(
bottom: 8.0
),
child: const Icon(
Icons.keyboard_arrow_right,
color: Colors.grey,
),
)
],
)
)
],
)
],
)),
],
),
),
),
),
onTap: (){
setState(() {
onItemclick(index);
});
},
);
}
void onItemclick(int index){
_data =getdata[index];
print("獲取到的頭ID"+_data.id.toString());
Navigator.of(context).pushNamed("company_details" ,arguments: {"id":_data.id});
}
}
消息模塊 具體代碼實(shí)現(xiàn)
import 'package:flutter/material.dart';
import '../network/servicepath.dart';
import '../bean/messageinfo.dart';
import '../utils/ToastUtil.dart';
/**
*
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間:2020年3月15日22:55:51
* 類說明:消息模塊
*
*
*/
class ChatPage extends StatefulWidget {
ChatPage({Key key}) : super(key: key);
@override
_ChatPageState createState() {
return _ChatPageState();
}
}
class _ChatPageState extends State<ChatPage> {
List getdata=[];
Data _data=null;
@override
void initState() {
super.initState();
getMessageInfo();
}
void getMessageInfo()async{
getmessageinfo().then((value){
setState(() {
MessageInfo messageInfo=value;
String msg=messageInfo.msg;
int code=messageInfo.code;
if(code==200){
getdata=messageInfo.data;
ToastUtil.showinfo(context, msg);
}else{
ToastUtil.showinfo(context, msg);
}
});
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("消息",style:
TextStyle(
color: Colors.white,
fontSize: 20
),),
centerTitle: true,
),
body: Container(
child:new ListView.builder(
itemCount:(getdata == null)?0:getdata.length,
itemBuilder: (BuildContext context , int position){
return getItem(position);
}),
),
);
}
Widget getItem(int index){
_data=getdata[index];
return
SizedBox(
child: Card(
elevation: 0.0,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 20),
child: ClipOval(
child: Image.network(
_data.headportraiturl,
height: 40,
width: 40,
fit: BoxFit.cover,
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
child: new Text(_data.nickname,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 18.0,
color: Colors.black
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
new Container(
child: new Text(_data.companyname+"|"+_data.jobname,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 15.0,
color: Colors.grey
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
new Container(
child: new Text(_data.msg,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 12.0,
color: Colors.grey
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
],
),
)
],
),
new Padding(padding: const EdgeInsets.only(left: 5.0,right: 5.0),
child: new Divider(
height: 2.0,
color: Colors.black54,
),
)
],
),
),
);
Container(
child: new Padding(padding: EdgeInsets.only(
left: 2.0,
right: 2.0,
),
child: SizedBox(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 20),
child: ClipOval(
child: Image.network(
_data.headportraiturl,
height: 40,
width: 40,
fit: BoxFit.cover,
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
child: new Text(_data.nickname,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 18.0,
color: Colors.black
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
new Container(
child: new Text(_data.companyname+"|"+_data.jobname,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 15.0,
color: Colors.grey
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
new Container(
child: new Text(_data.msg,
textAlign: TextAlign.left,
style: new TextStyle(
fontSize: 12.0,
color: Colors.grey
),
),
margin: EdgeInsets.only(
top: 2.0,
left: 10.0,
bottom: 2.0
),
),
],
),
)
],
),
new Padding(padding: const EdgeInsets.only(left: 5.0,right: 5.0),
child: new Divider(
height: 2.0,
color: Colors.black54,
),
)
],
),
/* child: Card(
elevation: 0.0,
),*/
),
)
);
}
}
個人中心(我的模塊)具體代碼實(shí)現(xiàn)
import 'package:flutter/material.dart';
import 'package:bosszhiping_tab/mywiget/menu_item.dart';
import 'package:bosszhiping_tab/mywiget/contact_item.dart';
class MinePage extends StatefulWidget {
MinePage({Key key}) : super(key: key);
@override
_MinePageState createState() {
return _MinePageState();
}
}
class _MinePageState extends State<MinePage> {
final double _appBarHeight = 180.0;
final String _userHead =
'https://img.bosszhipin.com/beijin/mcs/useravatar/20171211/4d147d8bb3e2a3478e20b50ad614f4d02062e3aec7ce2519b427d24a3f300d68_s.jpg';
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
backgroundColor: new Color.fromARGB(255, 242, 242, 245),
body: new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(
expandedHeight: _appBarHeight,
flexibleSpace: new FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
background: new Stack(
fit: StackFit.expand,
children: <Widget>[
const DecoratedBox(
decoration: const BoxDecoration(
gradient: const LinearGradient(
begin: const Alignment(0.0, -1.0),
end: const Alignment(0.0, -0.4),
colors: const <Color>[
const Color(0x00000000),
const Color(0x00000000)
],
),
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
new Expanded(
flex: 3,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Padding(
padding: const EdgeInsets.only(
top: 30.0,
left: 30.0,
bottom: 15.0,
),
child: new Text(
'Rei Ki',
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 35.0),
),
),
new Padding(
padding: const EdgeInsets.only(
left: 30.0,
),
child: new Text(
'在職-不考慮機(jī)會',
style: new TextStyle(
color: Colors.white, fontSize: 15.0),
),
),
],
),
),
new Expanded(
flex: 1,
child: new Padding(
padding: const EdgeInsets.only(
top: 40.0,
right: 30.0,
),
child: new CircleAvatar(
radius: 35.0,
backgroundImage: new NetworkImage(_userHead),
),
),
)
],
),
],
),
),
),
new SliverList(
delegate: new SliverChildListDelegate(
<Widget>[
new Container(
color: Colors.white,
child: new Padding(
padding: const EdgeInsets.only(
top: 10.0,
bottom: 10.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
new ContactItem(
count: '696',
title: '溝通過',
),
new ContactItem(
count: '0',
title: '面試',
),
new ContactItem(
count: '71',
title: '已投遞',
),
new ContactItem(
count: '53',
title: '感興趣',
),
],
),
),
),
new Container(
color: Colors.white,
margin: const EdgeInsets.only(top: 10.0,bottom: 20),
child: Column(
children: <Widget>[
new MenuItem(
icon: Icons.face,
title: '體驗新版本',
onPressed: (){
print("體驗新版本 ---- >");
},
),
new MenuItem(
icon: Icons.print,
title: '我的微簡歷',
),
new MenuItem(
icon: Icons.archive,
title: '附件簡歷',
),
new MenuItem(
icon: Icons.home,
title: '管理求職意向',
),
new MenuItem(
icon: Icons.title,
title: '提升簡歷排名',
),
new MenuItem(
icon: Icons.chat,
title: '牛人問答',
),
new MenuItem(
icon: Icons.assessment,
title: '關(guān)注公司',
),
new MenuItem(
icon: Icons.add_shopping_cart,
title: '錢包',
onPressed: (){
Navigator.of(context).pushNamed("wallet");
},
),
new MenuItem(
icon: Icons.security,
title: '隱私設(shè)置',
),
new MenuItem(
icon: Icons.add,
title: '添加職位信息',
onPressed: (){
Navigator.of(context).pushNamed("addpositioninfo");
print("添加職位信息");
},
),
],
),
),
],
),
)
],
),
);
}
}
個人中心模塊橫向布局的封裝
import 'package:flutter/material.dart';
/***
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間:2020年2月5日18:30:50
* 類說明:橫向布局的 封裝
*
*/
class ContactItem extends StatelessWidget {
ContactItem({Key key, this.count, this.title, this.onPressed})
: super(key: key);
final String count;
final String title;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: onPressed,
child: new Column(
children: [
new Padding(
padding: const EdgeInsets.only(
bottom: 4.0,
),
child: new Text(count, style: new TextStyle(fontSize: 18.0)),
),
new Text(title,
style: new TextStyle(color: Colors.black54, fontSize: 14.0)),
],
),
);
}
}
個人中心縱向布局的封裝
import 'package:flutter/material.dart';
/**
* 創(chuàng)建人:xuqing
* 創(chuàng)建時間 :2020年2月4日21:39:42
* 類說明:縱向不布局的封裝
*
*/
class MenuItem extends StatelessWidget {
final IconData icon;
final String title;
final VoidCallback onPressed;
MenuItem({Key key, this.icon, this.title, this.onPressed}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return new GestureDetector(
onTap: onPressed,
child: new Column(
children: <Widget>[
new Padding(
padding: EdgeInsets.only(
left: 20.0,
top: 12.0,
right: 20.0,
bottom: 10.0,
),
child: new Row(
children: <Widget>[
new Padding(padding: const EdgeInsets.only(
right: 8.0,
),
child:new Icon(
icon,
color: Colors.black54,
),
),
new Expanded(
child: new Text(
title,
style: new TextStyle(color: Colors.black54,fontSize: 16.0),
)
),
new Icon(
Icons.chevron_right,
color: Colors.grey,
)
],
)
),
new Padding(padding: const EdgeInsets.only(left: 20.0,right: 20.0),
child: new Divider(
height: 2.0,
color: Colors.black54,
),
)
],
),
);
}
}
還有公司詳情頁面 代碼具體看源代碼
最后總結(jié):
整個學(xué)習(xí)的項目采用了mvc 架構(gòu)模式去編寫鸠删,后臺接口返回的json數(shù)據(jù)通過格式化轉(zhuǎn)成數(shù)據(jù)模型類來處理
對于各個分區(qū)模塊也做了適當(dāng)?shù)拇a分離使得嵌套多層的布局代碼得到簡化庆杜。我也是一個正在學(xué)習(xí)flutter框的碼農(nóng)希望我的項目能幫助到各位同學(xué) 以后我還會貢獻(xiàn)更多有用的代碼分享給大家箱蝠。各位同學(xué)如果覺得文章還不錯 ,麻煩給關(guān)注和star眷蜈,小弟在這里謝過啦 , 也可以加我個人QQ/微信(1693891473)
項目地址 (flutter ):https://github.com/xq19930522/flutter_bosstap
服務(wù)端地址(springboot): https://github.com/xq19930522/bosstabservice