.

— Hold sword tianya, start from your bit by bit accumulation, and wherever you reach, you will strive for perfection. Beautiful application experience comes from the processing of details, but also from the self-requirements and efforts of code farmers


Flutter is Google’s latest mobile development framework.

[X1] Daily reminder of wechat public account at any time, daily accumulation, free to follow the bottom of the article scan code attention

【 X2 】 Various series of free open source video tutorials focus on you won’t get lost

【 X3 】 series article millions of Demo copy and paste use at any time

[x4] Five minute video takes you through the build quickly

【 X5 】 a glance at the source


As you can see in the picture below, your APP project will definitely use this scenario.


To xiaobian character, to achieve millions of Demo copy and paste at any time is certainly the need for source code

The full source code is here

A separate DART file is used as the startup entry to facilitate Demo implementation. The definition is as follows:

// Start the function
void main(a) {
  runApp(RootApp());
}

/ / root directory
class RootApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(primaryColor: Colors.grey[200]),
      // The page is started by defaulthome: HomePage(), ); }}Copy the code

Create a TabController to control TabBar/TabBarView interworking:


class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState(a) {
    return_ScrollHomePageState(); }}class _ScrollHomePageState extends State with SingleTickerProviderStateMixin {

  // In this case, the TAB page is using the TabView, so we need to create a controller
  TabController tabController;

  // page initialization method
  @override
  void initState(a) {
    super.initState();
    / / initialization
    tabController = new TabController(length: 3, vsync: this);
  }

  // Page destruction callback lifecycle
  @override
  void dispose(a) { tabController.dispose(); }... }Copy the code

Scaffold is used for the body of the page:

@override
 Widget build(BuildContext context) {
   // Build the body of the page
   return Scaffold(
     // Drop refresh
     body: RefreshIndicator(
       // Scrollable components send ScrollNotification notifications when they scroll
       notificationPredicate: (ScrollNotification notifation) {
         // This property contains information such as the current ViewPort and scroll position
         ScrollMetrics scrollMetrics = notifation.metrics;
         if (scrollMetrics.minScrollExtent == 0) {
           return true;
         } else {
           return false; }},// Drop down the refresh callback method
       onRefresh: () async {
         // Simulate network refresh wait 2 seconds
         await Future.delayed(Duration(milliseconds: 2000));
         // Returns the value to end the refresh
         return Future.value(true);
       },
       child: buildNestedScrollView(),
     ),
   );
 }
Copy the code

RefreshIndicator is a pull-down refresh component that triggers the pull-down refresh effect and is used directly by nested NestedScrollView sliding layout

// The basic use of NestedScrollView
 Widget buildNestedScrollView(a) {
   // Slide the view
   return NestedScrollView(
     // Configure a foldable header layout
     headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
       return [buildSliverAppBar()];
     },
     // The body of the page
     body: buidChildWidget(),
   );
 }
Copy the code

NestedScrollView contains two parts, one is the folded header, which is implemented using SliverAppBar, and the other is the sliding body of the page, which is implemented using TabBarView

BottomNavigationBar (BottomNavigationBar) BottomNavigationBar (BottomNavigationBar
 // You will notice that when you switch to another page, the previous page is destroyed, and when you return to the previous page, the page is rebuilt.
 // Then the data will be reloaded and the controls will be re-rendered, resulting in a very bad user experience.
 // Because TabBarView uses PageView internally, the solution is the same
 // The body of the page
 Widget buidChildWidget(a) {
   return TabBarView(
     controller: tabController,
     children: <Widget>[
       ItemPage1(1),
       ItemPage1(2),
       ItemPage1(3),]); }Copy the code

The implementation of SliverAppBar is as follows:

  //flexibleSpace collapsible content area
  buildSliverAppBar() {
    return SliverAppBar(
      title: buildHeader(),
      // The title is centered
      centerTitle: true.// SliverAppBar is fixed at the top of the page when this value is true
      // When this value is fase the SliverAppBar slides up as it slides
      pinned: true.// When true, the title of the SliverAppBar is hidden by sliding up
      // The bottom of the configuration is then displayed where the original AppBar was
      // If the value is false, the title of SliverAppBar will not be hidden
      // The configured bottom is then displayed under the title of the original AppBar setting
      floating: false.// When snap is set to true, slide down the page and SliverAppBar (with flexibleSpace content configured in it) will be displayed immediately.
      // Conversely, when snap is set to false, SliverAppBar is pulled down only when the ListView's data slides to the top.
      snap: false,
      elevation: 0.0.// Height of expansion
      expandedHeight: 380.// The content area under AppBar
      flexibleSpace: FlexibleSpaceBar(
        / / the background
        // Is configured as a widget, meaning that any widget can be used here
        // The Widget combination uses an image directly here
        background: buildFlexibleSpaceWidget(),
      ),
      bottom: buildFlexibleTooBarWidget(),
    );
  }
Copy the code

There are three parts in the SliverAppBar. The first part is the title part, which is configured with the title property. The code is as follows:

 // Build the title title of SliverAppBar
 buildHeader() {
   // Transparent components
   return Container(
     width: double.infinity,
     padding: EdgeInsets.only(left: 10),
     height: 38,
     decoration: BoxDecoration(
       color: Colors.white,
       border: Border.all(color: Colors.white),
       borderRadius: BorderRadius.circular(30),
     ),
     child: Row(
       mainAxisAlignment: MainAxisAlignment.center,
       children: [
         Icon(
           Icons.search_rounded,
           size: 18,
         ),
         SizedBox(
           width: 4,
         ),
         Text(
           "Search",
           style: TextStyle(
             fontSize: 14,),),),),); }Copy the code

The second part is the multicast diagram used to fold parts, which is configured in FlexibleSpaceBar configured with flexibleSpace property. The code is as follows:

buildFlexibleSpaceWidget() {
   return Column(
     children: [
       Container(
         height: 240,
         child: BannerHomepage(isTitle: false,),
       ),
       Container(
         child: Row(
           children: [
             Expanded(
               child: Container(
                 height: 120,
                 color: Colors.blueGrey,
                 child: Image.asset("images/banner5.jpeg"),
               ),
             ),
             Expanded(
               child: Container(
                 color: Colors.brown,
                 height: 120,
                 child: Image.asset("images/banner6.jpeg"(() [() [() [() [() [() }Copy the code

The third part of BannerHomepage is the TabBar TAB configured in bottom, which is used in conjunction with PreferredSize. The code is as follows:

 // The bottom property of [SliverAppBar] is configured
 Widget buildFlexibleTooBarWidget(a) {
   //[PreferredSize] is used to configure in the AppBar or SliverAppBar
   // Implement the PreferredSizeWidget in the bottom
   return PreferredSize(
     // Define the size
     preferredSize: Size(MediaQuery.of(context).size.width, 44),
     // Configure any child widgets
     child: Container(
       alignment: Alignment.center,
       child: Container(
         color: Colors.grey[200].// The width of the TabBar gradually increases as you slide up
         // The parent Container constraint is center alignment
         // The middle X-axis is magnified
         width: MediaQuery.of(context).size.width,
         child: TabBar(
           controller: tabController,
           tabs: <Widget>[
             new Tab(
               text: "Tag 1",),new Tab(
               text: "Tag 2",),new Tab(
               text: "Tag 3",),),),),); }Copy the code

To xiaobian character, to achieve millions of Demo copy and paste at any time is certainly the need for source code

The full source code is here

Of course, with the character of xiaobian, there must be a video recording, click here to view, interested you can pay attention to the video of watermelon – young people who get up early