提交 9438de01 编写于 作者: 徐群-ios's avatar 徐群-ios

feature: 集成列表功能开发

上级 edf184fe
// ignore_for_file: constant_identifier_names
class AssetImages {
static const String right_arrow = 'assets/multiImgs/right_arrow.png';
}
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:my_app2/Network/api/product_api.dart';
import 'package:my_app2/Network/http/BaseApi.dart';
import 'package:my_app2/Assets/AssetImages.dart';
import 'package:my_app2/Customization/ViewModel/ProductListViewModel.dart';
import 'package:my_app2/Models/ProductModel.dart';
import 'package:provider/provider.dart';
class Customization extends StatefulWidget {
class Customization extends StatelessWidget {
const Customization({super.key});
State<Customization> createState() => _CustomizationState();
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => ProductListViewModel(),
child: _CustomizationList(),
);
}
}
class _CustomizationList extends StatelessWidget {
@override
Widget build(BuildContext context) {
var viewModel = Provider.of<ProductListViewModel>(context);
return Scaffold(
appBar: AppBar(title: const Text('热门产品')),
body: _CustomizationListImg(viewModel),
);
}
}
class _CustomizationState extends State<Customization> {
class _CustomizationListImg extends StatefulWidget {
const _CustomizationListImg(this.viewModel);
final ProductListViewModel viewModel;
@override
State<_CustomizationListImg> createState() => _CustomizationListImgState();
}
class _CustomizationListImgState extends State<_CustomizationListImg> {
@override
void initState() {
super.initState();
ProductListApi request = ProductListApi(page: 1, pageSize: 10);
request.request(onSuccessed: (value) {
print(value);
}, onFailed: (error) {
print(error.toString());
});
widget.viewModel.pullUp();
}
@override
Widget build(BuildContext context) {
List<String> dataSource = [
"https://static.preclight.com/uploads/2023-02-08/63e36bec6e8f4.png",
"https://static.preclight.com/uploads/2023-02-20/63f2e9568b736.jpg",
"https://static.preclight.com/uploads/2023-02-07/63e219498801e.jpg",
"https://static.preclight.com/uploads/2023-02-07/63e2123ea9287.jpg",
"https://static.preclight.com/uploads/2023-02-07/63e21685eb2b4.png",
"https://static.preclight.com/uploads/2023-01-31/63d8f975dc915.jpg",
"https://static.preclight.com/uploads/2023-01-31/63d8f4cde0315.jpg",
"https://static.preclight.com/uploads/2023-02-22/63f59104a7fe7.png",
"https://static.preclight.com/uploads/2023-01-19/63c8e4eb35d16.png",
"https://static.preclight.com/uploads/2022-11-30/6387278fd8022.jpg"
];
return Scaffold(
appBar: AppBar(title: const Text('热门产品')),
body: CustomScrollView(slivers: [
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: SliverList(
delegate: ProductSliverBuilderDelegate(dataSource, 10)),
),
SliverList(
delegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
return const SizedBox(
height: 40,
child: Text("hello world"),
);
}, childCount: 2))
]));
return Consumer<ProductListViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
List<Widget> slivers = [];
if (viewModel.photoProductList.isNotEmpty &&
viewModel.handmadeProductList.isNotEmpty) {
slivers = [
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: _ListHeader('3D照片'),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: SliverList(
delegate: _ProductSliverBuilderDelegate(
viewModel.photoProductList, 10)),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: _ListHeader('3D定制手办'),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: SliverList(
delegate: _ProductSliverBuilderDelegate(
viewModel.handmadeProductList, 10)),
),
];
} else if (viewModel.photoProductList.isNotEmpty) {
slivers = [
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: _ListHeader('3D照片'),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: SliverList(
delegate: _ProductSliverBuilderDelegate(
viewModel.photoProductList, 10)),
),
];
} else if (viewModel.handmadeProductList.isNotEmpty) {
slivers = [
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: _ListHeader('3D定制手办'),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12),
sliver: SliverList(
delegate: _ProductSliverBuilderDelegate(
viewModel.handmadeProductList, 10)),
),
];
}
return CustomScrollView(slivers: slivers);
},
);
}
}
class ProductSliverBuilderDelegate extends SliverChildBuilderDelegate {
class _ListHeader extends SliverToBoxAdapter {
_ListHeader(String title, {double height = 50.0})
: assert(height > 0),
super(
child: SizedBox(
height: height,
child: Row(children: [
Container(
width: 4,
height: 14,
decoration: const BoxDecoration(
color: Color(0xFFFFAA22),
borderRadius: BorderRadius.all(Radius.circular(2.0))),
),
const SizedBox(
width: 6,
),
Text(
title,
style:
const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600),
)
]),
));
}
class _ProductSliverBuilderDelegate extends SliverChildBuilderDelegate {
static int _computeActualChildCount(int itemCount) {
return math.max(0, itemCount * 2 - 1);
}
final List<String> dataSource;
final List<ProductModel> dataSource;
final double spacing;
ProductSliverBuilderDelegate(this.dataSource, this.spacing)
_ProductSliverBuilderDelegate(this.dataSource, this.spacing)
: assert(spacing > 0),
super((context, index) {
final int itemIndex = index ~/ 2;
final Widget? widget;
if (index.isEven) {
double height = MediaQuery.of(context).size.width - 12.0 * 2;
String imgUrl = dataSource[itemIndex];
var item = dataSource[itemIndex];
String imgUrl = item.cover;
widget = Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(12.0))),
......@@ -78,7 +160,31 @@ class ProductSliverBuilderDelegate extends SliverChildBuilderDelegate {
height: height,
child: Stack(
fit: StackFit.expand,
children: [Image.network(imgUrl)],
children: [
Image.network(imgUrl),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
color: Colors.black.withOpacity(0.3),
height: 50,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Row(children: [
Expanded(
child: Text(
item.productName,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600),
)),
Image.asset(AssetImages.right_arrow)
]),
),
),
)
],
),
);
} else {
......
import 'package:flutter/material.dart';
import 'package:my_app2/Models/ProductModel.dart';
import 'package:my_app2/Network/api/product_api.dart';
import 'package:my_app2/Network/http/BaseApi.dart';
class ProductListViewModel extends ChangeNotifier {
final List<ProductModel> _productList = [];
int _page = 1;
final int _pageSize = 10;
bool _isLoading = true;
bool get isLoading => _isLoading && _productList.isEmpty;
bool get isEmpty => _productList.isEmpty;
void _updateProductList(List<ProductModel> list, bool isClear) {
_isLoading = false;
if (isClear) {
_productList.clear();
}
_productList.addAll(list);
notifyListeners();
}
/// 3d照片
List<ProductModel> get photoProductList {
var list = <ProductModel>[];
for (final item in _productList) {
if (item.productType == 2) {
list.add(item);
continue;
}
break;
}
return list;
}
/// 手办
List<ProductModel> get handmadeProductList {
int index = 0;
for (index; index < _productList.length; index++) {
if (_productList[index].productType == 1) {
break;
}
}
return _productList.sublist(index);
}
void pullUp() {
var api = ProductListApi(page: 1, pageSize: _pageSize);
api.request(
onSuccessed: (value) {
if (value == null) {
return;
}
_updateProductList(value, true);
},
onFailed: (p0) {},
);
}
void loadMore() {}
}
......@@ -9,22 +9,6 @@ enum RequestMethod { get, post }
typedef HttpParams = Map<String, dynamic>;
typedef HttpHeader = Map<String, dynamic>;
class Test {
Test(this.value);
final int value;
}
class AA<T> {
T getResponse(Map<String, dynamic> json) => throw Exception('子类重写');
}
class BB extends AA<Test> {
@override
Test getResponse(Map<String, dynamic> json) {
return Test(1);
}
}
class BaseApi<Model> {
String serviceKey() {
return "";
......
import 'package:flutter/material.dart';
/// _TabPageContainer 实现tab页面懒加载及状态保存
class TabPageContainer extends StatefulWidget {
final List<Widget> children;
final int currentIndex;
const TabPageContainer(
{Key? key, required this.children, required this.currentIndex})
: assert(currentIndex >= 0),
super(key: key);
@override
State<TabPageContainer> createState() => _TabPageContainerState();
}
class _TabPageContainerState extends State<TabPageContainer> {
final initMap = <int, bool>{};
@override
void initState() {
super.initState();
initMap[0] = true;
}
List<Widget> createChildren() {
final result = <Widget>[];
for (var i = 0; i < widget.children.length; ++i) {
final w = widget.children[i];
if (initMap[i] == true) {
result.add(w);
} else {
result.add(Container());
}
}
return result;
}
@override
Widget build(BuildContext context) {
return IndexedStack(
index: widget.currentIndex,
children: createChildren(),
);
}
@override
void didUpdateWidget(covariant TabPageContainer oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.currentIndex != widget.currentIndex) {
initMap[widget.currentIndex] = true;
setState(() {});
}
}
}
......@@ -5,6 +5,7 @@ import 'package:my_app2/Home/Home.dart';
import 'package:my_app2/Mine/Mine.dart';
import 'package:my_app2/Network/http/ServiceManager.dart';
import 'package:my_app2/Network/service/XmhService.dart';
import 'package:my_app2/TabPageContainer.dart';
void main() {
runApp(const MyApp());
......@@ -57,10 +58,9 @@ class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: const [Home(), Customization(), Mine()],
),
body: TabPageContainer(
currentIndex: _currentIndex,
children: const [Home(), Customization(), Mine()]),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: const [
......
......@@ -185,6 +185,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.0"
easy_refresh:
dependency: "direct main"
description:
name: easy_refresh
sha256: "4bf1e3bea60ca21ece286fcde16cdd64bdb7383b4901422a683404f77708c644"
url: "https://pub.dev"
source: hosted
version: "3.3.1"
extended_list_library:
dependency: transitive
description:
......@@ -376,6 +384,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
......@@ -392,6 +408,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.2"
path_drawing:
dependency: transitive
description:
name: path_drawing
sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "1.0.1"
pool:
dependency: transitive
description:
......@@ -400,6 +432,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.1"
provider:
dependency: "direct main"
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev"
source: hosted
version: "6.0.5"
pub_semver:
dependency: transitive
description:
......
......@@ -40,6 +40,8 @@ dependencies:
waterfall_flow: any
json_annotation: ^4.8.0
dio: ^5.0.0
provider: ^6.0.5
easy_refresh: ^3.3.1
dev_dependencies:
flutter_test:
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册