flutter_url_launcher轮播图banner编写(自定义可随意在任何地方添加和删除)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wdx_1136346879/article/details/89174393

自动无限循环,可以手动拖拽,指示器显示
效果图
首页代码,将轮播图自定义出来一个控件,直接可以添加和删除

 @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('首页')
          ),
          body: Column(
        children: <Widget>[
        Stack(//帧布局  
        //alignment: const FractionalOffset(0.9, 0.1),//方法一
        children: <Widget>[
            Pagination(),//轮播图 banner
            Positioned(//方法二
            top: 10.0,
            left: 0.0,
            // child: DisclaimerMsg(key:key,pWidget:this)
             child:Text('banner学习',)  //悬浮在banner上方
            ),
          ]),
        SizedBox(height: 1, child:Container(color: Theme.of(context).primaryColor)),
        SizedBox(height: 10),
        ],
      ),
        );
      
  }

轮播图组件代码

import 'package:flutter/material.dart';
import './home_banner.dart';
import './story.dart';
import 'package:url_launcher/url_launcher.dart';
/// 轮播图组件  可以直接引入
class Pagination extends StatelessWidget {
  static final String routeName = '/material/page-selector';
  static final List<Icon> icons = <Icon>[
    const Icon(Icons.event, semanticLabel: 'Event'),
    const Icon(Icons.home, semanticLabel: 'Home'),
    const Icon(Icons.android, semanticLabel: 'Android'),
    const Icon(Icons.alarm, semanticLabel: 'Alarm'),
    const Icon(Icons.face, semanticLabel: 'Face'),
    const Icon(Icons.language, semanticLabel: 'Language'),
  ];

  final List<dynamic> arr = [
    {'image': 'https://pics2.baidu.com/feed/8d5494eef01f3a291779e03320581f355d607c1f.jpeg', 'type': 0, 'id': 9695909, 'url': 'https://www.zhihu.com/question/294145797/answer/551162834', 'title': '中国女足收获四国赛冠军!但王霜太累了,何时能歇歇?'},
    {'image': 'https://pics5.baidu.com/feed/a9d3fd1f4134970a1ca8142320b772cca6865d60.jpeg', 'type': 0, 'id': 9695859, 'url': 'https://zhuanlan.zhihu.com/p/51696594', 'title': '郑州火车站加开40趟临时列车 应对清明假期返程高峰'},
    {'image': 'https://pics4.baidu.com/feed/6c224f4a20a44623d9a783e62d5fd10a0df3d743.jpeg', 'type': 0, 'id': 96956491409, 'url':'https://zhuanlan.zhihu.com/p/53497167','title': '凉山火灾复燃面积约7公顷 扑火人员已撤至安全地带'},
    {'image': 'https://pics5.baidu.com/feed/d01373f082025aaf986c179a4e900860024f1a82.jpeg', 'type': 0, 'id': 9695816, 'url': 'https://mp.weixin.qq.com/s?__biz=MzAwODY4OTk2Mg==&mid=2652048101&idx=1&sn=20296088e4bd8ca33c5c9991167d9f7d&chksm=808caaa0b7fb23b65c0e5806209f8d86da6732f3a00a70353f3606018339518b0a8656f14dc5&mpsshare=1&scene=2&srcid=0106SZapVysZdIS6Oc5AhNH6&from=timeline&ascene=2&devicetype=android-27&version=27000038&nettype=WIFI&abtest_cookie=BQABAAgACgALABMAFAAFAJ2GHgAjlx4AV5keAJuZHgCcmR4AAAA%3D&lang=zh_CN&pass_ticket=4K1%2FUpsxP4suPj2iubR17wbAP7r9LW9iYrPAC2dppTqv7j7JO5FWMXtcKeBRxueV&wx_header=1', 'title': '高雄飞往香港客机迫降 初步判断:机械故障并非鸟击'}
  ];

  void _launchURL(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  List<Widget> _pageSelector(BuildContext context) {
    List<Widget> list = [];
    List<StoryModel> bannerStories = [];
    /// super.initState();
    arr.forEach((item) {
      bannerStories.add(StoryModel.fromJson(item));
    });


    if (arr.length > 0) {
      list.add(HomeBanner(bannerStories, (story) {
        _launchURL('${story.url}');
      }));
    }
    return list;
  }

  @override
  Widget build(BuildContext context) {
    return
      Column(
        key:Key('__header__'),
        //physics: AlwaysScrollableScrollPhysics(),
        //padding: EdgeInsets.only(),
        children: _pageSelector(context)
      );
  }
}

轮播图事件控制,拖拽,点击,标题显示,指示器等

import 'dart:async';
import 'package:flutter/material.dart';
import './story.dart';

class HomeBanner extends StatefulWidget {
  final List<StoryModel> bannerStories;
  final OnTapBannerItem onTap;

  HomeBanner(this.bannerStories, this.onTap, {Key key})
      :super(key: key);

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

class _BannerState extends State<HomeBanner> {
  int virtualIndex = 0;
  int realIndex = 1;
  PageController controller;
  Timer timer;

  @override
  void initState() {
    super.initState();
    controller = PageController(
                                initialPage: realIndex, 
                                //viewportFraction: 0.8//所占屏幕比例
                                );
    timer = Timer.periodic(Duration(seconds: 2), (timer) { // 自动滚动
      //  print(realIndex);
      controller.animateToPage(realIndex + 1,
          duration: Duration(milliseconds: 500),
          curve: Curves.linear);
    });
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
    timer.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200.0,
      child: Stack(
         alignment: Alignment.bottomCenter,//小点的位置
          children: <Widget>[
            PageView(
              controller: controller,
              onPageChanged: _onPageChanged,
              children: _buildItems(),
              ),
            _buildIndicator(), // 上面的小点
          ]),
    );
  }

  List<Widget> _buildItems() { // 排列轮播数组
    List<Widget> items = [];
    if (widget.bannerStories.length > 0) {
      // 头部添加一个尾部Item,模拟循环
      items.add(
          _buildItem(widget.bannerStories[widget.bannerStories.length - 1]));
      // 正常添加Item
      items.addAll(
          widget.bannerStories.map((story) => _buildItem(story)).toList(
              growable: false));
      // 尾部
      items.add(
          _buildItem(widget.bannerStories[0]));
    }
    return items;
  }
//每一个图片的点击事件
  Widget _buildItem(StoryModel story) {
    return GestureDetector(
      onTap: () { // 按下
        if (widget.onTap != null) {
          widget.onTap(story);
        }
      },
      child: Stack(
        fit: StackFit.expand,
        children: <Widget>[
         Image.network(story.image, fit: BoxFit.cover),
          _buildItemTitle(story.title), // 内容文字,大意
        ],),);
  }
//图片title
  Widget _buildItemTitle(String title) {
    return Container(
      decoration: BoxDecoration( /// 背景的渐变色
        gradient: LinearGradient(
          begin: Alignment.bottomCenter,
          end: const Alignment(0.0, -0.8),
          colors: [const Color(0xa0000000), Colors.transparent],
        ),
      ),
      alignment: Alignment.bottomCenter,
      child: Container(
        margin: EdgeInsets.symmetric(vertical: 22.0, horizontal: 16.0),
        child: Text(
          title, style: TextStyle(color: Colors.white, fontSize: 18.0),),),
    );
  }
//指示器显示
  Widget _buildIndicator() {
    List<Widget> indicators = [];
    for (int i = 0; i < widget.bannerStories.length; i++) {
      indicators.add(Container(
          width: 6.0,
          height: 6.0,
          margin: EdgeInsets.symmetric(horizontal: 1.5, vertical: 10.0),
          decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: i == virtualIndex ? Colors.white : Colors.grey)));
    }
    return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: indicators);
  }
//页面切换的时候
  _onPageChanged(int index) {
    realIndex = index;
    int count = widget.bannerStories.length;
    if (index == 0) {
      virtualIndex = count - 1;
      controller.jumpToPage(count);
    } else if (index == count + 1) {
      virtualIndex = 0;
      controller.jumpToPage(1);
    } else {
      virtualIndex = index - 1;
    }
    setState(() {});
  }
}

typedef void OnTapBannerItem(StoryModel story);

github源码地址: https://github.com/1136346879/flutter_url_launcher_banner

猜你喜欢

转载自blog.csdn.net/wdx_1136346879/article/details/89174393