рд╕реНрдкрдВрджрди: AppBar рдФрд░ SliverAppBar рдКрдкрд░ рдкрдВрдк

рд╕реНрдкрдВрджрди рдЯреВрд▓рдмрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЬреНрдЮрд╛рдд AppBar рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рд╣рдореЗрдВ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдЯреВрд▓рдмрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╕реНрд╡рд╛рдЗрдк рдХрд░рддреЗ рд╕рдордп рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЙрддреНрдХреГрд╖реНрдЯ SliverAppBar рд╡рд┐рдЬреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред


рджреЛрдиреЛрдВ рд╡рд┐рдЧреЗрдЯреНрд╕ рдЖрдкрдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдереЛрдбрд╝рд╛ рдФрд░ рд╕реБрдВрджрд░ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЬреЛ рд╕реНрдкрдВрджрди рдореЗрдВ, рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдВрджреЗрд╣ рдХреЗ, рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред


рдореИрдВрдиреЗ StackOverflow рдкрд░ рдФрд░ Facebook рд╕рдореВрд╣реЛрдВ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдкреНрд░рд╢реНрди рджреЗрдЦреЗ рдХрд┐ рдЖрдк рд╡реНрдпрд╡рд╣рд╛рд░ рдпрд╛ рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ AppBar рдФрд░ SliverAppBar рдХреЛ рдХреИрд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред


рдЖрдЗрдП рджреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рджреЗрдЦреЗрдВред


рдЯрд╛рд╕реНрдХ 1


рд╣рдо рдПрдХ рдРрд╕рд╛ AppBar рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдХреНрд░реАрди рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЦрд░рд╛рдм рди рд╣реЛ, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЖрдо рддреМрд░ рдкрд░ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдПрдХ рджрд░рд╛рдЬ (рд╕рд╛рдЗрдб рдореЗрдиреВ) рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдЙрджреНрдШрд╛рдЯрди рдкрд░ AppBar рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрдЧрд╛ред рд╡рд╣ рдпрд╣ рд╣реИ: рд╣рдорд╛рд░реЗ рдЕрдкрдиреЗ AppBar   рд╣рдореЗрдВ рдЬрд┐рди рдЖрдпрд╛рдореЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ, AppBar рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЖрдХрд╛рд░ рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕реЗ рдмрджрд▓ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рдмрд╛рдж , рд╣рдо рд╕реНрдХреИрдлреЛрд▓реНрдб рдореЗрдВ рдРрдкрдмрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рджреЗрдЦрддреЗ рд╣реИрдВ, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ PreferredSizeWidget рдЬреИрд╕реЗ рд╡рд┐рдЬреЗрдЯ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдЕрдм рд╣рдо AppBar рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ рдФрд░ рдкрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ Statefulbidget рд╣реИ рдЬреЛ PreferredSizeWidget рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред



рдмрд┐рдВрджреБ рдЫреЛрдЯрд╛ рд╣реИ: рдмрд╕ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рд╡рд┐рдЬреЗрдЯ рдмрдирд╛рдПрдВ рдЬреЛ PreferredSizeWidget рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред


рдпрд╣реА рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ



рдЖрдк рдРрд╕рд╛ рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЬрдм рдЖрдк рд╣рдорд╛рд░реЗ AppBar рдХреЗ рдореЗрдиреВ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ , рддреЛ рдПрдХ рд╕рд╛рдЗрдб рдореЗрдиреВ рдЦреБрд▓рддрд╛ рд╣реИред


рд╣рдо рдЗрд╕реЗ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


`AppBar` рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдпрд╣ рдХреИрд╕реЗ AppBar рдкрд╛рдбрд╝ рдХреЗ рдЕрдВрджрд░ рд╕рд╛рдЗрдбрдмрд╛рд░ рдХреЗ рдЙрджреНрдШрд╛рдЯрди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред


class Sample1 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( drawer: Drawer(), appBar: MyCustomAppBar( height: 150, ), body: Center( child: FlutterLogo( size: MediaQuery.of(context).size.width / 2, ), ), ), ); } } class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget { final double height; const MyCustomAppBar({ Key key, @required this.height, }) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ Container( color: Colors.grey[300], child: Padding( padding: EdgeInsets.all(30), child: AppBar( title: Container( color: Colors.white, child: TextField( decoration: InputDecoration( hintText: "Search", contentPadding: EdgeInsets.all(10), ), ), ), actions: [ IconButton( icon: Icon(Icons.verified_user), onPressed: () => null, ), ], ) , ), ), ], ); } @override Size get preferredSize => Size.fromHeight(height); } 

рдПрдХ рдХрд╕реНрдЯрдо рд╡рд┐рдЬреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдпрд╣рд╛рдБ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛рдкрди рд╣реИ рдФрд░ рдЖрдк рд╕реНрдХреИрдлреЛрд▓реНрдб рд╕реЗ GlobalKey рдЬреИрд╕реЗ ScaffoldState рдпрд╛ InheritedWidget рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд░рд╛рдЬ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп рдХреЗ рддрд░реАрдХреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 import 'package:flutter/material.dart'; class Sample1 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( drawer: Drawer(), appBar: MyCustomAppBar( height: 150, ), body: Center( child: FlutterLogo( size: MediaQuery.of(context).size.width / 2, ), ), ), ); } } class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget { final double height; const MyCustomAppBar({ Key key, @required this.height, }) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ Container( color: Colors.grey[300], child: Padding( padding: EdgeInsets.all(30), child: Container( color: Colors.red, padding: EdgeInsets.all(5), child: Row(children: [ IconButton( icon: Icon(Icons.menu), onPressed: () { Scaffold.of(context).openDrawer(); }, ), Expanded( child: Container( color: Colors.white, child: TextField( decoration: InputDecoration( hintText: "Search", contentPadding: EdgeInsets.all(10), ), ), ), ), IconButton( icon: Icon(Icons.verified_user), onPressed: () => null, ), ]), ), ), ), ], ); } @override Size get preferredSize => Size.fromHeight(height); } 

рдкрд░рд┐рдгрд╛рдо



рд╕рд░рд▓, рд╕рд╣реА? рдЖрдЗрдП SliverAppBar рдХреЗ рджреВрд╕рд░реЗ рдХрд╛рд░реНрдп рдХреЛ рджреЗрдЦреЗрдВ ред


рдЯрд╛рд╕реНрдХ реи


рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ, SliverAppBar рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:



рд╣рдо рдЬреЛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡рд╣ рд╣рдорд╛рд░реЗ SliverAppBar рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдХрд╛рд░реНрдб рдХреЛ рдбрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрдХреГрддрд┐ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред



рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди SliverAppBar рдХреЗ рдЕрдВрджрд░ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреНрд░реЙрдк рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрдЧреЗ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ рдХрд┐ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ?



рдШрдмрд░рд╛рд╣рдЯ рдХреЗ рдмрд┐рдирд╛, рдЪрд▓реЛ SliverAppBar рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ рдФрд░, рдЖрд╢реНрдЪрд░реНрдп рдХреА рдмрд╛рдд рд╣реИ, рдпрд╣ рд╕реНрдЯреЗрдЯрдлреБрд▓рд╡реЗрдЯ рд╣реИ, рдЬреЛ SliverPersistentHeader рдХреЗ рдЕрдВрджрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдпрд╣ рд╕рдВрдкреВрд░реНрдг рд░рд╣рд╕реНрдп рд╣реИред


рд╣рдо SliverPersistentHeader рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ SliverPersistentHeaderDelegate рдмрдирд╛рдПрдВрдЧреЗ ред


 class Sample2 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Material( child: CustomScrollView( slivers: [ SliverPersistentHeader( delegate: MySliverAppBar(expandedHeight: 200), pinned: true, ), SliverList( delegate: SliverChildBuilderDelegate( (_, index) => ListTile( title: Text("Index: $index"), ), ), ) ], ), ), ); } } class MySliverAppBar extends SliverPersistentHeaderDelegate { final double expandedHeight; MySliverAppBar({@required this.expandedHeight}); @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Stack( fit: StackFit.expand, overflow: Overflow.visible, children: [ Image.network( "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", fit: BoxFit.cover, ), Center( child: Opacity( opacity: shrinkOffset / expandedHeight, child: Text( "MySliverAppBar", style: TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 23, ), ), ), ), Positioned( top: expandedHeight / 2 - shrinkOffset, left: MediaQuery.of(context).size.width / 4, child: Opacity( opacity: (1 - shrinkOffset / expandedHeight), child: Card( elevation: 10, child: SizedBox( height: expandedHeight, width: MediaQuery.of(context).size.width / 2, child: FlutterLogo(), ), ), ), ), ], ); } @override double get maxExtent => expandedHeight; @override double get minExtent => kToolbarHeight; @override bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true; } 

рдкрд░рд┐рдгрд╛рдо



рд╣реЛ рдЧрдпрд╛, рджреЛрдиреЛрдВ рдХрд╛рд░реНрдп рд╣рд▓ рд╣реЛ рдЧрдПред


рдЙрджрд╛рд╣рд░рдг рдЗрд╕ рднрдВрдбрд╛рд░ рдореЗрдВ рд╣реИрдВ ред


рдирд┐рд╖реНрдХрд░реНрд╖


рдЕрдХреНрд╕рд░ рд╣рдореЗрдВ рдирд┐рд░рд╛рд╢рд╛ рд╣реЛрддреА рд╣реИ рдЬрдм рд╣рдореЗрдВ рд╡рд┐рдЬреЗрдЯ рдХреЗ рдХреЛрдИ рдЧреБрдг рдирд╣реАрдВ рдорд┐рд▓рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдлрд╝реНрд▓рдЯрд░ рдореЗрдВ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╡рд┐рдЬреЗрдЯ рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

Source: https://habr.com/ru/post/hi456054/


All Articles