原理:通过Function实现index的回调
导航栏代码
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:oktoast/oktoast.dart';
import 'package:social_im/common/globalEventBus.dart';
import 'package:social_im/http/api.dart';
import 'package:social_im/http/rxhttp.dart';
import 'package:social_im/http/utils/NetUtils.dart';
import 'package:social_im/http/utils/response.dart';
import 'package:social_im/widget/loading_dialog.dart';
import '../../camera_picker/constants/constants.dart';
import '../../common/Global.dart';
import '../../common/colors.dart';
import '../../constant/dimens.dart';
import '../../http/net_callback.dart';
import '../../models/cloudCustomDataBean.dart';
import '../../utils/image_utile.dart';
import '../widget/myText.dart';
import 'MyDragBottle.dart';
import 'MyThrowBottle.dart';
import 'data/DriftBottleList.dart';
import '../../generated/l10n.dart';
import 'data/bottle_model.dart';
import 'dialog/chat_dialog.dart';
//我的瓶子导航栏
class MyBottleNav extends StatefulWidget {
const MyBottleNav({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => MyBottleNavState();
}
class MyBottleNavState extends State<MyBottleNav>
with SingleTickerProviderStateMixin {
late TabController _tabController;
List<Chose> tabs = [];
int currentIndex = 0;
String inputCotent = '';
List<AssetEntity> assetss = [];
bool isScreening = false;
//取屏幕最大宽度和高度
final width = window.physicalSize.width;
final height = window.physicalSize.height;
DriftBottleList? driftBottleList;
late StreamSubscription<OnCloseBottleRefresh> _onCloseBottleRefresh;
@override
void initState() {
_getDriftBottleList();
super.initState();
tabs.add(Chose(title: S.current.bottle_thrown_bottles, position: 0));
tabs.add(Chose(title: S.current.bottle_picked_bottles, position: 1));
_tabController =
TabController(length: tabs.length, vsync: this, initialIndex: 0);
_tabController.addListener(() {
if (_tabController.index.toDouble() == _tabController.animation!.value) {
mySetState(() {
currentIndex = _tabController.index;
});
}
});
_onCloseBottleRefresh = EventBusUtil.listen((event) {
if (event.playType == CloudCustomDataBean.TYPE_DRIFT_BOTTLE) {
_getDriftBottleList();
if (mounted) {
setState(() {});
}
}
});
}
///获取瓶子列表
_getDriftBottleList() {
showLoadingDialog();
RxHttp<Response>()
..init()
..setBaseUrl(Api.BASE_API)
..setPath(Api.API_GET_DRIFT_BOTTLELIST)
..setCacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST)
..setJsonTransFrom((p0) => Response.fromJson(json.decoder.convert(p0)))
..call(
NetCallback(onNetFinish: (response) {
dismissLoadingDialog();
if (response.code == 200) {
driftBottleList = DriftBottleList.fromJson(response.data);
}
if (mounted) {
setState(() {});
}
}, onCacheFinish: (response) {
if (response.code == 200) {
driftBottleList = DriftBottleList.fromJson(response.data);
}
if (mounted) {
setState(() {});
}
}, onNetError: (code) {
dismissLoadingDialog();
showToast('${S.current.network_error_tips}[$code]');
}),
server: Servers.microServices);
}
@override
void dispose() {
dismissLoadingDialog();
_onCloseBottleRefresh.cancel();
super.dispose();
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.dark,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: ImageUtile.imageProvider(
'assets/images/bg_drift_my_bottle.png'),
fit: BoxFit.fill)),
child: Column(children: [
addHeadView(),
Container(
color: Colors.transparent,
padding: const EdgeInsets.only(
bottom: 15, left: 8, right: 8, top: 27),
child: TabBar(
isScrollable: false,
indicatorWeight: 2.4,
indicatorSize: TabBarIndicatorSize.label,
indicatorColor: const Color(0xFF6EA6F5),
labelColor: const Color(0xFF6EA6F5),
labelStyle: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
labelPadding: const EdgeInsets.only(
left: 8, right: 8, bottom: 12),
unselectedLabelColor: const Color(0xFF1A1A1A),
unselectedLabelStyle: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
controller: _tabController,
tabs: tabs.map((chose) {
return Stack(
clipBehavior: Clip.none,
alignment: Alignment.topRight,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(chose.title),
],
),
Positioned(
right: -10,
top: -10,
child: showMessageNumView(chose.position == 0
? driftBottleList?.down_no_read_num ?? 0
: driftBottleList?.up_no_read_num ?? 0))
],
);
}).toList()),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: tabs.map((chose) {
switch (chose.position) {
case 0:
return MyThrowBottle(
downList: driftBottleList?.downList ?? [],
onItemClicked: (index) {
showChatDialog(context, 2, index,
chatDialogModel: ChatDialogModel(
type: 0,
bottleModel: driftBottleList
?.downList![index] ??
BottleModel()));
},
);
case 1:
return MyDragBottle(
upList: driftBottleList?.upList ?? [],
onItemClicked: (index) {
showChatDialog(context, 1, index,
chatDialogModel: ChatDialogModel(
type: 1,
bottleModel: driftBottleList
?.upList![index] ??
BottleModel()));
});
default:
return Container();
}
}).toList()))
]))));
}
//头部按键
Widget addHeadView() {
return Container(
padding: EdgeInsets.only(top: Global.topHeight + 10),
color: Colors.transparent,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(left: 16, right: 10),
child: ImageUtile.imageWidget(
'assets/images/icon_back@2x.png',
width: 24,
height: 24)),
Text(S.current.bottle_my,
style: const TextStyle(
fontSize: Dimens.fontSize_16, color: Colors.black))
],
),
));
}
Widget showMessageNumView(messagesNum) {
return Container(
height: 18,
child: messagesNum > 0
? PhysicalModel(
color: Colors.transparent,
borderRadius: BorderRadius.circular(9),
clipBehavior: Clip.antiAlias,
child: Container(
color: CommonColors.getColorFA6300,
padding: const EdgeInsets.fromLTRB(6, 1, 6, 1),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ContentCenterText(
messagesNum > 99 ? '99+' : messagesNum.toString(),
11.0,
Colors.white)
])))
: null);
}
}
///选择对象model
class Chose {
const Chose({required this.title, required this.position});
final String title;
final int position;
}
重点部分,为什么要整合点击事件在导航栏这里,因为好看,好理解,逻辑比较顺,全局上点击
Expanded(
child: TabBarView(
controller: _tabController,
children: tabs.map((chose) {
switch (chose.position) {
case 0:
return MyThrowBottle(//扔瓶子界面
downList: driftBottleList?.downList ?? [],//第一个参数
onItemClicked: (index) {//第二个参数
showChatDialog(context, 2, index,
chatDialogModel: ChatDialogModel(
type: 0,
bottleModel: driftBottleList
?.downList![index] ??
BottleModel()));//当点击item时弹出弹窗
},
);
case 1:
return MyDragBottle(//捞瓶子界面
upList: driftBottleList?.upList ?? [],
onItemClicked: (index) {
showChatDialog(context, 1, index,
chatDialogModel: ChatDialogModel(
type: 1,
bottleModel: driftBottleList
?.upList![index] ??
BottleModel()));
});
default:
return Container();
}
}).toList()))
捞瓶子代码
import 'dart:ui';
import 'package:flutter/material.dart';
import '../../common/colors.dart';
import '../../generated/l10n.dart';
import '../../utils/date_util.dart';
import '../widget/myText.dart';
import '../widget/splitLine.dart';
import 'data/bottle_model.dart';
//捡的瓶子
class MyDragBottle extends StatefulWidget {
final List<BottleModel> upList;
final Function(int index)? onItemClicked;
const MyDragBottle({Key? key, required this.upList, this.onItemClicked})
: super(key: key);
@override
State<StatefulWidget> createState() => MyDragBottleState();
}
class MyDragBottleState extends State<MyDragBottle> {
//取屏幕最大宽度和高度
final width = window.physicalSize.width;
final height = window.physicalSize.height;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
Widget showMessageNumView(messagesNum) {
return Container(
height: 18,
child: messagesNum > 0
? PhysicalModel(
color: Colors.transparent,
borderRadius: BorderRadius.circular(9),
clipBehavior: Clip.antiAlias,
child: Container(
color: CommonColors.getColorFA6300,
padding: const EdgeInsets.fromLTRB(6, 1, 6, 1),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ContentCenterText(
messagesNum > 99 ? '99+' : messagesNum.toString(),
11.0,
Colors.white)
])))
: null);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
color: Colors.transparent,
home: widget.upList.isEmpty?Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: Container(
margin: const EdgeInsets.only(bottom: 120),
child: Column(children: [
ContentText(S.current.bottle_no_data, 14.0,
CommonColors.getTextWeakColor()),
TopPadding(30),
])),
)
],
):Scaffold(
backgroundColor: Colors.transparent,
body: Container(
color: Colors.transparent,
child: MediaQuery.removePadding(
removeTop: true,
context: context,
child: widget.upList.isEmpty
? Container()
: ListView.builder(
shrinkWrap: true,
itemCount: widget.upList.length,
itemBuilder: (BuildContext context, int index) {
BottleModel upList = widget.upList[index];
return GestureDetector(
onTap: () {
if (widget.onItemClicked != null) {
widget.onItemClicked!(index);
}
},
child: Stack(
alignment: Alignment.topRight,
children: [
if (index % 3 == 0)
Container(
width: width,
margin: const EdgeInsets.only(
top: 16, left: 16, right: 16),
padding: const EdgeInsets.only(
left: 16, top: 16, bottom: 8, right: 16),
decoration: BoxDecoration(
color: const Color(0xFFF8F9FF),
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Color(0xFFBCC0EE),
blurRadius: 1,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
upList.text!,
style: const TextStyle(
color: Color(0xFF333333),
fontSize: 18),
),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
DateUtil.formatDateMs(
upList.downTime! * 1000,
format: 'yyyy.MM.dd'),
style: const TextStyle(
color: Color(0xFF999999),
fontSize: 12),
),
)
],
),
),
if (index % 3 == 1)
Container(
width: width,
margin: const EdgeInsets.only(
top: 16, left: 16, right: 16),
padding: const EdgeInsets.only(
left: 16, top: 16, bottom: 8, right: 16),
decoration: BoxDecoration(
color: const Color(0xFFEDFAFF),
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Color(0xFFBCE2F1),
blurRadius: 1,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
upList.text!,
style: const TextStyle(
color: Color(0xFF333333),
fontSize: 18),
),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
DateUtil.formatDateMs(
upList.downTime! * 1000,
format: 'yyyy.MM.dd'),
style: const TextStyle(
color: Color(0xFF999999),
fontSize: 12),
),
)
],
),
),
if (index % 3 == 2)
Container(
width: width,
margin: const EdgeInsets.only(
top: 16, left: 16, right: 16),
padding: const EdgeInsets.only(
left: 16, top: 16, bottom: 8, right: 16),
decoration: BoxDecoration(
color: const Color(0xFFFBFFF2),
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Color(0xFFDBEBB6),
blurRadius: 1,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
upList.text!,
style: const TextStyle(
color: Color(0xFF333333),
fontSize: 18),
),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
DateUtil.formatDateMs(
upList.downTime! * 1000,
format: 'yyyy.MM.dd'),
style: const TextStyle(
color: Color(0xFF999999),
fontSize: 12),
),
)
],
),
),
Positioned(
top: 7,
right: 15,
child: showMessageNumView(upList.noReadNum),
)
],
),
);
})),
),
),
);
}
}
回调的重点代码
class MyDragBottle extends StatefulWidget {
final List<BottleModel> upList;
final Function(int index)? onItemClicked;//定义一个可回调的对象,里面带一个参数,回调这个参数
const MyDragBottle({Key? key, required this.upList, this.onItemClicked})
: super(key: key);
@override
State<StatefulWidget> createState() => MyDragBottleState();
}
ListView.builder(
shrinkWrap: true,
itemCount: widget.upList.length,
itemBuilder: (BuildContext context, int index) {
BottleModel upList = widget.upList[index];
return GestureDetector(
onTap: () {
if (widget.onItemClicked != null) {
widget.onItemClicked!(index);//当点击该item时回调该index给导航栏
}
},