前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter实现App功能引导页

Flutter实现App功能引导页

作者头像
砸漏
发布2020-10-18 22:50:32
1.9K0
发布2020-10-18 22:50:32
举报
文章被收录于专栏:恩蓝脚本恩蓝脚本

App功能介绍页,主要是由介绍app功能的几张图片和当前页指示符组成,如下效果

我们来一步一步实现上面的界面,左右滑动切换显示功能页,这个可以通过PageView来实现,底部的指示符半透明覆盖在PageView上,开发过Android同学知道可以用Framelayout布局来实现,Flutter上也有类似的控件Stack,我们先完成骨架代码

代码语言:javascript
复制
// An highlighted block
void 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用来控制显示哪一页,先定义它

代码语言:javascript
复制
class _AppFuncBrowseState extends State<AppFuncBrowse  {
 PageController _pageController = PageController();
 //省略...
}

有了PageController我们就可以创建PageView,代码如下

代码语言:javascript
复制
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还没提供该原生控件,我们只能自己实现它,其实也很简单,代码如下:

代码语言:javascript
复制
 _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,其对应上面属性刚好相反

上面属性的其他值可以自己试验,我们这里用到

代码语言:javascript
复制
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,

表示子控件左右(包含与父控件)间距相同,并且宽度保持最小,最后我们来实现三个点,当前页的对应的点颜色需要和其他未显示的页有所区别,我们需要记录当前是第几页,从而使对应的第几个点highlight显示

代码语言:javascript
复制
class _AppFuncBrowseState extends State<AppFuncBrowse  {
 PageController _pageController = PageController();
 int _pageIndex = 0;

然后就可以创建点了

代码语言:javascript
复制
 _dotWidget(int index) {
 return Container(
  width: 10,
  height: 10,
  decoration: BoxDecoration(
   shape: BoxShape.circle,
   color: (_pageIndex == index) ? Colors.white70 : Colors.black12));
 }

滑动PageView,需要更新_pageIndex,从而对应的更新当前页对应的点的颜色

代码语言:javascript
复制
return PageView(
  controller: _pageController,
  onPageChanged: (pageIndex) {
  setState(() {
   _pageIndex = pageIndex;
   print(_pageController.page);
   print(pageIndex);
  });
  },

onPageChanged就是PageView换页的事件,这里需要调用setState从而使Widget重建更新当前页的点颜色 到这里为止就剩下点击点更新PageView的功能了,我们来实现点击功能,就是监听点击手势,代码如下

代码语言:javascript
复制
 _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,具体定义如下

代码语言:javascript
复制
class _AppFuncBrowseState extends State<AppFuncBrowse  {
 PageController _pageController = PageController();
 int _pageIndex = 0;
 GlobalKey<_AppFuncBrowseState  _pageIndicatorKey = GlobalKey();

现在只剩下前后翻页的代码了,代码如下

代码语言:javascript
复制
 _scrollToPreviousPage() {
 if (_pageIndex   0) {
  _pageController.animateToPage(_pageIndex - 1,
   duration: const Duration(milliseconds: 200), curve: Curves.ease);
 }
 }

以上就是本文的全部内容,希望对大家的学习有所帮助。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档