功能引导 android,Flutter实现App功能引导页

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

1e2d56f454f2d007c9b226a5da4c251a.png

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

// 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 {

@override

Widget build(BuildContext context) {

return Scaffold(

body: Container(

color: Colors.white,

child: Stack(

children: [

],

),

));

}

}

AppFuncBrowse 就是我们功能介绍页,上面编译运行功能后,我们先来着手实现功能介绍页面切换,PageView主要有两类构建函数,一个是懒加载页面(适合页面很多时使用),一个是适合少量页面的一次性加载的,我们实例显示3个页面,就简单的用这种方式, PageView用到了PageController用来控制显示哪一页,先定义它

class _AppFuncBrowseState extends State {

PageController _pageController = PageController();

//省略...

}

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

Widget _createPageView() {

return PageView(

controller: _pageController,

onPageChanged: (pageIndex) {

setState(() {

_pageIndex = pageIndex;

print(_pageController.page);

print(pageIndex);

});

},

children: [

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: [

_createPageView(),

],

),

));

}

bf5ae0669cd3de0ad0e73a982c213d42.png

到这里我们完成了一个可以左右滑动的功能页, 每页的内容大家可以自定义,一般是一张图片,我这里为了简单起见直接显示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: [

_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 {

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 {

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);

}

}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/571357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue项目调用jssip_JsSIP和FreeSWITCH整合

写在前面&#xff1a;FreeSWITCH作为服务器&#xff0c;通过SIP协议&#xff0c;Web端使用jssipwebrtc和其他软电话进行通信一、先配置FreeSWITCH(用的版本1.6.20)的配置&#xff1a;1 、修改vars.xml文件&#xff0c;找到下面字段&#xff0c;并设置2、修改 autoload_configs/…

ios禁止页面下拉

document.querySelector(body).addEventListener(touchmove, function(e) { e.preventDefault();})此类事件是手机touchmove默认事件行为&#xff0c;可以通过js代码禁止默认事件&#xff1a;转载于:https://www.cnblogs.com/zhouyx/p/8145182.html

android中虚拟程序停止,为什么我的在虚拟机运行后出现应用程序停止运行

源自&#xff1a;9-2 使用ToggleButton按钮实现开关效果为什么我的在虚拟机运行后出现应用程序停止运行package com.example.sss;import com.example.android4_0.R;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuIt…

android layout(l, t, r, b);,服务器里的a,t,l,r,b是什么意思? Android编程中关于layout(l,t,r,b)函数的问题...

导航&#xff1a;网站首页 >服务器里的a,t,l,r,b是什么意思? Android编程中关于layout(l,t,r,b)函数的问题服务器里的a,t,l,r,b是什么意思? Android编程中关于layout(l,t,r,b)函数的问题相关问题:匿名网友:我们知道&#xff0c;屏幕的分辨率往往以“像素数 x 像素数”的格…

python里else中文意思_Python循环语句中else的用法总结

前言本文讨论Python的for…else和while…else等语法&#xff0c;这些是Python中最不常用、最为误解的语法特性之一。Python中的for、while等循环都有一个可选的else分支(类似if语句和try语句那样)&#xff0c;在循环迭代正常完成之后执行。换句话说&#xff0c;如果我们不是以除…

go语言 方法

go 语言中没有类&#xff0c;但是是有方法。 方法的定义&#xff1a; func (recevier type) methodName(参数列表)(返回值列表){ } type School struct {Name stringAddr string }func NewSchool(name, addr string) *School {return &School {Name:name,Addr:addr,} }fun…

android 获取加速度传感器值,Android开发获取传感器数据的方法示例【加速度传感器,磁场传感器,光线传感器,方向传感器】...

本文实例讲述了Android开发获取传感器数据的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;package mobile.android.sensor;import java.util.List;import android.app.Activity;import android.hardware.Sensor;import android.hardware.SensorEvent;import and…

ocp oracle 考试报名_获得Oracle认证对拓展职业前景的影响

知识就是力量通过考试和考试成绩固然很重要&#xff0c;但您在学习过程中所掌握的知识才是您职业成功的坚实基础。在备考过程中&#xff0c;获得的知识和经验才是您真正的财富。Oracle Certified Associate (OCA)&#xff1a;专员级别的认证能够证明学员具备基本技能&#xff0…

SpringMVC(2)—SpringMVC整合Spring的HelloWorld

一、这是一个SpringMVC框架的案例HelloWorld 功能&#xff1a;HelloWorld 二、SpringMVC运行流程 1.流程 请求——>springDispatcherServlet的url-pattern检查SpringMVC中是否存在对应的映射无&#xff1a;检查是否配置的<mvc:default-servlet-handler/>无&#xff…

mac android 录屏软件下载,苹果录屏app下载 苹果录屏 for Android V2.1.3 安卓手机版 下载-脚本之家...

苹果录屏是一款不错的手机录屏软件&#xff0c;该软件能帮助你录制流畅清晰视频&#xff0c;实现屏幕内容实时同步录制&#xff0c;录制视频流畅清晰不卡顿&#xff0c;需要的朋友可以下载使用。应用介绍苹果录屏&#xff0c;是一款免费屏幕录制软件&#xff0c;能帮助你录制流…

火箭技术术语_仿真优化火箭发动机 3D 打印制造工艺

台湾工业技术研究院(ITRI)为台湾创新空间(TiSPACE)提供增材制造(也称 3D 打印技术)服务&#xff0c;包括原始设计制造、重新设计和仿真等。TiSPACE 的固液火箭发动机中使用的燃料喷射器组件的 3D 打印过程为&#xff1a;首先&#xff0c;激光将第一层粉末熔化并融合到构建板上&…

车林通购车之家--购车计算器模块--保险

//car-calculator-bx.twig {{ include(jsq-nav.twig) }} <div class"switch-item active" id"bodya"><div class"top-layer2 clearfix"><div class"tit"><span>新车保险市场价</span></div><…

麒麟710f能否升级到鸿蒙系统,定了!麒麟710以上支持升级鸿蒙系统,荣耀也可以升级...

原标题&#xff1a;定了&#xff01;麒麟710以上支持升级鸿蒙系统&#xff0c;荣耀也可以升级华为Mate X2发布会上&#xff0c;余承东表示4月份推送手机版鸿蒙系统&#xff0c;距离首发日期越来越近。不少朋友关心&#xff0c;哪些机型支持鸿蒙系统&#xff0c;荣耀手机可以更新…

我的奇思妙想机器人消防员_我是小小消防员(绘画篇)|来啊~斗图啊~看一场奇思妙想SHOW!...

点击上方 “四川消防119” 关注我们来&#xff0c;来&#xff0c;来快来进入孩子们脑洞大开的世界吧&#xff01;自今年6月以来&#xff0c;我们火热开展了“暑期消防安全教育专项行动”之“我是小小消防员”儿童消防绘画、作文竞赛活动&#xff0c;吸引了全省幼儿园小盆友、小…

mysql数据备份(windows,linux)

今天我有个朋友让我帮他在windowServer服务器上备份一下mysql的数据库&#xff0c;于是花了一天的时间完成了一个每天定时备份数据库的功能&#xff0c;小编在这里为大家记录一下&#xff1a; 首先对于mysql命令行的导入导出作一个简单的梳理 一、导入 ①mysql -h主机 -u账号 -…

android5.1.1移植教程,iTOP4412开发板Android5.1.1移植教程

对于传统的操作系统来说&#xff0c;普通的 I/O 操作一般会被内核缓存&#xff0c;这种 I/O 被称作缓存 I/O。本文所介绍的文件访问机制不经过操作系统内核的缓存&#xff0c;数据直接在磁盘和应用程序地址空间进行传输&#xff0c;所以该文件访问的机制称作为直接 I/O。Linux …

岗位po是什么意思_劳务派遣是什么意思,劳务派遣和正式员工区别在哪

劳务派遣也是劳动活动的一种&#xff0c;虽然性质相对于临时工&#xff0c;但是劳务派遣仍然属于劳动合同法所调整的&#xff0c;不过与正式员工存在一定区别。因此接下来将由找法网小编为您介绍关于劳务派遣是什么意思&#xff0c;劳务派遣和正式员工区别在哪及其相关方面的知…

Android对性能要求,Android性能管理

管理Android设备的功耗和性能有助于确保应用程序在各种硬件上始终如一地顺畅运行。在Android 7.0及更高版本中&#xff0c;OEM可以实现对持续性能提示的支持&#xff0c;使应用程序能够保持一致的设备性能&#xff0c;并指定专属核以提高CPU密集型前台应用程序的性能。持续性能…

BZOJ 1878: [SDOI2009]HH的项链 | 莫队

题解: http://www.lydsy.com/JudgeOnline/problem.php?id1878 题解: 莫队板子题 核心思想是对区间的询问离线之后按照合理的顺序来优化复杂度 一般的做法是先分块,以左端点所在块为第一关键字,右端点位置为第二关键字排序 用两个指针来跑,这样可以证明的是时间复杂度为O(n√n)…

layui导航栏页面滚动固定_帮你搞定长滚动网页的设计!这5种设计策略需谨记!...

网站中的内容再好&#xff0c;总得让用户能看到&#xff0c;才有价值&#xff0c;而矛盾在于&#xff0c;首屏的空间始终是有限的。所以&#xff0c;我们总希望用户能够滚动页面向下看&#xff0c;从某种意义上来说&#xff0c;长滚动页面和无限滚动的设计&#xff0c;如此地受…