This article is mainly written about the gold nuggets APP boiling point page, the effect is as follows:

To add a Tabbar first

I wrote about Tabbar in a previous article. So you can just use it. portal

Boiling point page header content build

This part of the content is similar to the home page, can be encapsulated into a component, pass the data in, and then apply it. So far it looks like this:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class SearchTop extends StatefulWidget {
  SearchTop({Key key}) : super(key: key);

  @override
  _SearchTopState createState() => _SearchTopState();
}

class _SearchTopState extends State<SearchTop> {
  String currentString = 'recommendations';

  tagButton({title = 'recommendations'{})return FlatButton(
        onPressed: () {
          setState(() {
            currentString = title;
          });
        },
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Padding(
              padding: EdgeInsets.symmetric(vertical: 5),
              child: Text(title,
                  style: currentString == title
                      ? TextStyle(fontSize: 20, color: Colors.blue)
                      : TextStyle(fontSize: 18, color: Colors.grey)), ), Offstage( offstage: currentString ! = title, child: Container( height:2,
                width: title.length.toDouble() * 20,
                decoration: BoxDecoration(color: Colors.blue),
              ),
            )
          ],
        ));
  }

  renderTag() {
    return Container(
      width: Get.width,
      decoration: BoxDecoration(color: Colors.white),
      padding: EdgeInsets.only(
          top: Get.context.mediaQueryPadding.top, left: 10, right: 10),
      child: Row(
        children: [
          Expanded(
              child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              children: [
                'recommendations'.'hot'.'attention'.'front end'.'Fishing at work'.'Push recruitment'.'A hole in the tree'.'Learned today'.'A picture is worth a thousand words'.'Algorithm of the Day',
              ].map<Widget>((e) => tagButton(title: e)).toList(),
            ),
          )),
          InkWell(
            onTap: () {},
            child: Container(
              padding: EdgeInsets.only(left: 10),
              child: Icon(
                Icons.list_alt,
                color: Colors.grey,
                size: 24() [() [() [(). }@override
  Widget build(BuildContext context) {
    returnrenderTag(); }}Copy the code

The second half of the list is built

First analyze a wave of pages, divided into two parts, the top part is a horizontal scroll list, the bottom part is a boiling point content list, image type, text type, link type

Horizontal scrolling list building

Make the first item returned in the list a horizontal scroll view and create a new search_hot.dart file

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class SearchHot extends StatefulWidget {
  SearchHot({Key key}) : super(key: key);

  @override
  _SearchHotState createState() => _SearchHotState();
}

class _SearchHotState extends State<SearchHot> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      width: Get.width - 20,
      margin: EdgeInsets.only(top: 10, left: 10),
      padding: EdgeInsets.symmetric(horizontal: 20),
      decoration: BoxDecoration(
          color: Colors.white, borderRadius: BorderRadius.circular(5)),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Expanded(
              child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '🔥 there's a new tool, check it out check it out check it out ',
                style: TextStyle(fontSize: 18),
                maxLines: 2,
                overflow: TextOverflow.ellipsis,
              ),
              Padding(
                padding: EdgeInsets.only(top: 5),
                child: Text(
                  'Like 89· Reading 123· One Morning',
                  style: TextStyle(fontSize: 14, color: Colors.grey),
                ),
              )
            ],
          )),
          Offstage(
            offstage: false,
            child: Container(
              height: 60,
              width: 60, decoration: BoxDecoration(color: Colors.red), ), ) ], ), ); }}Copy the code

Use it on the page

@override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        SearchTop(),
        Expanded(
            child: CommonListWiget(
          networkApi: (currentPage) async {
            Future.delayed(Duration(milliseconds: 500)).then((value) => {
                  dataList.addAll(['1'.'2'])});return dataList;
          },
          itemBuilder: (BuildContext context, int position) {
            if (position == 0) {
              return SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  children: [
                    SearchHot(),
                    SearchHot(),
                    SearchHot(),
                  ],
                ),
              );
            }
            return ListTile(
              title: Text('test' + position.toString()),
              subtitle: Text('Some description')); })),])); }Copy the code

Bottom list building

Dart file search_item.dart file search_item.dart file search_item.dart

Boiling point information

renderAvatar() {
    return Row(
      children: [
        ClipOval(
          child: Container(
            height: 40,
            width: 40,
            decoration: BoxDecoration(color: Colors.red),
          ),
        ),
        Container(
          margin: EdgeInsets.symmetric(horizontal: 10),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'the tree hole robot',
                style: TextStyle(fontSize: 16, color: Colors.black),
              ),
              Text(
                'Automatic Anonymous robot @ # Tree hole #·31 minutes ago',
                style: TextStyle(fontSize: 14, color: Colors.grey),
              ),
            ],
          ),
        )
      ],
    );
  }
  
  @override
  Widget build(BuildContext context) {
    return Container(
      width: Get.width,
      decoration: BoxDecoration(color: Colors.white),
      padding: EdgeInsets.all(15),
      margin: EdgeInsets.only(top: 10),
      child: Column(
        children: [
          renderAvatar(),
        ],
      ),
    );
  }
Copy the code

The next step is to distinguish between displaying text and images based on type

Display of different states

Display text, which contains functions, after the number of lines is more than 3, display the expand button, click to expand.

//TQExpandableText is a packaged tool widget
renderType() {
    if (widget.type == 1) {
      // Display text
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
        child: TQExpandableText(
          'there is a new tool, hurriedly see seem to see have a new tool, hurriedly to see seems to see how the new tool, hurriedly to see seems to see how the new tool, hurriedly to see seems to see how the new tool, hurriedly to see seems to see how the new tools, hurriedly to see seems to see how the new tools, hurriedly to see seems to see how the new tools, hurriedly run seems to see',
          expandText: 'full',
          collapseText: 'put',
          maxLines: 3,
          style: TextStyle(fontSize: 14, color: Colors.black.withOpacity(0.8)))); }else if (widget.type == 2) {
      // Display text plus images
    } else if (widget.type == 3) {
      // Display text plus images
    }
    return Container();
  }
Copy the code

Show the picture, click on the picture to enlarge the effect, mainly using Hero animation to complete

Main code (PS: the picture is in the digging gold boiling point to find a network picture 😄)

// Display text plus images
      return Hero(
          tag: 'imgaesView',
          child: Material(
            child: InkWell(
                onTap: () {
                  Navigator.push(
                      context,
                      new PageRouteBuilder(
                        transitionDuration: const Duration(milliseconds: 250),
                        pageBuilder: (context, _, __) => Scaffold(
                          body: InkWell(
                            onTap: () {
                              Navigator.of(context).pop();
                            },
                            child: Hero(
                                tag: 'imgaesView',
                                child: Container(
                                  width: Get.width,
                                  height: Get.height,
                                  child: Image.network(
                                      'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39c71164cc4a455b83ac6f579e2a39c1~tplv-k3u1fbpfcp-watermark.image'),
                                )),
                          ),
                        ),
                        transitionsBuilder: (_, Animation<double> animation, __,
                                Widget child) =>
                            new SlideTransition(
                                position: new Tween<Offset>(
                                  begin: Offset(0.0.1.0),
                                  end: Offset(0.0.0.0),
                                ).animate(animation),
                                child: child),
                      ));
                },
                child: Container(
                  margin: EdgeInsets.only(top: 10, left: 10),
                  width: 200,
                  height: 140,
                  child: Image.network(
                      'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39c71164cc4a455b83ac6f579e2a39c1~tplv-k3u1fbpfcp-watermark.image')))));Copy the code

Final linkage effect

The bottom list slides, and the label slides with it.Modify the search_page.dart file and you’re done. The search_hot.dart slide is the same as the home slide I wrote earlier, so I won’t post the code. Same way

@override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        SearchTop(
          dataList: tag,
          currentIndex: currentIndex,
          onTag: (value) {
            setState(() {
              currentIndex = value;
            });
            int index = tag.indexWhere((element) => element == value);
            controller.animateToPage(index,
                duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
          },
        ),
        Expanded(
            child: PageView.builder(
          controller: controller,
          itemBuilder: (context, index) {
            return CommonListWiget(
              networkApi: (currentPage) async {
                Future.delayed(Duration(milliseconds: 500)).then((value) => {
                      dataList.addAll(['1'.'2'])});return dataList;
              },
              itemBuilder: (BuildContext context, int position) {
                if (position == 0) {
                  return SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    child: Row(
                      children: [
                        SearchHot(),
                        SearchHot(),
                        SearchHot(),
                      ],
                    ),
                  );
                }
                returnSearchItem(type: position); }); }, scrollDirection: Axis.horizontal, onPageChanged: (index) {print(tag[index]);
            setState(() {
              currentIndex = tag[index];
            });
            print(currentIndex);
          },
          itemCount: tag.length,
        )),
      ],
    ));
  }
Copy the code