Flutter之banner实现

 先写一个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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值