【移动应用开发技术】利用Flutter怎么实现一个走马灯布局_第1页
【移动应用开发技术】利用Flutter怎么实现一个走马灯布局_第2页
【移动应用开发技术】利用Flutter怎么实现一个走马灯布局_第3页
【移动应用开发技术】利用Flutter怎么实现一个走马灯布局_第4页
【移动应用开发技术】利用Flutter怎么实现一个走马灯布局_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】利用Flutter怎么实现一个走马灯布局

本篇文章给大家分享的是有关利用Flutter怎么实现一个走马灯布局,在下觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着在下一起来看看吧。创建首页首先创建一个IndexPage部件,这个部件用来放PageView,因为需要使用setState方法更新UI,所以它是stateful的。import

'package:flutter/material.dart';

class

IndexPage

extends

StatefulWidget

{

@override

_IndexPageState

createState()

=>

_IndexPageState();

}

class

_IndexPageState

extends

State<IndexPage>

{

@override

Widget

build(BuildContext

context)

{

return

Scaffold(

appBar:

AppBar(

elevation:

0.0,

backgroundColor:

Colors.white,

),

body:

Column(

children:

<Widget>[],

),

);

}

}然后在部件内申明一个_pageIndex变量用来保存当前显示的页面的index,在initState生命周期里面初始化一个PageController用来配置PageView部件。在body的Column里面创建一个PageView.builder,使用一个SizedBox部件指定PageView的高度,将controller设置为_pageController,在onPageChanged事件里将当前显示页面的index值赋值给_pageIndex变量。int

_pageIndex

=

0;

PageController

_pageController;

@override

void

initState()

{

super.initState();

_pageController

=

PageController(

initialPage:

0,

viewportFraction:

0.8,

);

}

body:

Column(

children:

<Widget>[

SizedBox(

height:

580.0,

child:

PageView.builder(

itemCount:

3,

pageSnapping:

true,

controller:

_pageController,

onPageChanged:

(int

index)

{

setState(()

{

_pageIndex

=

index;

});

},

itemBuilder:

(BuildContext

ctx,

int

index)

{

return

_buildItem(_pageIndex,

index);

},

),

),

],

),关键点:设置PageController的viewportFraction参数小于1,这个值是用来设置每个页面在屏幕上显示的比例,小于1的话,就可以在当前页面同时显示其它页面的内容了。///

The

fraction

of

the

viewport

that

each

page

should

occupy.

///

Defaults

to

1.0,

which

means

each

page

fills

the

viewport

in

the

scrolling

direction.

final

double

viewportFraction;实现_buildItem接着实现_buildItem方法,这个方法就是返回PageView.builder里每一个页面渲染的内容,第一个参数activeIndex是当前显示在屏幕上页面的index,第二个参数index是每一项自己的index。使用一个Center部件让内容居中显示,然后用一个AnimatedContainer添加页面切换时的高度变化的动画效果,切换页面的时候使用了setState方法改变了_pageIndex,Flutter重新绘制每一项。关键点在于判断当前页面是否为正在显示的页面,是的话它的高度就是500不是的话就是450。_buildItem(activeIndex,

index)

{

return

Center(

child:

AnimatedContainer(

curve:

Curves.easeInOut,

duration:

Duration(milliseconds:

300),

height:

activeIndex

==

index

?

500.0

:

450.0,

margin:

EdgeInsets.symmetric(vertical:

20.0,

horizontal:

10.0),

decoration:

BoxDecoration(

color:

heroes[index].color,

borderRadius:

BorderRadius.all(Radius.circular(12.0)),

),

child:

Stack(),

),

);

}

添加内容然后给AnimatedContainer添加每一项的内容child:

Stack(

fit:

StackFit.expand,

children:

<Widget>[

ClipRRect(

borderRadius:

BorderRadius.all(

Radius.circular(12.0),

),

child:

Iwork(

heroes[index].image,

fit:

BoxFit.cover,

),

),

Align(

alignment:

Alignment.bottomCenter,

child:

Row(

children:

<Widget>[

Expanded(

child:

Container(

padding:

EdgeInsets.all(12.0),

decoration:

BoxDecoration(

color:

Colors.black26,

borderRadius:

BorderRadius.only(

bottomRight:

Radius.circular(12.0),

bottomLeft:

Radius.circular(12.0),

),

),

child:

Text(

heroes[index].title,

textAlign:

TextAlign.center,

style:

TextStyle(

fontSize:

20.0,

fontWeight:

FontWeight.bold,

color:

Colors.white,

),

),

),

)

],

),

),

],

),实现指示器然后实现页面的指示器,创建一个PageIndicator部件,需要传入pageCount表示总页数,以及currentIndex表示当前显示的页数索引。把所有指示器放在一个Row部件里,判断当前指示器的index是否为正在显示页面的index,是的话显示较深的颜色。class

PageIndicator

extends

StatelessWidget

{

final

int

pageCount;

final

int

currentIndex;

const

PageIndicator(this.currentIndex,

this.pageCount);

Widget

_indicator(bool

isActive)

{

return

Container(

width:

6.0,

height:

6.0,

margin:

EdgeInsets.symmetric(horizontal:

3.0),

decoration:

BoxDecoration(

color:

isActive

?

Color(0xff666a84)

:

Color(0xffb9bcca),

shape:

BoxShape.circle,

boxShadow:

[

BoxShadow(

color:

Colors.black12,

offset:

Offset(0.0,

3.0),

blurRadius:

3.0,

),

],

),

);

}

List<Widget>

_buildIndicators()

{

List<Widget>

indicators

=

[];

for

(int

i

=

0;

i

<

pageCount;

i++)

{

indicators.add(i

==

currentIndex

?

_indicator(true)

:

_indicator(false));

}

return

indicators;

}

@override

Widget

build(BuildContext

context)

{

return

Row(

mainAxisAlignment:

MainAxisAlignment.center,

children:

_buildIndicators(),

);

}

}添加PageIndicator到SizedBox下面封装Carousel最后的最后优化一下代码,把部件封装一下,让它成为一个单独的部件,创建一个Carousel部件,对外暴露items和height两个属性,分别配置数据和高度。class

Carousel

extends

StatefulWidget

{

final

List

items;

final

double

height;

const

Carousel({

@required

this.items,

@required

this.height,

});

@override

_CarouselState

createState()

=>

_CarouselState();

}

class

_CarouselState

extends

State<Carousel>

{

int

_pageIndex

=

0;

PageController

_pageController;

Widget

_buildItem(activeIndex,

index)

{

final

items

=

widget.items;

return

Center(

child:

AnimatedContainer(

curve:

Curves.easeInOut,

duration:

Duration(milliseconds:

300),

height:

activeIndex

==

index

?

500.0

:

450.0,

margin:

EdgeInsets.symmetric(vertical:

20.0,

horizontal:

10.0),

decoration:

BoxDecoration(

color:

items[index].color,

borderRadius:

BorderRadius.all(Radius.circular(12.0)),

),

child:

Stack(

fit:

StackFit.expand,

children:

<Widget>[

ClipRRect(

borderRadius:

BorderRadius.all(

Radius.circular(12.0),

),

child:

Iwork(

items[index].image,

fit:

BoxFit.cover,

),

),

Align(

alignment:

Alignment.bottomCenter,

child:

Row(

children:

<Widget>[

Expanded(

child:

Container(

padding:

EdgeInsets.all(12.0),

decoration:

BoxDecoration(

color:

Colors.black26,

borderRadius:

BorderRadius.only(

bottomRight:

Radius.circular(12.0),

bottomLeft:

Radius.circular(12.0),

),

),

child:

Text(

items[index].title,

textAlign:

TextAlign.center,

style:

TextStyle(

fontSize:

20.0,

fontWeight:

FontWeight.bold,

color:

Colors.white,

),

),

),

)

],

),

),

],

),

),

);

}

@override

void

initState()

{

super.initState();

_pageController

=

PageController(

initialPage:

0,

viewportFraction:

0.8,

);

}

@override

Widget

build(BuildContext

context)

{

return

Column(

children:

<Widget>[

Container(

height:

widget.height,

child:

PageView.builder(

pageSnapping:

true,

itemCount:

heroes.length,

controller:

_pageController,

onPageChanged:

(int

index)

{

setState(()

{

_pageIndex

=

index;

});

},

itemBuilder:

(BuildContext

ctx,

int

index)

{

return

_buildItem(_pageIndex,

index);

},

),

),

PageIndicator(_pageIndex,

widget.items.length),

],

);

}

}之后在IndexPage部件里就只用实例化一个Carousel了,同时由于IndexPage不用管理部件状态了,可以将它变成StatelessWidget。完整代码import

'package:flutter/material.dart';

class

Hero

{

final

Color

color;

final

String

image;

final

String

title;

Hero({

@required

this.color,

@required

this.image,

@required

this.title,

});

}

List

heroes

=

[

Hero(

color:

Color(0xFF86F3FB),

image:

"/images/lol/act/img/skin/big22009.jpg",

title:

'寒冰射手-艾希',

),

Hero(

color:

Color(0xFF7D6588),

image:

"/images/lol/act/img/skin/big39006.jpg",

title:

'刀锋舞者-艾瑞莉娅',

),

Hero(

color:

Color(0xFF4C314D),

image:

"/images/lol/act/img/skin/big103015.jpg",

title:

'九尾妖狐-阿狸',

),

];

class

Carousel

extends

StatefulWidget

{

final

List

items;

final

double

height;

const

Carousel({

@required

this.items,

@required

this.height,

});

@override

_CarouselState

createState()

=>

_CarouselState();

}

class

_CarouselState

extends

State<Carousel>

{

int

_pageIndex

=

0;

PageController

_pageController;

Widget

_buildItem(activeIndex,

index)

{

final

items

=

widget.items;

return

Center(

child:

AnimatedContainer(

curve:

Curves.easeInOut,

duration:

Duration(milliseconds:

300),

height:

activeIndex

==

index

?

500.0

:

450.0,

margin:

EdgeInsets.symmetric(vertical:

20.0,

horizontal:

10.0),

decoration:

BoxDecoration(

color:

items[index].color,

borderRadius:

BorderRadius.all(Radius.circular(12.0)),

),

child:

Stack(

fit:

StackFit.expand,

children:

<Widget>[

ClipRRect(

borderRadius:

BorderRadius.all(

Radius.circular(12.0),

),

child:

Iwork(

items[index].image,

fit:

BoxFit.cover,

),

),

Align(

alignment:

Alignment.bottomCenter,

child:

Row(

children:

<Widget>[

Expanded(

child:

Container(

padding:

EdgeInsets.all(12.0),

decoration:

BoxDecoration(

color:

Colors.black26,

borderRadius:

BorderRadius.only(

bottomRight:

Radius.circular(12.0),

bottomLeft:

Radius.circular(12.0),

),

),

child:

Text(

items[index].title,

textAlign:

TextAlign.center,

style:

TextStyle(

fontSize:

20.0,

fontWeight:

FontWeight.bold,

color:

Colors.white,

),

),

),

)

],

),

),

],

),

),

);

}

@override

void

initState()

{

super.initState();

_pageController

=

PageController(

initialPage:

0,

viewportFraction:

0.8,

);

}

@override

Widget

build(BuildContext

context)

{

return

Column(

children:

<Widget>[

Container(

height:

widget.height,

child:

PageView.builder(

pageSnapping:

true,

itemCount:

heroes.length,

controller:

_pageController,

onPageChanged:

(int

index)

{

setState(()

{

_pageIndex

=

index;

});

},

itemBuilder:

(BuildContext

ctx,

int

index)

{

return

_buildItem(_pageIndex,

index);

},

),

),

PageIndicator(_pageIndex,

widget.items.length),

],

);

}

}

class

PageIndicator

extends

StatelessWidget

{

final

int

currentIndex;

final

int

pageCount;

const

PageIndicator(th

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论