Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Flutter to implement a Walking Lantern layout

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is about how to use Flutter to implement a walking lantern layout. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Walking lantern is a common effect, this article talks about how to use PageView to achieve a walking lantern in Flutter, the effect is as follows, the height of the current page is higher than other pages, there is a height change animation when switching pages. PageView.builder widgets are mainly used to achieve this effect.

Development

Create the home page

First create an IndexPage part, which is used to hold the PageView, because you need to update the UI using the setState method, so it is stateful.

Import 'package:flutter/material.dart';class IndexPage extends StatefulWidget {@ override _ IndexPageState createState () = > _ IndexPageState ();} class _ IndexPageState extends State {@ override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (elevation: 0.0, backgroundColor: Colors.white,), body: Column (children: [],),);}}

Then declare a _ pageIndex variable inside the widget to hold the index of the currently displayed page, and initialize a PageController to configure the PageView widget during the initState life cycle.

Create a PageView.builder in the Column of body, use a SizedBox widget to specify the height of the PageView, set controller to _ pageController, and assign the index value of the currently displayed page to the _ pageIndex variable in the onPageChanged event.

Int _ pageIndex = 0 body PageController _ pageController;@overridevoid initState () {super.initState (); _ pageController = PageController (initialPage: 0, viewportFraction: 0.8,);} body: Column (children: [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) },),),],)

Key point: set the viewportFraction parameter of PageController less than 1, this value is used to set the ratio of each page displayed on the screen, less than 1, you can display the contents of other pages on the current page at the same time.

/ 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

Implement _ buildItem

Then implement the _ buildItem method, which returns the rendered content of each page in the PageView.builder. The first parameter, activeIndex, is the index of the page currently displayed on the screen, and the second parameter, index, is each item's own index.

Use a Center widget to center the content, and then use an AnimatedContainer to add animation of the height change when switching pages, using the setState method to change the _ pageIndex when switching pages, and Flutter to redraw each item. The key point is to determine whether the current page is the one being displayed, and if so, its height is 500 or 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: preferences [index] .color, borderRadius: BorderRadius.all (Radius.circular (12.0)),), child: Stack (),),);}

Add content

Then add the contents of each item to AnimatedContainer

Child: Stack (fit: StackFit.expand, children: [ClipRRect (borderRadius: BorderRadius.all (Radius.circular),), child: Image.network (questions [index] .image, fit: BoxFit.cover,), Align (alignment: Alignment.bottomCenter, child: Row (children: [Expanded (child: Container (padding: EdgeInsets.all), decoration: BoxDecoration (color: Colors.black26, borderRadius: BorderRadius.only (bottomRight: Radius.circular, bottomLeft: Radius.circular) ), child: Text (topics [index] .title, textAlign: TextAlign.center, style: TextStyle (fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white,)],),],))

Realization indicator

Then implement the page indicator and create a PageIndicator widget that needs to pass in pageCount to represent the total number of pages and currentIndex to represent the number of pages currently displayed. Put all the indicators in a Row part to determine whether the index of the current indicator is the index of the page being displayed, and if so, display a darker color.

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 _ buildIndicators () {List 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 {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: [ClipRRect (borderRadius: Radius.circular (12.0),) Child: Image.network (items [index] .image, fit: BoxFit.cover,), Align (alignment: Alignment.bottomCenter, child: Row (children: [Expanded (child: Container (padding: EdgeInsets.all), decoration: BoxDecoration (color: Colors.black26, borderRadius: BorderRadius.only (bottomRight: Radius.circular, bottomLeft: Radius.circular), 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: [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),],);}}

After that, only one Carousel is instantiated in the IndexPage widget, and since the IndexPage does not have to manage the state of the widget, it can be turned into a StatelessWidget.

Complete code

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://cache.yisu.com/upload/information/20201211/272/44767.jpg", title: 'ice shooter-Ash',), Hero (color: Color (0xFF7D6588), image:" https://cache.yisu.com/upload/information/20201211/272/44768.jpg", title: 'blade dancer-Arielia',), Hero (color: Color (0xFF4C314D) Image: "https://cache.yisu.com/upload/information/20201211/272/44769.jpg", title: 'Nine demon foxes-Ali',),] 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 {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: [ClipRRect (borderRadius: Radius.circular (12.0),) Child: Image.network (items [index] .image, fit: BoxFit.cover,), Align (alignment: Alignment.bottomCenter, child: Row (children: [Expanded (child: Container (padding: EdgeInsets.all), decoration: BoxDecoration (color: Colors.black26, borderRadius: BorderRadius.only (bottomRight: Radius.circular, bottomLeft: Radius.circular), 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: [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 (this.currentIndex, this.pageCount); Widget _ indicator (bool isActive) {return Container (width: 6. 0, height: 6. 0, margin: EdgeInsets.symmetric (horizontal: 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 _ buildIndicators () {List indicators = []; for (int I = 0; I < pageCount; ionization +) {indicators.add (I = currentIndex? _ indicator (true): _ indicator (false));} return indicators } @ override Widget build (BuildContext context) {return Row (mainAxisAlignment: MainAxisAlignment.center, children: _ buildIndicators (),);}} class IndexPage extends StatelessWidget {@ override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (elevation: 0.0, backgroundColor: Colors.white,), body: Carousel (height: 540, items: heroes,), backgroundColor: Colors.white,);}}

Thank you for reading! This is the end of this article on "how to use Flutter to achieve a walking lantern layout". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it out for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report