。
在开发中经常遇到首页的分类入口,如美团的美食团购、打车等入口,左右切换还可以分页更多展示。
一、使用flutter_swiper_null_safety
在pubspec.yaml引入
dart
# 轮播图
flutter_swiper_null_safety: ^1.0.2
二、实现swiper分页代码
由于我这里按照一页8条展示,两行四列展示格式。
当列表list传入的控件时候,一共的页数为
dart
int getSwiperPageNumber() {
int allLength = widget.list.length;
int aPageNum = getSwiperOnePageNumber();
if (allLength % aPageNum == 0) {
return (allLength / aPageNum).toInt();
}
return (allLength / aPageNum).toInt() + 1;
}
通过列表,一页数量计算每一页应该展示多少个按钮。
dart
List getSwiperPagerItems(int pagerIndex) {
List pagerItems = [];
int allLength = widget.list.length;
int aPageNum = getSwiperOnePageNumber();
int start = pagerIndex * aPageNum;
int end = (pagerIndex + 1) * aPageNum;
if (end > allLength) {
end = allLength;
}
pagerItems = widget.list.sublist(start, end);
return pagerItems;
}
一共pages的列表
dart
int pagerNumber = getSwiperPageNumber();
for (int index = 0; index < pagerNumber; index++) {
CategorySwiperPagerItem swiperPagerItem = CategorySwiperPagerItem();
swiperPagerItem.pagerIndex = index;
swiperPagerItem.pagerItems = getSwiperPagerItems(index);
swiperPagers.add(swiperPagerItem);
}
通过使用flutter_swiper_null_safety来显示
dart
Swiper(
// 横向
scrollDirection: Axis.horizontal,
// 布局构建
itemBuilder: (BuildContext context, int index) {
CategorySwiperPagerItem swiperPagerItem = swiperPagers[index];
return HomeCategoryPager(
pagerIndex: swiperPagerItem.pagerIndex,
pageItems: swiperPagerItem.pagerItems,
width: itemWidth,
height: itemHeight,
containerHeight: showHeight,
containerWidth: width,
);
},
//条目个数
itemCount: swiperPagers.length,
// 自动翻页
autoplay: false,
// pagination: _buildSwiperPagination(),
// pagination: _buildNumSwiperPagination(),
//点击事件
// onTap: (index) {
// LoggerManager().debug(" 点击 " + index.toString());
// },
// 相邻子条目视窗比例
viewportFraction: 1,
// 用户进行操作时停止自动翻页
autoplayDisableOnInteraction: true,
// 无限轮播
loop: false,
//当前条目的缩放比例
scale: 1,
),
实现比较简单,
完整代码如下
dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart';
import 'package:flutter_app_dfaceintl/config/resource_manager.dart';
import 'package:flutter_app_dfaceintl/utils/color_util.dart';
import 'package:flutter_app_dfaceintl/widget/common/show_gesture_container.dart';
import 'package:one_context/one_context.dart';
import 'package:flutter_app_dfaceintl/config/logger_manager.dart';
class CategorySwiperPagerItem {
int pagerIndex = 0;
List pagerItems = [];
}
class HomeCategoryWidget extends StatefulWidget {
const HomeCategoryWidget({
Key? key,
required this.rowNumber,
required this.numberOfPerRow,
required this.list,
required this.screenWidth,
}) : super(key: key);
// 多少行
final int rowNumber;
// 一行几个
final int numberOfPerRow;
final List list;
final double screenWidth;
@override
State<HomeCategoryWidget> createState() => _HomeCategoryWidgetState();
}
class _HomeCategoryWidgetState extends State<HomeCategoryWidget> {
double showHeight = 0.0;
double containVPadding = 5.0;
double containHPadding = 10.0;
List<CategorySwiperPagerItem> swiperPagers = [];
bool showPagination = false;
@override
void initState() {
// TODO: implement initState
double containerHeight = getContainerMaxHeight(widget.screenWidth);
showHeight = containerHeight + 2 * containVPadding;
int pagerNumber = getSwiperPageNumber();
for (int index = 0; index < pagerNumber; index++) {
CategorySwiperPagerItem swiperPagerItem = CategorySwiperPagerItem();
swiperPagerItem.pagerIndex = index;
swiperPagerItem.pagerItems = getSwiperPagerItems(index);
swiperPagers.add(swiperPagerItem);
}
if (swiperPagers.length > 1) {
showPagination = true;
}
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
double width = widget.screenWidth;
double itemWidth = (width - 2 * containHPadding) / widget.numberOfPerRow;
double itemHeight = itemWidth;
return Container(
width: width,
height: showHeight,
margin: EdgeInsets.symmetric(vertical: 5.0),
padding: EdgeInsets.symmetric(
vertical: containVPadding,
horizontal: containHPadding,
),
color: Colors.white,
child: Swiper(
// 横向
scrollDirection: Axis.horizontal,
// 布局构建
itemBuilder: (BuildContext context, int index) {
CategorySwiperPagerItem swiperPagerItem = swiperPagers[index];
return HomeCategoryPager(
pagerIndex: swiperPagerItem.pagerIndex,
pageItems: swiperPagerItem.pagerItems,
width: itemWidth,
height: itemHeight,
containerHeight: showHeight,
containerWidth: width,
);
},
//条目个数
itemCount: swiperPagers.length,
// 自动翻页
autoplay: false,
// pagination: _buildSwiperPagination(),
// pagination: _buildNumSwiperPagination(),
//点击事件
// onTap: (index) {
// LoggerManager().debug(" 点击 " + index.toString());
// },
// 相邻子条目视窗比例
viewportFraction: 1,
// 用户进行操作时停止自动翻页
autoplayDisableOnInteraction: true,
// 无限轮播
loop: false,
//当前条目的缩放比例
scale: 1,
),
);
}
int getSwiperOnePageNumber() {
return widget.numberOfPerRow * widget.rowNumber;
}
int getSwiperPageNumber() {
int allLength = widget.list.length;
int aPageNum = getSwiperOnePageNumber();
if (allLength % aPageNum == 0) {
return (allLength / aPageNum).toInt();
}
return (allLength / aPageNum).toInt() + 1;
}
List getSwiperPagerItems(int pagerIndex) {
List pagerItems = [];
int allLength = widget.list.length;
int aPageNum = getSwiperOnePageNumber();
int start = pagerIndex * aPageNum;
int end = (pagerIndex + 1) * aPageNum;
if (end > allLength) {
end = allLength;
}
pagerItems = widget.list.sublist(start, end);
return pagerItems;
}
double getContainerMaxHeight(double screenWidth) {
double width = screenWidth;
double itemSize = (width - 2 * containHPadding) / widget.numberOfPerRow;
double maxHeight = itemSize * widget.rowNumber;
int allLength = widget.list.length;
if (allLength <= widget.numberOfPerRow) {
maxHeight = itemSize;
}
return maxHeight;
}
}
class HomeCategoryPager extends StatelessWidget {
const HomeCategoryPager({
Key? key,
required this.pagerIndex,
required this.pageItems,
required this.width,
required this.height,
this.containerWidth,
this.containerHeight,
}) : super(key: key);
final int pagerIndex;
final List pageItems;
final double width;
final double height;
final double? containerWidth;
final double? containerHeight;
@override
Widget build(BuildContext context) {
return Container(
width: containerWidth,
height: containerHeight,
child: Wrap(
children: pageItems
.map((e) => HomeCategoryItem(
width: width,
height: height,
))
.toList(),
),
);
}
}
class HomeCategoryItem extends StatelessWidget {
const HomeCategoryItem({
Key? key,
required this.width,
required this.height,
}) : super(key: key);
final double width;
final double height;
@override
Widget build(BuildContext context) {
return ShowGestureContainer(
padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 5.0),
width: width,
height: height,
highlightedColor: ColorUtil.hexColor(0xf0f0f0),
onPressed: () {
LoggerManager().debug("ShowGestureContainer");
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
buildIcon(),
Padding(
padding: EdgeInsets.only(top: 5.0),
child: buildTitle(),
),
],
),
);
}
Widget buildTitle() {
return Text(
"栏目",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
color: ColorUtil.hexColor(0x444444),
decoration: TextDecoration.none,
),
);
}
Widget buildIcon() {
return Icon(
Icons.access_alarm,
size: 32.0,
color: Colors.brown,
);
}
}
三、小结
flutter开发实战-实现首页分类目录入口切换功能。Swiper实现如美团的美食团购、打车等入口,左右切换还可以分页更多展示。
学习记录,每天不停进步。