You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
9.9 KiB

1 year ago
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:medicine_app/request_util.dart';
import 'package:medicine_app/search_page.dart';
import 'package:medicine_app/slide_page_route.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'medicine_detail_page.dart';
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).accentColor,
elevation: 2,
shadowColor: Theme.of(context).shadowColor,
toolbarHeight: 50,
title: TextButton(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.search_sharp,
size: 17,
),
Text('搜索')
],
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.grey.shade500),
shadowColor: MaterialStateProperty.all(Colors.transparent),
overlayColor: MaterialStateProperty.all(Colors.transparent),
minimumSize: MaterialStateProperty.all(Size.fromHeight(32)),
backgroundColor: MaterialStateProperty.all(Colors.white24.withOpacity(0.80)),
textStyle: MaterialStateProperty.all(TextStyle(fontSize: 13, letterSpacing: 2)),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)),
),
),
onPressed: () => Navigator.of(context).push(SlidePageRoute(builder: SearchMedicinePage())),
),
),
body: FutureBuilder(future: Future.sync(() {
return Request.getDio().get('/medicine/outlines');
}), builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map data = json.decode(snapshot.data.toString());
final List<dynamic> medicineList = data['data'];
return ListView.builder(
cacheExtent: 10,
padding: EdgeInsets.only(bottom: 30),
itemCount: medicineList.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index < medicineList.length) {
final Map medicine = medicineList[index];
final List<dynamic> medicineDetails = medicine['details'];
return Card(
color: Colors.grey[10],
shadowColor: Colors.grey[50],
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
borderOnForeground: false,
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
// 外边距
child: Container(
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
height: 250,
child: Column(
children: [
Expanded(
flex: 1,
child: ListTile(
title: Text(
"${medicine['name']}",
style: TextStyle(fontWeight: FontWeight.bold),
)),
),
Expanded(
flex: 3,
child: Builder(builder: (context) {
final int pageCount = (medicineDetails.length / 6).ceil();
final int maxPageCount = medicineDetails.length;
final controller = PageController();
return Padding(
padding: EdgeInsets.only(bottom: 3),
child: Stack(
alignment: Alignment.bottomCenter,
children: [
SmoothPageIndicator(
controller: controller, // PageController
count: pageCount,
effect: WormEffect(dotWidth: 7, dotHeight: 7)),
PageView(
children: List.generate(pageCount, (index) {
return GridView.count(
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 3,
mainAxisSpacing: 20,
crossAxisSpacing: 35,
padding: EdgeInsets.symmetric(
horizontal: 30,
),
children: medicineDetails
.sublist(index * 6, min((index + 1) * 6, maxPageCount))
.map((e) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(SlidePageRoute(
builder: MedicineDetailPage(name: "${e['text']}"),
));
},
child: Column(
children: [
Expanded(
flex: 2,
child: null != e['icon']
? CircleAvatar(
backgroundColor:
Theme.of(context).secondaryHeaderColor,
backgroundImage: Image.network(
e['icon'],
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) {
return child;
} else {
return Icon(Icons.downloading_outlined);
}
},
).image,
radius: 50,
)
: CircleAvatar(
backgroundColor:
Theme.of(context).secondaryHeaderColor,
)),
Expanded(
flex: 1,
child: Text(
'${e['text']}',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
color: Colors.black.withAlpha(170)),
),
)
],
),
);
}).toList());
}).toList(),
controller: controller,
)
],
),
);
}))
],
),
),
);
} else {
return Container(
alignment: Alignment.center,
child: Text(
'- 没有更多了 -',
style: TextStyle(color: Colors.grey),
),
);
}
});
} else {
return Center(
child: SpinKitFadingCircle(
color: Theme.of(context).primaryColor,
size: 32,
));
}
}),
);
}
}