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
200 lines
9.9 KiB
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,
|
|
));
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
}
|