先写一个banner控件
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:transparent_image/transparent_image.dart';
//这个是在网络上找的一个例子,练手
const MAX_COUNT = 0x7fffffff;
///
/// Item的点击事件
///
typedef void OnBannerItemClick(int position, BannerItem entity);
///
/// 自定义ViewPager的每个页面显示
///
typedef Widget CustomBuild(int position, BannerItem entity);
class BannerWidget extends StatefulWidget {
final double height;
final List<BannerItem> datas;
int duration;
double pointRadius;
Color selectedColor;
Color unSelectedColor;
Color textBackgroundColor;
bool isHorizontal;
OnBannerItemClick bannerPress;
CustomBuild build;
BannerWidget(double this.height, List<BannerItem> this.datas,
{Key key,
int this.duration = 5000,
double this.pointRadius = 3.0,
Color this.selectedColor = Colors.red,
Color this.unSelectedColor = Colors.white,
Color this.textBackgroundColor = const Color(0x99000000),
bool this.isHorizontal = true,
OnBannerItemClick this.bannerPress,
CustomBuild this.build})
: super(key: key);
@override
BannerState createState() {
return new BannerState();
}
}
class BannerState extends State<BannerWidget> {
Timer timer;
int selectedIndex = 0;
PageController controller;
@override
void initState() {
double current = widget.datas.length > 0
? (MAX_COUNT / 2) - ((MAX_COUNT / 2) % widget.datas.length)
: 0.0;
controller = PageController(initialPage: current.toInt());
_initPageAutoScroll();
super.initState();
}
_initPageAutoScroll() {
start();
}
@override
void didUpdateWidget(BannerWidget oldWidget) {
super.didUpdateWidget(oldWidget);
}
start() {
stop();
timer = Timer.periodic(Duration(milliseconds: widget.duration), (timer) {
if(widget.datas.length > 0 && controller != null && controller.page != null) {
controller.animateToPage(controller.page.toInt() + 1,
duration: Duration(milliseconds: 300), curve: Curves.linear);
}
});
}
stop() {
timer?.cancel();
timer = null;
}
@override
void dispose() {
stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Container(
height: widget.height,
color: Colors.black12,
child: Stack(
children: <Widget>[
getViewPager(),
new Align(
alignment: Alignment.bottomCenter,
child: IntrinsicHeight(
child: Container(
padding: EdgeInsets.all(6.0),
color: widget.textBackgroundColor,
child: getBannerTextInfoWidget(),
),
),
),
],
),
);
}
Widget getViewPager() {
return PageView.builder(
itemCount: widget.datas.length > 0 ? MAX_COUNT : 0,
controller: controller,
onPageChanged: onPageChanged,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
if (widget.bannerPress != null)
widget.bannerPress(selectedIndex, widget.datas[selectedIndex]);
},
child: widget.build == null
? FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image:
widget.datas[index % widget.datas.length].itemImagePath,
fit: BoxFit.cover)
: widget.build(
index, widget.datas[index % widget.datas.length]));
},
);
}
Widget getSelectedIndexTextWidget() {
return widget.datas.length > 0 && selectedIndex < widget.datas.length
? widget.datas[selectedIndex].itemText
: Text('');
}
Widget getBannerTextInfoWidget() {
if (widget.isHorizontal) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Expanded(
flex: 1,
child: getSelectedIndexTextWidget(),
),
Expanded(
flex: 0,
child: Row(
mainAxisSize: MainAxisSize.min,
children: circle(),
),
),
],
);
} else {
return new Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
getSelectedIndexTextWidget(),
IntrinsicWidth(
child: Row(
children: circle(),
),
),
],
);
}
}
List<Widget> circle() {
List<Widget> circle = [];
for (var i = 0; i < widget.datas.length; i++) {
circle.add(Container(
margin: EdgeInsets.all(2.0),
width: widget.pointRadius * 2,
height: widget.pointRadius * 2,
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: selectedIndex == i
? widget.selectedColor
: widget.unSelectedColor,
),
));
}
return circle;
}
onPageChanged(index) {
selectedIndex = index % widget.datas.length;
setState(() {});
}
}
class BannerItem {
String itemImagePath;
Widget itemText;
static BannerItem defaultBannerItem(String image, String text) {
BannerItem item = new BannerItem();
item.itemImagePath = image;
Text textWidget = new Text(
text,
softWrap: true,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white, fontSize: 12.0, decoration: TextDecoration.none),
);
item.itemText = textWidget;
return item;
}
}
去网上搞数据填充数据
import 'package:dio/dio.dart';
const String BASEURL ="https://www.wanandroid.com";
class HttpConfig{
static const baseUrl = BASEURL;
static const timeout = 3000;
}
class RequestManager{
static final BaseOptions options = BaseOptions(
baseUrl: HttpConfig.baseUrl,connectTimeout: HttpConfig.timeout
);
static final Dio dio = Dio(options);
static Future<T> request<T>(String url,{String method='get',Map<String,dynamic> params,Interceptor interceptor})async{
final options = Options(method:method);
Interceptor dInter = InterceptorsWrapper(
onRequest: (RequestOptions options){
return options;//
},
onResponse: (Response response){
return response;
},
onError:(DioError error){
return error;
}
);
List<Interceptor> inters = [dInter];
if(interceptor!=null){
inters.add(interceptor);
}
dio.interceptors.addAll(inters);
//发送网络请求
try{
Response response = await dio.request<T>(url,queryParameters: params,options: options);
return response.data;
}on DioError catch(e){
return Future.error(e);
}
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_weight_ui/model/home_banner_data_entity.dart';
import 'banner_widget.dart';
import '../net/RequestUtils.dart';
class BannerPage extends StatefulWidget{
@override
State<StatefulWidget> createState() =>_BannerPage();
}
class _BannerPage extends State<BannerPage>{
List<HomeBannerDataData> data = new List<HomeBannerDataData>();
List<BannerItem> datas = [];
@override
void initState() {
getHomeData();
super.initState();
}
getHomeData() async {
var result = await RequestManager.request("https://www.wanandroid.com/banner/json");
setState(() {
HomeBannerDataEntity dataBean = HomeBannerDataEntity().fromJson(result);
data.addAll(dataBean.data);
for(var i=0;i<data.length;i++){
datas.add(BannerItem.defaultBannerItem(data[i].imagePath, data[i].title));
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
centerTitle: true,
title: Text('首页'),
),
body: Center(
child: Column(
children: <Widget>[
new BannerWidget(
180.0,
datas,
bannerPress: (pos, item) {
//TODO去做特别的逻辑
},
)
],
),
),
);
}
}
用到的库,以及JsonToDartBean插件(自行百度)
dependencies:
flutter:
sdk: flutter
dio: ^3.0.9
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
transparent_image: ^0.1.0