使用Flutter实现一个走马灯布局的示例代码

使用Flutter实现一个走马灯布局的示例代码,第1张

概述使用Flutter实现一个走马灯布局的示例代码 走马灯是一种常见的效果,本文讲一下如何用 PageView 在 Flutter 里实现一个走马灯, 效果如下,当前页面的高度比其它页面高,切换页面的时候有一个高度变化的动画.实现这样的效果主要用到的是 PageView.builder 部件. 开发 创建首页 首先创建一个 IndexPage 部件,这个部件用来放 PageView ,因为需要使用 setState 方法更新 UI,所以它是 stateful 的. import 'package:flutter/material.dart'; c

走马灯是一种常见的效果,本文讲一下如何用 PageVIEwFlutter 里实现一个走马灯,效果如下,当前页面的高度比其它页面高,切换页面的时候有一个高度变化的动画。实现这样的效果主要用到的是 PageVIEw.builder 部件。


开发

创建首页

首先创建一个 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 部件。

bodyColumn 里面创建一个 PageVIEw.builder ,使用一个 SizedBox 部件指定 PageVIEw 的高度,将 controller 设置为 _pageController ,在 onPageChanged 事件里将当前显示页面的 index 值赋值给 _pageIndex 变量。

int _pageIndex = 0;PageController _pageController;@overrIDevoID 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); },],

关键点: 设置 PageControllervIEwportFraction 参数小于 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 方法改变了 _pageIndexFlutter 重新绘制每一项。关键点在于判断当前页面是否为正在显示的页面,是的话它的高度就是 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: Image.network( 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(),); }}

添加 PageIndicatorSizedBox 下面

封装 Carousel

最后的最后优化一下代码,把部件封装一下,让它成为一个单独的部件,创建一个 Carousel 部件,对外暴露 itemsheight 两个属性,分别配置数据和高度。

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,decoration: Boxdecoration(  color: items[index].color,child: Stack(  fit: StackFit.expand,children: <Widget>[  ClipRRect(  borderRadius: borderRadius.all(  Radius.circular(12.0),child: Image.network(  items[index].image,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),child: Text(   items[index].Title,style: TextStyle(    FontSize: 20.0,)  ],); } @overrIDe voID initState() { super.initState(); _pageController = PageController( initialPage: 0,); } @overrIDe Widget build(BuildContext context) { return Column( children: <Widget>[ Container(  height: Widget.height,child: PageVIEw.builder(  pageSnapPing: true,itemCount: heroes.length,onPageChanged: (int index) {  setState(() {  _pageIndex = index;  });  },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: "https://game.gtimg.cn/images/lol/act/img/skin/big22009.jpg",Title: '寒冰射手-艾希',Hero( color: color(0xFF7D6588),image: "https://game.gtimg.cn/images/lol/act/img/skin/big39006.jpg",Title: '刀锋舞者-艾瑞莉娅',Hero( color: color(0xFF4C314D),image: "https://game.gtimg.cn/images/lol/act/img/skin/big103015.jpg",Title: '九尾妖狐-阿狸',];class Carousel extends StatefulWidget { final List items; final double height; const Carousel({ @required this.items,); }}class PageIndicator extends StatelessWidget { final int currentIndex; final int pageCount; const PageIndicator(this.currentIndex,); }}class IndexPage extends StatelessWidget { @overrIDe Widget build(BuildContext context) { return Scaffold( appbar: Appbar( elevation: 0.0,body: Carousel( height: 540,items: heroes,); }}

至此,整个布局就完成了! :sunglasses:

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

总结

以上是内存溢出为你收集整理的使用Flutter实现一个走马灯布局的示例代码全部内容,希望文章能够帮你解决使用Flutter实现一个走马灯布局的示例代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144286.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存