5.1 WelcomeSlider 封装

5.1 WelcomeSlider 封装

实现步骤:


1
flutter pub add carousel_slider

第 2 步:i18n 配置

lib/common/i18n/locale_keys.dart

1
2
3
4
5
6
7
8
9
10
// 欢迎页
static const welcomeOneTitle = 'welcome_one_title';
static const welcomeOneDesc = 'welcome_one_desc';
static const welcomeTwoTitle = 'welcome_two_title';
static const welcomeTwoDesc = 'welcome_two_desc';
static const welcomeThreeTitle = 'welcome_three_title';
static const welcomeThreeDesc = 'welcome_three_desc';
static const welcomeSkip = 'welcome_skip';
static const welcomeNext = 'welcome_next';
static const welcomeStart = 'welcome_start';

lib/common/i18n/locales/locale_en.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
// welcome 欢迎
LocaleKeys.welcomeOneTitle: 'Choose Your Desire Product',
LocaleKeys.welcomeOneDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeTwoTitle: 'Complete your shopping',
LocaleKeys.welcomeTwoDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeThreeTitle: 'Get product at your door',
LocaleKeys.welcomeThreeDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeSkip: 'Skip',
LocaleKeys.welcomeNext: 'Next',
LocaleKeys.welcomeStart: 'Get Started',

lib/common/i18n/locales/locale_zh.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
// welcome 欢迎
LocaleKeys.welcomeOneTitle: '选择您喜欢的产品',
LocaleKeys.welcomeOneDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeTwoTitle: '完成您的购物',
LocaleKeys.welcomeTwoDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeThreeTitle: '足不出户的购物体验',
LocaleKeys.welcomeThreeDesc:
'Contrary to popular belief, Lorem Ipsum is not simply random text',
LocaleKeys.welcomeSkip: '跳过',
LocaleKeys.welcomeNext: '下一页',
LocaleKeys.welcomeStart: '立刻开始',

第 3 步:WelcomeModel 类

lib/common/models/welcome_model.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
/// 欢迎数据 Model
class WelcomeModel {
/// 图片url
String? image;

/// 标题
String? title;

/// 说明
String? desc;

WelcomeModel({this.image, this.title, this.desc});

WelcomeModel.fromJson(dynamic json) {
image = json["image"];
title = json["title"];
desc = json["desc"];
}

Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["image"] = image;
map["title"] = title;
map["desc"] = desc;
return map;
}
}

第 4 步:WelcomeSlider 类

image-20220713132606210

lib/common/components/welcome_slider.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
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_woo_commerce_getx_learn/common/index.dart';

/// 欢迎 slider
class WelcomeSliderWidget extends StatelessWidget {
/// 项目
final List<WelcomeModel> items;

/// 页数发生变化
final Function(int) onPageChanged;

/// 控制器
final CarouselController? carouselController;

const WelcomeSliderWidget(
this.items, {
Key? key,
required this.onPageChanged,
this.carouselController,
}) : super(key: key);

Widget sliderItem(WelcomeModel item) {
return Builder(
builder: (BuildContext context) {
return <Widget>[
// 图
if (item.image != null)
ImageWidget.asset(
item.image!,
fit: BoxFit.cover,
),

// 标题
if (item.title != null)
TextWidget.title1(
item.title ?? "",
maxLines: 2,
softWrap: true,
textAlign: TextAlign.center,
),

// 描述
if (item.desc != null)
TextWidget.body1(
item.desc ?? "",
maxLines: 3,
softWrap: true,
textAlign: TextAlign.center,
)
]
.toColumn(mainAxisAlignment: MainAxisAlignment.spaceAround)
.width(MediaQuery.of(context).size.width);
},
);
}

@override
Widget build(BuildContext context) {
return CarouselSlider(
carouselController: carouselController,
options: CarouselOptions(
height: 500.w,
viewportFraction: 1, // 充满
enlargeCenterPage: false, // 动画 封面效果
enableInfiniteScroll: false, // 无限循环
autoPlay: false, // 自动播放
onPageChanged: (index, reason) => onPageChanged(index),
),
items: <Widget>[
for (var item in items) sliderItem(item),
].toList(),
);
}
}

第 5 步:控制器

lib/pages/system/welcome/controller.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
List<WelcomeModel>? items;

_initData() {
items = [
WelcomeModel(
image: AssetsImages.welcome_1Png,
title: LocaleKeys.welcomeOneTitle.tr,
desc: LocaleKeys.welcomeOneDesc.tr,
),
WelcomeModel(
image: AssetsImages.welcome_2Png,
title: LocaleKeys.welcomeTwoTitle.tr,
desc: LocaleKeys.welcomeTwoDesc.tr,
),
WelcomeModel(
image: AssetsImages.welcome_3Png,
title: LocaleKeys.welcomeThreeTitle.tr,
desc: LocaleKeys.welcomeThreeDesc.tr,
),
];
update(["slider"]);
}

@override
void onReady() {
super.onReady();
_initData();
}

第 6 步:视图

lib/pages/system/welcome/view.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
// slider
Widget _buildSlider() {
return GetBuilder<WelcomeController>(
id: "slider",
init: controller,
builder: (controller) => controller.items == null
? const SizedBox()
: WelcomeSliderWidget(
controller.items!,
onPageChanged: (index) {},
),
);
}

// 内容页
Widget _buildView() {
return <Widget>[
// slider切换
buildSlider(),
// 控制栏
]
.toColumn(
mainAxisAlignment: MainAxisAlignment.spaceAround,
)
.paddingAll(AppSpace.page);
}

第 7 步:splash 跳转到 welcome

lib/pages/system/splash/controller.dart

1
2
3
4
5
6
_jumpToPage() {
// 欢迎页
Future.delayed(const Duration(seconds: 1), () {
Get.offAllNamed(RouteNames.systemWelcome);
});
}
1
2
3
4
5
6
7
@override
void onReady() {
super.onReady();
FlutterNativeSplash.remove(); // 删除设备启动图
// _initData(); // 初始数据
_jumpToPage(); // 跳转界面
}

最后:运行

img

提交代码到 git