提交 35f1cb64 authored 作者: yueweilu's avatar yueweilu

图书馆界面 (滑动到指定位置未完成)

上级 ae8cc6b7
......@@ -4,5 +4,5 @@ keyPassword=123456
keyAlias=zijing
#storeFile=/Users/apple/zijiing_key.jks
storeFile=zijiing_key.jks
\ No newline at end of file
storeFile=/Users/apple/zijiing_key.jks
#storeFile=zijiing_key.jks
\ No newline at end of file
......@@ -5,14 +5,17 @@ class CategoryModel {
CategoryModel({
this.categoryId,
this.name,
this.selected = false,
});
CategoryModel.fromJson(dynamic json) {
categoryId = json['category_id'];
name = json['name'];
selected = false;
}
num? categoryId;
String? name;
late bool selected;
CategoryModel copyWith({ num? categoryId,
String? name,
}) => CategoryModel( categoryId: categoryId ?? this.categoryId,
......@@ -348,13 +351,13 @@ class BookDetailModel {
class FilterModel {
FilterModel({
required this.id,
required this.name,
this.id,
this.name,
this.selected = false
});
String id;
String name;
String? id;
String? name;
late bool selected = false;
}
......
part of library;
class LibraryContentController extends GetxController {
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
// 图书列表数据
List<CourseModel> books = [];
final int _limit = 20;
int _page = 1;
bool _noMore = false;
@override
void onClose() {
refreshController.dispose();
super.onClose();
}
/// 收藏 与 取消收藏
void love({
required String bookId,
required num isCollection
}) async {
if (isCollection == 0){
isCollection = 1;
}
else{
isCollection = 0;
}
bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
if (result) {
onRefresh();
}
}
/// 获取图书列表数据
Future<void> _getBooks([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.books(
page: _page,
limit: _limit, categoryId: '',
);
// 如果是刷新 清理数据
if (isRefresh) books.clear();
books.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getBooks(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getBooks();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
}
\ No newline at end of file
......@@ -9,11 +9,39 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
// 广告数组
List<AdModel> ads = [];
late LabelModel selectedLabel = LabelModel();
// 选中标签
late FilterModel selectedLabel = FilterModel();
// 选中分类
late FilterModel selectedCategory = FilterModel();
// 选中是否收费
late FilterModel selectedFree = FilterModel();
late FilterModel selectedDown = FilterModel();
late TabController tabController = TabController(length:categories.length, vsync: this);
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
// 图书列表数据
List<CourseModel> books = [];
List<FilterModel> filterCategories = [];
List<FilterModel> filterLabels = [];
List<FilterModel> filterFree = [
FilterModel(id: '0', name: '收费',selected: false),
FilterModel(id: '1', name: '免费',selected: false)
];
List<FilterModel> filterDown = [
FilterModel(id: 'read_num', name: '读过'),
FilterModel(id: 'rating', name: '评分')
];
final int _limit = 20;
int _page = 1;
bool _noMore = false;
late AnimationController _controller;
......@@ -60,12 +88,68 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
@override
void onClose() {
tabController.dispose();
refreshController.dispose();
super.onClose();
}
/// 重置
void resetFilter() {
for(FilterModel model in filterCategories){
model.selected = false;
}
filterCategories.first.selected = true;
for(FilterModel model in filterLabels){
model.selected = false;
}
filterLabels.first.selected = true;
for(FilterModel model in filterFree){
model.selected = false;
}
for(FilterModel model in filterDown){
model.selected = false;
}
update();
}
/// 确定
void sureFilter(){
WidgetsBinding.instance!.addPostFrameCallback((_) {
tabController.animateTo(3); // 你想要的标签索引
});
update();
for(FilterModel model in filterCategories){
if (model.selected){
selectedCategory = model;
}
}
for(FilterModel model in filterLabels){
if(model.selected){
selectedLabel= model;
}
}
for(FilterModel model in filterFree){
if(model.selected){
selectedFree= model;
}
}
for(FilterModel model in filterDown){
if(model.selected){
selectedDown= model;
}
}
void selectLabel(LabelModel model){
for (LabelModel m in labels){
onRefresh();
}
void selectLabel(FilterModel model){
for (FilterModel m in filterLabels){
m.selected = false;
}
model.selected = true;
......@@ -84,15 +168,88 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
categories = await LibraryAPI.categories();
tabController.dispose();
tabController = TabController(length:categories.length, vsync: this);
categories.first.selected = true;
filterCategories = categories.map((model) {
return FilterModel(id: model.categoryId.toString(), name: model.name??'',selected: model.selected);
}).toList();
print('===========$filterCategories');
update();
}
/// 获取标签数据
void _getLabels() async {
labels = await LibraryAPI.labels();
selectedLabel = labels.first;
filterLabels = labels.map((model) {
return FilterModel(id: model.labelId.toString(), name: model.name??'',selected: model.selected);
}).toList();
selectedLabel = filterLabels.first;
selectedLabel.selected = true;
update(['label']);
}
/// 收藏 与 取消收藏
void love({
required String bookId,
required num isCollection
}) async {
if (isCollection == 0){
isCollection = 1;
}
else{
isCollection = 0;
}
bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
if (result) {
onRefresh();
}
}
/// 获取图书列表数据
Future<void> _getBooks([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.books(
page: _page,
limit: _limit,
categoryId: selectedCategory.id??'',
labelId: selectedLabel.id??'',
isFree: selectedFree.id??'',
sortField: selectedDown.id??''
);
// 如果是刷新 清理数据
if (isRefresh) books.clear();
books.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getBooks(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getBooks();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
......
library library;
import 'package:azlistview/azlistview.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_list_view/flutter_list_view.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
......@@ -14,7 +16,6 @@ import '../../models/index.dart';
import '../../routes/index.dart';
import '../../widgets/index.dart';
import '../course/index.dart';
import '../library_content/index.dart';
import '../study/index.dart';
......@@ -26,4 +27,3 @@ part 'widgets/content.dart';
part 'widgets/subject.dart';
part 'widgets/filter.dart';
part 'test.dart';
part 'content_controller.dart';
\ No newline at end of file
......@@ -38,37 +38,25 @@ class _LibraryPageState extends State<LibraryPage> {
children: [
_buildTab(controller),
_buildLabel(),
GetBuilder<LibraryContentController>(
init: LibraryContentController(),
builder:(contentController)=> Expanded(
Expanded(
child: CustomPullScrollView(
controller: contentController.refreshController,
onRefresh: contentController.onRefresh,
onLoading: contentController.onLoading,
child: CustomScrollView(
slivers: [
// 广告位
SliverToBoxAdapter(
child: Container(
color: Colors.red,
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: BuildBanner(items: controller.ads,),
),
),
SliverFillRemaining(
child: TabBarView(
controller: controller.tabController,
children: List.generate(controller.categories.length, (index){
print('=======================================$index');
return LibraryContentPage(controller: contentController,);
})
),
),
controller: controller.refreshController,
onRefresh: controller.onRefresh,
onLoading: controller.onLoading,
child: SingleChildScrollView(
child: Column(
children: [
controller.ads.isNotEmpty?Container(
color: Colors.cyan,
child: BuildBanner(items:controller.ads)
):const SizedBox(),
LibraryContentPage(controller: controller,)
],
),
),
),
),
)
],
),
Visibility(
......@@ -97,18 +85,19 @@ class _LibraryPageState extends State<LibraryPage> {
scrollDirection:Axis.horizontal ,
itemBuilder: (BuildContext context, int index){
return GestureDetector(
child: BuildLabelWidget(model: controller.labels[index],),
child: BuildLabelWidget(model: controller.filterLabels[index],),
onTap: (){
controller.selectLabel( controller.labels[index]);
controller.selectLabel( controller.filterLabels[index]);
},
);
},
itemCount: controller.labels.length,
itemCount: controller.filterLabels.length,
),
),
);
}
PreferredSizeWidget _buildTab(LibraryController controller){
return PreferredSize(
preferredSize: Size.fromHeight(48.w),
......@@ -128,7 +117,7 @@ class _LibraryPageState extends State<LibraryPage> {
unselectedLabelStyle: TextStyle(color: Colours.c9,fontSize: 14.w,height: 1.5),
controller: controller.tabController,
isScrollable: true,
tabs: controller.categories.map((model){
tabs: controller.filterCategories.map((model){
return Tab(text: model.name);
}).toList(),
),
......
part of library;
class LibraryContentPage extends StatefulWidget {
final LibraryContentController controller;
final LibraryController controller;
// final CategoryModel categoryModel;
const LibraryContentPage({
Key? key,
......@@ -17,7 +17,7 @@ class _LibraryContentPageState extends State<LibraryContentPage> with AutomaticK
@override
Widget build(BuildContext context) {
return ListView.builder(
// shrinkWrap: true,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.controller.books.length,
itemBuilder: (BuildContext context, int index) {
......
......@@ -18,13 +18,13 @@ class FilterPage extends StatefulWidget {
class _FilterPageState extends State<FilterPage> {
@override
Widget build(BuildContext context) {
List<FilterModel> categories = widget.controller.categories.map((model) {
return FilterModel(id: model.categoryId.toString(), name: model.name??'');
}).toList();
List<FilterModel> labels = widget.controller.labels.map((model) {
return FilterModel(id: model.labelId.toString(), name: model.name??'');
}).toList();
// List<FilterModel> categories = widget.controller.categories.map((model) {
// return FilterModel(id: model.categoryId.toString(), name: model.name??'');
// }).toList();
//
// List<FilterModel> labels = widget.controller.labels.map((model) {
// return FilterModel(id: model.labelId.toString(), name: model.name??'');
// }).toList();
return Container(
color: const Color(0xFF000000).withOpacity(0.5),
......@@ -39,10 +39,10 @@ class _FilterPageState extends State<FilterPage> {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildWrapWidget('分类', categories),
_buildWrapWidget('标签', labels),
_buildWrapWidget('是否收费', [FilterModel(id: '0', name: '收费'),FilterModel(id: '1', name: '免费')]),
_buildWrapWidget('排序', [FilterModel(id: '0', name: '读过'),FilterModel(id: '1', name: '评分')]),
_buildWrapWidget('分类', widget.controller.filterCategories),
_buildWrapWidget('标签', widget.controller.filterLabels),
_buildWrapWidget('是否收费', widget.controller.filterFree),
_buildWrapWidget('排序', widget.controller.filterDown),
],
)
],
......@@ -58,7 +58,9 @@ class _FilterPageState extends State<FilterPage> {
children: [
Expanded(
child: GestureDetector(
onTap: widget.resetTap,
onTap: (){
widget.controller.resetFilter();
},
child: Container(
alignment: Alignment.center,
height: 35.w,
......@@ -105,8 +107,8 @@ class _FilterPageState extends State<FilterPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(left: 10,bottom: 10,top: 10),
child: Text(title,style: TextStyle(fontSize: 15,height:1.6,color: Colours.c3,fontWeight: Fonts.medium),)
margin: EdgeInsets.only(left: 10.w,bottom: 10.w,top: 10.w),
child: Text(title,style: TextStyle(fontSize: 15.w,height:1.6,color: Colours.c3,fontWeight: Fonts.medium),)
),
Wrap(
spacing: 10,
......@@ -116,9 +118,10 @@ class _FilterPageState extends State<FilterPage> {
children: data.map((model){
return GestureDetector(
onTap: (){
print('================================');
setState(() {
print('--------------------------------${model.selected}');
for (FilterModel model in data){
model.selected = false;
}
model.selected = !model.selected;
});
},
......@@ -126,17 +129,19 @@ class _FilterPageState extends State<FilterPage> {
height: 27,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(13.5),
color: model.selected?AppTheme.primary: Colours.cF4
color: model.selected?const Color(0xFFC02D55).withOpacity(0.08): Colours.cF4,
border: model.selected?Border.all(width: 0.5.w,color: AppTheme.primary):null
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal:15,vertical: 5),
child: model.name == '读过' || model.name == '评分'?Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(model.name,style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
Image.asset('assets/images/down.png'),
Text(model.name??'',style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
Image.asset(model.selected?'assets/images/filter_select.png':'assets/images/filter_unselect.png'),
],
):Text(model.name,style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
):Text(model.name??'',style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
),
),
);
......
......@@ -2,7 +2,7 @@ part of library;
class BuildLabelWidget extends StatelessWidget {
final LabelModel model;
final FilterModel model;
const BuildLabelWidget({
Key? key,
required this.model
......
// part of library_content;
//
// class LibraryContentController extends GetxController {
//
// final CategoryModel categoryModel;
// late LabelModel labelModel;
// LibraryContentController(this.categoryModel, this.labelModel);
//
// final EasyRefreshController refreshController = EasyRefreshController(
// controlFinishLoad: true,
// controlFinishRefresh: true,
// );
//
// // 广告数组
// List<AdModel> ads = [];
//
// final int _limit = 10;
// int _page = 1;
// bool _noMore = false;
//
//
// // 图书列表数据
// List<CourseModel> books = [];
//
//
// @override
// void onReady() {
//
// super.onReady();
// }
//
//
// @override
// void onClose() {
// refreshController.dispose();
// super.onClose();
// }
//
//
// /// 收藏 与 取消收藏
// void love({
// required String bookId,
// required num isCollection
// }) async {
// if (isCollection == 0){
// isCollection = 1;
// }
// else{
// isCollection = 0;
// }
// bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
// if (result) {
// onRefresh();
// }
// }
//
// /// 获取图书列表数据
// Future<void> _getBooks([bool isRefresh = false]) async {
// if (isRefresh) _page = 1;
// // 网路请求
// final result = await LibraryAPI.books(
// page: _page,
// limit: _limit,
// categoryId: categoryModel.categoryId.toString(),
// labelId: labelModel.labelId.toString()
// );
// // 如果是刷新 清理数据
// if (isRefresh) books.clear();
// books.addAll(result);
// _page ++;
// _noMore = result.length < _limit;
// update();
//
// }
//
// void onRefresh() async {
// try {
// await _getBooks(true);
// refreshController.finishRefresh(IndicatorResult.success);
// refreshController.resetFooter();
// } catch (error) {
// refreshController.finishRefresh(IndicatorResult.fail);
// }
// }
//
// void onLoading() async {
// if (_noMore) {
// refreshController.finishLoad(IndicatorResult.noMore);
// return;
// }
// try {
// await _getBooks();
// refreshController.finishLoad();
// } catch (error) {
// refreshController.finishLoad(IndicatorResult.fail);
// }
// }
//
// }
\ No newline at end of file
// library library_content;
//
// import 'package:easy_refresh/easy_refresh.dart';
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
// import 'package:get/get_state_manager/src/simple/get_controllers.dart';
// import 'package:go_router/go_router.dart';
//
// import '../../apis/index.dart';
// import '../../models/index.dart';
// import '../../routes/index.dart';
// import '../../widgets/index.dart';
// import '../course/index.dart';
// import '../library/index.dart';
//
// part 'view.dart';
// part 'controller.dart';
\ No newline at end of file
// part of library_content;
//
// class LibraryContentPage extends StatefulWidget {
// final CategoryModel categoryModel;
// final LabelModel labelModel;
// final String tag;
// const LibraryContentPage({
// Key? key,
// required this.categoryModel,
// required this.labelModel,
// required this.tag
// }) : super(key: key);
//
// @override
// State<LibraryContentPage> createState() => _LibraryContentPageState();
// }
//
// class _LibraryContentPageState extends State<LibraryContentPage> {
// @override
// Widget build(BuildContext context) {
// return GetBuilder<LibraryContentController>(
// // tag: widget.tag,
// init: LibraryContentController(widget.categoryModel,widget.labelModel),
// builder: (controller) => CustomPullScrollView(
// controller: controller.refreshController,
// onRefresh: controller.onRefresh,
// onLoading: controller.onLoading,
// child: ListView.builder(
// itemCount: controller.books.length+1,
// itemBuilder: (BuildContext context, int index) {
// if (index == 0){
// return Container(
// color: Colors.red,
// padding: const EdgeInsets.symmetric(horizontal: 10),
// child: BuildBanner(items: controller.ads,),
// );
// }
// else {
// CourseModel model = controller.books[index-1];
// return GestureDetector(
// onTap: (){
// context.pushNamed(Routes.bookDetail,queryParameters: {'book_id':model.bookId.toString()});
// },
// child: LibraryCell(model: model,onTap: (){
// controller.love(bookId: model.bookId.toString(), isCollection: model.isCollection!);
// },),
// );
// }
// },
// ),
// ),
// );
// }
// // @override
// // bool get wantKeepAlive => true;
// }
差异被折叠。
......@@ -97,7 +97,8 @@ dependencies:
package_info_plus: ^4.2.0
# 版本更新
flutter_app_update: ^3.0.4
# 能指定滑动位置的listView
azlistview: ^2.0.0
dev_dependencies:
flutter_test:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论