Using fluent to implement a walking lantern layout example code

The riding light is a common effect. This article talks about how to use pageview to realize a riding light in fluent. The effect is as follows. The height of the current page is higher than that of other pages. There is an animation of height change when switching pages. The pageview. Builder component is mainly used to achieve this effect.

development

Create home page

First, create an indexpage part, which is used to put the pageview. Because the UI needs to be updated with the setstate method, it is 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>[],);
 }
}

Then declare one in the component_ The PageIndex variable is used to save the index of the currently displayed page. A pagecontroller is initialized in the initstate life cycle to configure the pageview part.

Create a pageview. Builder in the column of the body, and use a Sized@R_ 352_ 2419 @ part specifies the height of pageview and sets the controller to_ Pagecontroller, in the onpagechanged event, assign the index value of the currently displayed page to_ PageIndex variable.

int _pageIndex = 0;
PageController _pageController;

@override
void initState() {
 super.initState();
 _pageController = PageController(
 initialPage: 0,viewportFraction: 0.8,);
}

body: Column(
 children: <Widget>[
 Sized@R_352_2419@(
 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 points: set the viewportfraction parameter of pagecontroller to be less than 1. This value is used to set the display proportion of each page on the screen. If it is less than 1, the contents of other pages can be displayed 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;

Realize_ buildItem

Then implement_ Builditem method, which returns the rendered content of each page in pageview.builder. The first parameter activeindex is the index of the page currently displayed on the screen, and the second parameter index is the index of each item.

Use a center part to display the content in the center, and then use an animatedcontainer to add the animation effect of the height change during page switching. When switching pages, use the setstate method_ PageIndex and fluent redraw each item. The key point is to judge whether the current page is being displayed. If yes, its height is 500, otherwise it is 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: @R_352_2419@Decoration(
 color: heroes[index].color,borderRadius: BorderRadius.all(Radius.circular(12.0)),child: Stack(),);
}

Add content

Then add the contents of each item to the animatedcontainer

child: Stack(
 fit: StackFit.expand,children: <Widget>[
 ClipRRect(
 borderRadius: BorderRadius.all(
 Radius.circular(12.0),child: Image.network(
 heroes[index].image,fit: @R_352_2419@Fit.cover,Align(
 alignment: Alignment.bottomCenter,child: Row(
 children: <Widget>[
  Expanded(
  child: Container(
  padding: EdgeInsets.all(12.0),decoration: @R_352_2419@Decoration(
  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,)
 ],

Implementation indicator

Then implement the page indicator and create a pageindicator part. You need to pass in pagecount to represent the total number of pages and currentindex to represent the currently displayed page index. Put all indicators in a row part to judge whether the index of the current indicator is the index of the page being displayed. If so, it will 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: @R_352_2419@Decoration(
 color: isActive ? Color(0xff666a84) : Color(0xffb9bcca),shape: @R_352_2419@Shape.circle,@R_352_2419@Shadow: [
  @R_352_2419@Shadow(
  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(),);
 }
}

Add pageindicator to Sized@R_ 352_ 2419 @ below

Package carousel

Finally, optimize the code, encapsulate the part, make it a separate part, create a carousel part, expose the items and height attributes, and configure the data and height respectively.

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: @R_352_2419@Decoration(
  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: @R_352_2419@Decoration(
   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),);
 }
}

After that, only one carousel will be instantiated in the indexpage part. At the same time, because the indexpage does not need to manage the part state, it can be changed 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://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,);
 }
}

At this point, the whole layout is completed!: sunglasses:

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>