完成Application-Category页
This commit is contained in:
parent
91c50070ec
commit
ac67682918
|
@ -51,7 +51,7 @@ class ApplicationController extends GetxController {
|
|||
super.onInit();
|
||||
|
||||
// 准备静态数据 作为tab
|
||||
tabTitles = ['Welcome', 'Cagegory', 'Bookmarks', 'Account'];
|
||||
tabTitles = ['Welcome', 'Category', 'Bookmarks', 'Account'];
|
||||
bottomTabs = <BottomNavigationBarItem>[
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:news_getx/data/repository/news_repository.dart';
|
||||
|
||||
import 'category_controller.dart';
|
||||
|
||||
class CategoryBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut(() => CategoryController());
|
||||
Get.lazyPut(() => CategoryController(
|
||||
newsRepository: NewsRepository()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,76 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:news_getx/data/model/news.dart';
|
||||
import 'package:news_getx/data/repository/news_repository.dart';
|
||||
import 'package:news_getx/modules/category/category_state.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
class CategoryController extends GetxController {
|
||||
NewsRepository newsRepository;
|
||||
|
||||
CategoryController({required this.newsRepository});
|
||||
|
||||
/// UI 组件
|
||||
final RefreshController refreshController = RefreshController(
|
||||
initialRefresh: true,
|
||||
);
|
||||
|
||||
/// 响应式成员变量
|
||||
final state = CategoryState();
|
||||
|
||||
/// 成员变量
|
||||
String categoryCode = '';
|
||||
int curPage = 1;
|
||||
int pageSize = 20;
|
||||
int total = 20;
|
||||
|
||||
/// 事件
|
||||
void onRefresh() {
|
||||
fetchNewsList(isRefresh: true).then((_) {
|
||||
refreshController.refreshCompleted(resetFooterState: true);
|
||||
}).catchError((_) {
|
||||
refreshController.refreshFailed();
|
||||
});
|
||||
}
|
||||
|
||||
void onLoading() {
|
||||
if (state.newsList.length < total) {
|
||||
fetchNewsList().then((_) {
|
||||
refreshController.loadComplete();
|
||||
}).catchError((_) {
|
||||
refreshController.loadFailed();
|
||||
});
|
||||
} else {
|
||||
refreshController.loadNoData();
|
||||
}
|
||||
}
|
||||
|
||||
/// 方法
|
||||
|
||||
// 拉取数据
|
||||
Future<void> fetchNewsList({bool isRefresh = false}) async {
|
||||
var result = await newsRepository.newsPageList(
|
||||
params: NewsPageListRequest(
|
||||
categoryCode: categoryCode,
|
||||
pageNum: curPage + 1,
|
||||
pageSize: pageSize,
|
||||
),
|
||||
);
|
||||
|
||||
if (isRefresh) {
|
||||
curPage = 1;
|
||||
total = result.counts!;
|
||||
state.newsList.clear();
|
||||
} else {
|
||||
curPage++;
|
||||
}
|
||||
|
||||
state.newsList.addAll(result.items!);
|
||||
}
|
||||
|
||||
///dispose 释放内存
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
refreshController.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:news_getx/modules/category/widgets/news_page_list.dart';
|
||||
|
||||
import 'category_controller.dart';
|
||||
|
||||
|
@ -8,6 +9,8 @@ class CategoryPage extends GetView<CategoryController> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text('Categories');
|
||||
return Scaffold(
|
||||
body: NewsPageList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:news_getx/data/model/news.dart';
|
||||
|
||||
class CategoryState {
|
||||
// 分类
|
||||
RxList<NewsItem> newsList = <NewsItem>[].obs;
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:news_getx/data/model/news.dart';
|
||||
import 'package:news_getx/modules/widgets/image.dart';
|
||||
import 'package:news_getx/theme/app_colors.dart';
|
||||
import 'package:news_getx/utils/date.dart';
|
||||
|
||||
class NewsListItem extends StatelessWidget {
|
||||
const NewsListItem({super.key, required this.newsItem});
|
||||
|
||||
final NewsItem newsItem;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 161.h,
|
||||
padding: EdgeInsets.all(20.w),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 左侧图
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// 到详情页
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 121.w,
|
||||
height: 121.w,
|
||||
child: netImageCached(
|
||||
newsItem.thumbnail ?? "",
|
||||
width: 121.w,
|
||||
height: 121.w,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 右侧内容
|
||||
SizedBox(
|
||||
width: 194.w,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 作者
|
||||
Container(
|
||||
margin: EdgeInsets.all(0),
|
||||
child: Text(
|
||||
newsItem.author ?? '',
|
||||
style: TextStyle(
|
||||
fontFamily: 'Avenir',
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.thirdElementText,
|
||||
fontSize: 14.sp,
|
||||
),
|
||||
),
|
||||
),
|
||||
// 标题
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// 到详情页
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 10.h),
|
||||
child: Text(
|
||||
newsItem.title ?? '',
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 3,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Montserrat',
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.primaryText,
|
||||
fontSize: 16.sp,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Spacer(),
|
||||
// 一行 3 列
|
||||
Container(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
ConstrainedBox(
|
||||
// 分类
|
||||
constraints: BoxConstraints(maxWidth: 60.w),
|
||||
child: Text(
|
||||
newsItem.category ?? "",
|
||||
style: TextStyle(
|
||||
fontFamily: 'Avenir',
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.secondaryElementText,
|
||||
fontSize: 14.sp,
|
||||
height: 1,
|
||||
),
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
// 添加时间
|
||||
Container(
|
||||
width: 15.w,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 100.w),
|
||||
child: Text(
|
||||
'• ${timeLineFormat(newsItem.addtime ?? DateTime(0))}',
|
||||
style: TextStyle(
|
||||
fontFamily: 'Avenir',
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColors.thirdElementText,
|
||||
fontSize: 14.sp,
|
||||
height: 1,
|
||||
),
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
// 占满剩余空间
|
||||
Spacer(),
|
||||
// 更多
|
||||
InkWell(
|
||||
child: Icon(
|
||||
Icons.more_horiz,
|
||||
color: AppColors.primaryText,
|
||||
size: 24,
|
||||
),
|
||||
onTap: () {
|
||||
print('查看更多...');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:news_getx/modules/category/category_controller.dart';
|
||||
import 'package:news_getx/modules/category/widgets/news_item.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
class NewsPageList extends StatefulWidget {
|
||||
const NewsPageList({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<NewsPageList> createState() => _NewsPageListState();
|
||||
}
|
||||
|
||||
class _NewsPageListState extends State<NewsPageList>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
final controller = Get.find<CategoryController>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return GetX<CategoryController>(
|
||||
init: controller,
|
||||
builder: (controller) {
|
||||
return SmartRefresher(
|
||||
controller: controller.refreshController,
|
||||
enablePullUp: true,
|
||||
onRefresh: controller.onRefresh,
|
||||
onLoading: controller.onLoading,
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(vertical: 0.w, horizontal: 0.h),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
var item = controller.state.newsList[index];
|
||||
return NewsListItem(newsItem: item);
|
||||
},
|
||||
childCount: controller.state.newsList.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue