preface

Flutter achieves the top adsorption effect.Copy the code

First, the effect picture:

An overview of the

CustomScrollView is a component provided by Flutter that can be used to customize the scrolling effect. It acts like glue to hold multiple slivers together. The difference between NestedScrollView and ScrollView is that NestedScrollView supports nested sliding. Whether it is a parent control or a child control, nested sliding is supported and enabled by default.Copy the code
body:NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverPersistentHeader( pinned: true, delegate: SliverCustomHeaderDelegate( context: context, coverImgUrl: 'assets/images/sliver_bg.png', collapsedHeight: ScreenUtil().setHeight(90), expandedHeight: ScreenUtil().setHeight(280), title: , popCallBack:callback, paddingTop: 0),)]; },Copy the code

This demo USES SliverPersistentHeader, silver family SliverPersistentHeader is one of the most important attribute SliverPersistentHeaderDelegate, Therefore we need to implement a class inherits from SliverPersistentHeaderDelegate here the need to achieve SliverPersistentHeaderDelegate, SliverAppBar is implemented based on this, just more complex logic.

SliverPersistentHeader attributes: delegate: whether SliverPersistentHeaderDelegate fixed head layout (default false) pinned: whether fixed head layout (default false) floating: Floating head layout (default false)Copy the code

SliverPersistentHeaderDelegate implementation code is as follows: as you can see, the realization of the SliverPersistentHeaderDelegate class must implement the four methods. MinExtent: indicates the height of a component when it is folded up. MaxExtent: the height of the component when expanded. ShouldRebuild: similar to shouldComponentUpdate in React; Build: Builds the rendered content.

import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/screenutil.dart'; class SliverCustomHeaderDelegate extends SliverPersistentHeaderDelegate { final double collapsedHeight; final double expandedHeight; final double paddingTop; final String coverImgUrl; final String title; final Function popCallBack; BuildContext context; SliverCustomHeaderDelegate({ this.context, this.collapsedHeight, this.expandedHeight, this.paddingTop, this.coverImgUrl, this.title, this.popCallBack }); @override double get minExtent => this.collapsedHeight + this.paddingTop + MediaQuery.of(context).padding.top; @override double get maxExtent => this.expandedHeight; @override bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) { return true; } Color makeStickyHeaderBgColor(shrinkOffset) { final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255) .clamp(0, 255) .toInt(); return Color.fromARGB(alpha, 255, 255, 255); } Color makeStickyHeaderTextColor(shrinkOffset, isIcon) { if (shrinkOffset <= 50) { return isIcon ? Colors.white : Colors.transparent; } else { final int alpha = (shrinkOffset / (this.maxExtent - this.minExtent) * 255) .clamp(0, 255) .toInt(); return Color.fromARGB(alpha, 0, 0, 0); }} Color makeStickyHeaderTitleColor (shrinkOffset) {/ / it represents the current head of the scroll offset the if (shrinkOffset > 50) {return Colors, transparent;  } else { return Color(0xFFFF542C); } } @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( height: this.maxExtent, width: MediaQuery.of(context).size.width, child: Stack(fit: StackFit. Expand, children: <Widget>[// // background Image Container(child: image. asset(this.coverImgUrl, fit: Box fit.fill), // retracts the head of toy (left: 0, right: 0, top: 0, child: Container(color: Enclosing makeStickyHeaderBgColor (shrinkOffset), / / background color child: / / SafeArea (/ / bottom: false, / / the child: Container (height: this.collapsedHeight + MediaQuery.of(context).padding.top, padding: EdgeInsets.only(top: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[IconButton(onPressed: () async{await popCallBack();}, padding: const edgeinsets.all (16.0), icon: Image.asset( 'assets/images/ic_back.png', color: this.makeStickyHeaderTextColor(shrinkOffset, true), ), ), Container( width: ScreenUtil().setWidth(400), child: Text( this.title, maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, color: Enclosing makeStickyHeaderTextColor (shrinkOffset, false), / / title color),),), AnimatedOpacity (opacity: 0, duration: Duration(microseconds: 200), child: IconButton(padding: const EdgeInsets. All (16.0), icon: Image.asset( 'assets/images/ic_back.png', color: this .makeStickyHeaderTextColor(shrinkOffset, true), ), ), ), ], ), ), // ), ), ), Positioned( bottom: ScreenUtil().setHeight(40), left: ScreenUtil().setWidth(30), child: Container( width: ScreenUtil().setWidth(500), child: Text( title, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: ScreenUtil().setSp(34), color: this.makeStickyHeaderTitleColor( shrinkOffset), // Color(0xFFFF542C)), ), ), )) ], ), ); }}Copy the code

Welcome to learn and share FLUTTER with me. The project will continue to update new learning demo

Github address of this project: project address

Here is our public account: Flutter Programming Notes (CODE9871)Copy the code

The official accounts share their learning ideas from time to time

Past review:

The Flutter implements a digital scale

Flutter implements simple rotation animations

The Flutter achieves a simple drawer effect