9.3 轮播广告 ad

9.3 轮播广告 ad

img

这个组件是一个轮播图组件,再叠加一个指示器组件合成

实现步骤:


1
flutter pub add carousel_slider

第 2 步:创建 kv 模型

lib/common/models/kv.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// key value 键值对
class KeyValueModel<T> {
String key;
T value;

KeyValueModel({required this.key, required this.value});

factory KeyValueModel.fromJson(Map<String, dynamic> json) {
return KeyValueModel(
key: json['key'] as String,
value: json['value'] as T,
);
}

Map<String, dynamic> toJson() => {
'key': key,
'value': value,
};

@override
String toString() {
return "$value";
}
}

第 3 步:轮播组件封装

lib/common/components/carousel.dart

定义组件输入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';

import '../index.dart';

/// 滚动视图
class CarouselWidget extends StatelessWidget {
const CarouselWidget(
{Key? key,
this.onPageChanged,
this.onTap,
required this.items,
this.currentIndex,
this.height,
this.indicatorColor,
this.indicatorCircle,
this.indicatorAlignment,
this.indicatorLeft,
this.indicatorRight,
this.indicatorBottom})
: super(key: key);

/// 切换页码
final Function(int, CarouselPageChangedReason)? onPageChanged;

/// 点击
final Function(int, KeyValueModel)? onTap;

/// 数据列表
final List<KeyValueModel> items;

/// 当前选中
final int? currentIndex;

/// 高度
final double? height;

/// 指示器 颜色
final Color? indicatorColor;

/// 指示器 是否圆形
final bool? indicatorCircle;

/// 指示器 对齐方式
final MainAxisAlignment? indicatorAlignment;

/// 指示器 位置
final double? indicatorLeft, indicatorRight, indicatorBottom;

Widget _buildView() {
List<Widget> ws = [
// 滚动视图
CarouselSlider(
options: CarouselOptions(
// 高度
height: height,
// 填充比例
viewportFraction: 1,
// 图像比例
aspectRatio: 3.2 / 1,
// 确定当前页面是否应该大于侧面图像, 在旋转木马中营造一种深度感。
enlargeCenterPage: false,
// 循环
enableInfiniteScroll: true,
// 自动播放
autoPlay: true,
// 回调页切换事件
onPageChanged: onPageChanged,
),
items: <Widget>[
for (var i = 0; i < items.length; i++)
ImageWidget.url(
items[i].value,
fit: BoxFit.fill,
).onTap(
() {
if (onTap != null) onTap!(i, items[i]);
},
),
],
),

// 指示器
SliderIndicatorWidget(
// 个数
length: items.length,
// 当前索引
currentIndex: currentIndex ?? 0,
// 颜色
color: indicatorColor ?? AppColors.background,
// 是否圆形
isCircle: indicatorCircle ?? true,
// 对齐方式
alignment: indicatorAlignment ?? MainAxisAlignment.center,
).positioned(
left: indicatorLeft ?? 20,
right: indicatorRight ?? 20,
bottom: indicatorBottom ?? 10,
),
];

return ws.toStack();
}

@override
Widget build(BuildContext context) {
return _buildView();
}
}

第 4 步:轮播数据准备

Banners API

lib/common/api/system.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import '../index.dart';

/// 系统 api
class SystemApi {
/// Banner Ads
static Future<List<KeyValueModel>> banners() async {
List<KeyValueModel> bannerItems = [
KeyValueModel(
key: "01",
value:
"https://ducafecat.oss-cn-beijing.aliyuncs.com/flutter_woo_commerce_getx_ducafecat/banner01.png"),
KeyValueModel(
key: "02",
value:
"https://ducafecat.oss-cn-beijing.aliyuncs.com/flutter_woo_commerce_getx_ducafecat/banner02.png"),
KeyValueModel(
key: "03",
value:
"https://ducafecat.oss-cn-beijing.aliyuncs.com/flutter_woo_commerce_getx_ducafecat/banner03.png"),
];

return bannerItems;
}
}

这里我们写死方便演示,图片用的阿里oss

lib/pages/goods/home/controller.dart

控制器中定义数据

1
2
3
4
5
6
7
8
9
10
11
// Banner 当前位置
int bannerCurrentIndex = 0;

// Banner 数据
List<KeyValueModel> bannerItems = [];

// Banner 切换事件
void onChangeBanner(int index, /*CarouselPageChangedReason*/ reason) {
bannerCurrentIndex = index;
update(["home_banner"]);
}

注意这里的 update 操作

1
2
3
4
5
6
7
_initData() async {
// 首页
// banner
bannerItems = await SystemApi.banners();

update(["home"]);
}

第 5 步:轮播广告

lib/pages/goods/home/view.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 轮播广告
Widget _buildBanner() {
return GetBuilder<HomeController>(
init: controller,
id: "home_banner",
builder: (_) {
return CarouselWidget(
items: controller.bannerItems,
currentIndex: controller.bannerCurrentIndex,
onPageChanged: controller.onChangeBanner,
height: 190.w,
);
})
.clipRRect(all: AppSpace.button)
.sliverToBoxAdapter()
.sliverPaddingHorizontal(AppSpace.page);
}

提交代码到 git