美文网首页Flutter圈子
Flutter 自定义view-banner

Flutter 自定义view-banner

作者: 折剑游侠 | 来源:发表于2019-12-12 15:54 被阅读0次

width默认屏幕宽度,可设置高度。


image.png
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'cf_banner_indicator.dart';

typedef GetWidgetCallback = Widget Function(int index);

///width默认为屏幕宽度
class CfBanner extends StatefulWidget {
  final int length;

  final GetWidgetCallback callback;
  final double height;
  final Widget selectorWidget;
  final Widget normalWidget;
  final bool autoLoop;
  final bool showIndicator;
  final bool spaceMode;

  CfBanner(
      {Key key,
      this.length,
      this.callback,
      @required this.height,
      this.selectorWidget,
      this.normalWidget,
      this.autoLoop = true,
      this.showIndicator = true,
      this.spaceMode = true});

  @override
  State<StatefulWidget> createState() {
    return _CfBannerState();
  }
}

class _CfBannerState extends State<CfBanner> {
  @override
  void didUpdateWidget(CfBanner oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void deactivate() {
    super.deactivate();
  }

  @override
  void dispose() {
    super.dispose();
    if (_timer != null) {
      _timer.cancel();
    }
  }

  PageController _pageController;
  int _currentIndex = 100;
  Timer _timer;

  //设置定时器
  _setTimer() {
    if (_timer != null) {
      return;
    }

    _timer = Timer.periodic(Duration(seconds: 5), (_) {
      _pageController.animateToPage(_currentIndex + 1,
          duration: Duration(milliseconds: 400), curve: Curves.easeOut);
    });
  }

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

  int bannerMax = 10000000000;

  double currentWidth = 0;

  CfBannerIndicator indicator;

  GlobalKey<CfBannerIndicatorState> indicatorKey =
      GlobalKey<CfBannerIndicatorState>();

  double viewportFractionCustom = 1;
  double paddingCustom = 0;

  Widget getBanner2() {
    if (widget.spaceMode) {
      viewportFractionCustom = 0.925;
      paddingCustom = 0.0125;
    }
    currentWidth = MediaQuery.of(context).size.width;

    if (widget.length > 0 && _pageController == null) {
      _pageController = new PageController(
          initialPage: widget.length * 100,
          viewportFraction: viewportFractionCustom);
      _currentIndex = widget.length * 100;

      if (widget.autoLoop) {
        _setTimer();
      }
    }
    if (widget.length == 0) {
      return Container();
    }
    PageView pageView = new PageView.builder(
      itemBuilder: ((context, index) {
        GlobalKey _key = new GlobalKey();
        Container container = Container(
          key: _key,
          //左右两个padding
          margin: EdgeInsets.only(
              left: currentWidth * paddingCustom,
              right: currentWidth * paddingCustom),
          width: currentWidth,
          height: widget.height,
          child: widget.callback(index % widget.length),
        );

        return container;
      }),
      itemCount: bannerMax,
      scrollDirection: Axis.horizontal,
      reverse: false,
      controller: _pageController,
      physics: PageScrollPhysics(parent: BouncingScrollPhysics()),
      onPageChanged: ((index) {
        _currentIndex = index;
        if (indicatorKey.currentState != null) {
          indicatorKey.currentState
              .updateWidgets(widget.length, (_currentIndex) % widget.length);
        } else {}
      }),
    );
    if (widget.showIndicator) {
      indicator = CfBannerIndicator(
        normalWidget: widget.normalWidget,
        selectorWidget: widget.selectorWidget,
        key: indicatorKey,
        length: widget.length,
        select: (_currentIndex) % widget.length,
      );
    }

    return Container(
      width: MediaQuery.of(context).size.width,
      height: widget.height,
      child: Stack(
        children: <Widget>[pageView, _getIndicator()],
      ),
    );
  }

  Widget _getIndicator() {
    if (widget.showIndicator) {
      return Positioned(
        bottom: currentWidth * 0.02,
        left: 0,
        right: 0,
        child: indicator,
      );
    } else {
      return Container();
    }
  }
}

指示器

import 'package:flutter/material.dart';

class CfBannerIndicator extends StatefulWidget {
  int length;
  int select;
  final Widget selectorWidget;
  final Widget normalWidget;

  CfBannerIndicator(
      {Key key,
      this.length,
      this.select,
      this.selectorWidget,
      this.normalWidget})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return CfBannerIndicatorState();
  }
}

class CfBannerIndicatorState extends State<CfBannerIndicator> {
  List<Widget> points() {
    List<Widget> list;
    for (var i = 0; i < widget.length; i++) {
      if (list == null) {
        list = new List();
      }
      list.add(_getWidget(i));
    }
    if (list == null) {
      list = new List();
      list.add(Container());
    }
    return list;
  }

  Widget _getWidget(int i) {
    int index = widget.select;

    if (index == i) {
      if (widget.selectorWidget != null) {
        return widget.selectorWidget;
      }
      return Container(
        margin: EdgeInsets.only(left: 0.5, right: 0.5),
        child: Image.asset(
          "images/banner_select_true.png",
          height: 10,
          width: 15,
        ),
      );
    } else {
      if (widget.normalWidget != null) {
        return widget.normalWidget;
      }
      return Container(
        margin: EdgeInsets.only(left: 0.5, right: 0.5),
        child: Image.asset(
          "images/banner_select_false.png",
          height: 5,
          width: 10,
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: points(),
    );
  }

  updateWidgets(int length, int select) {
    widget.length = length;
    widget.select = select;
    setState(() {});
  }
}

相关文章

网友评论

    本文标题:Flutter 自定义view-banner

    本文链接:https://www.haomeiwen.com/subject/dfstnctx.html