这篇文章将为大家详细讲解有关如何使用Flutter实现App功能引导页,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
App功能介绍页,主要是由介绍app功能的几张图片和当前页指示符组成,如下效果
我们来一步一步实现上面的界面,左右滑动切换显示功能页,这个可以通过PageView来实现,底部的指示符半透明覆盖在PageView上,开发过Android同学知道可以用Framelayout布局来实现,Flutter上也有类似的控件Stack,我们先完成骨架代码
// An highlighted blockvoid main() => runApp(App());class App extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Title', theme: ThemeData( primarySwatch: Colors.blue, ), home: AppFuncBrowse(), ); }}class AppFuncBrowse extends StatefulWidget { @override _AppFuncBrowseState createState() { return _AppFuncBrowseState(); }}class _AppFuncBrowseState extends State<AppFuncBrowse> { @override Widget build(BuildContext context) { return Scaffold( body: Container( color: Colors.white, child: Stack( children: <Widget>[ ], ), )); }}
AppFuncBrowse 就是我们功能介绍页,上面编译运行功能后,我们先来着手实现功能介绍页面切换,PageView主要有两类构建函数,一个是懒加载页面(适合页面很多时使用),一个是适合少量页面的一次性加载的,我们实例显示3个页面,就简单的用这种方式, PageView用到了PageController用来控制显示哪一页,先定义它
class _AppFuncBrowseState extends State<AppFuncBrowse> { PageController _pageController = PageController(); //省略...}
有了PageController我们就可以创建PageView,代码如下
Widget _createPageView() { return PageView( controller: _pageController, onPageChanged: (pageIndex) { setState(() { _pageIndex = pageIndex; print(_pageController.page); print(pageIndex); }); }, children: <Widget>[ Container( color: Colors.blue, child: Center( child: Text('Page 1'), ), ), Container( color: Colors.red, child: Center( child: Text('Page 2'), ), ), Container( color: Colors.green, child: Center( child: Text('Page 3'), ), ), ], ); }@override Widget build(BuildContext context) { // TODO: implement build return Scaffold( body: Container( color: Colors.white,// margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top), child: Stack( children: <Widget>[ _createPageView(), ], ), )); }
到这里我们完成了一个可以左右滑动的功能页, 每页的内容大家可以自定义,一般是一张图片,我这里为了简单起见直接显示Text,到目前为止我们离目标还缺一个页码指示器,学过iOS的非常熟悉,需要用到UIPageControl,可惜的是到目前为止Flutter还没提供该原生控件,我们只能自己实现它,其实也很简单,代码如下:
_createPageIndicator() { return Opacity( opacity: 0.7, child: Align( alignment: FractionalOffset.bottomCenter, child: Container( margin: EdgeInsets.only(bottom: 60), height: 40, width: 80, padding: EdgeInsets.all(0), decoration: BoxDecoration( color: Colors.grey, //.withAlpha(128), borderRadius: BorderRadius.all(const Radius.circular(6.0))), child: GestureDetector( behavior: HitTestBehavior.translucent, onTapUp: (detail) => _handlePageIndicatorTap(detail), child: Row( key: _pageIndicatorKey, mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.min, children: <Widget>[ _dotWidget(0), _dotWidget(1), _dotWidget(2), ]), ), ), ), ); }
咋一看感觉好复杂,其实也很简单,学过设计模式的同学可能看出和装饰者模式一样,widget层次结构就类似这种模式,这也是Flutter的强大之处,用现有的控件可以组合出各种效果,首先我们用Opacity控件来封装子控件,设置opacity使其成为半透明,然后使用Align控制其底部对齐,为了使其距离底部一段距离,还需要Container来包装,为了实现圆角的Container,强大的decoration属性就登场了,它能实现各种装饰效果,这里我们实现的效果是灰色背景和圆角。
现在讲完了这些装修,就剩下三个点了,三个点在同一水平线上,所以我们用Row来做为父控件,Row有几个属性值注意
mainAxisAlignment 主轴对齐方式,Row的主轴是水平方向,crossAxisAlignment 主轴的垂直方向对齐方式,Row的主轴是水平方向,所以该字段表示上下对齐方式mainAxisSize 主轴方向的大小,对Row来说即宽度与Row对应的控件是Column,其对应上面属性刚好相反
上面属性的其他值可以自己试验,我们这里用到
mainAxisAlignment: MainAxisAlignment.spaceEvenly,mainAxisSize: MainAxisSize.min,
表示子控件左右(包含与父控件)间距相同,并且宽度保持最小,最后我们来实现三个点,当前页的对应的点颜色需要和其他未显示的页有所区别,我们需要记录当前是第几页,从而使对应的第几个点highlight显示
class _AppFuncBrowseState extends State<AppFuncBrowse> { PageController _pageController = PageController(); int _pageIndex = 0;
然后就可以创建点了
_dotWidget(int index) { return Container( width: 10, height: 10, decoration: BoxDecoration( shape: BoxShape.circle, color: (_pageIndex == index) ? Colors.white70 : Colors.black12)); }
滑动PageView,需要更新_pageIndex,从而对应的更新当前页对应的点的颜色
return PageView( controller: _pageController, onPageChanged: (pageIndex) { setState(() { _pageIndex = pageIndex; print(_pageController.page); print(pageIndex); }); },
onPageChanged就是PageView换页的事件,这里需要调用setState从而使Widget重建更新当前页的点颜色到这里为止就剩下点击点更新PageView的功能了,我们来实现点击功能,就是监听点击手势,代码如下
_handlePageIndicatorTap(TapUpDetails detail) { RenderBox renderBox = _pageIndicatorKey.currentContext.findRenderObject(); Size widgeSize = renderBox.paintBounds.size; Offset tapOffset = renderBox.globalToLocal(detail.globalPosition); if (tapOffset.dx > widgeSize.width / 2) { _scrollToNextPage(); } else { _scrollToPreviousPage(); } }
手势有一个属性behavior需要值得注意,默认值为deferToChild,具体取值如下:
behavior: HitTestBehavior.translucent 控制响应的点击区域:translucent 表示整个区域,被遮挡的子视图也能响应opaque 表示整个区域,被遮挡的子视图不能响应deferToChild 表示点击到子视图才响应,手势默认behavior
需要实现点击左半部分向前翻页,点击后半部分向后翻页,我们需要判断当前点击的区域,这就需要找到Row的RenderObject来获取控件区域,然后获取点击相对控件的偏移来确定,具体见代码,_pageIndicatorKey就是传给Row的key,具体定义如下
class _AppFuncBrowseState extends State<AppFuncBrowse> { PageController _pageController = PageController(); int _pageIndex = 0; GlobalKey<_AppFuncBrowseState> _pageIndicatorKey = GlobalKey();
现在只剩下前后翻页的代码了,代码如下
_scrollToPreviousPage() { if (_pageIndex > 0) { _pageController.animateToPage(_pageIndex - 1, duration: const Duration(milliseconds: 200), curve: Curves.ease); } }
关于“如何使用Flutter实现App功能引导页”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。