Let’s first look at the effect of implementing this implementation. I wanted to get lazy and use the flutter pub directly, but I found that all of them were very different from the current UI, so I decided to implement one myself. Overall words are relatively simple, originally is also to practice and do.

In order to facilitate the handling of statusbar height adaptation, so directly rely on Appbar implementation, so that you do not have to deal with the statusbar adaptation.

class _HotWidgetState extends State<HotWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        titleSpacing: 0.// Clear the left and right padding of title. By default, there is a certain padding distance
        toolbarHeight: 44.// Set the height to 44, the height of the design. To make it easier to fit,
        // The plugin flutter_screenutil is recommended for screen adaptation
        backgroundColor: Colors.white,
        elevation: 0.// Since the title itself accepts a widget, it can be given a custom widget directly.
        title: SearchAppBar(
          hintLabel: "Movie/TV show/Actor", ), ), body: Container(), ); }}Copy the code

The control definition of Flutter recommends the use of composite controls. This is really cool because everything is a widget and can be easily combined.

import 'package:flutter/material.dart';
import 'package:flutter_demo_001/ui.theme/color.dart';
import 'package:flutter_demo_001/ui.theme/theme.dart';
import 'package:flutter_demo_001/utils/padding.dart';

class SearchAppBar extends StatefulWidget {
  SearchAppBar({Key? key, required this.hintLabel}) : super(key: key);

  final String hintLabel;

  @override
  State<StatefulWidget> createState() {
    returnSearchAppBarState(); }}class SearchAppBarState extends State<SearchAppBar> {
  late FocusNode _focusNode;

  ///Controls are not displayed by default

  bool _offstage = true;

  ///Listen for TextField content changes
  final TextEditingController _textEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _focusNode = FocusNode();
    _textEditingController.addListener(() {
      var isVisible = _textEditingController.text.isNotEmpty;
      _updateDelIconVisible(isVisible);
    });
  }

  _updateDelIconVisible(boolisVisible) { setState(() { _offstage = ! isVisible; }); }@override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 30,
      child: Row(
        children: [
          Expanded(
            flex: 1,
            child: Container(
              height: double.infinity,
              margin: const EdgeInsets.only(left: 16),
              decoration: BoxDecoration(
                  color: colorF5F6FA, borderRadius: BorderRadius.circular(4)),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  paddingOnly(const EdgeInsets.only(left: 8)),
                  Image.asset(
                    "images/home_search.png",
                    width: 16,
                    height: 16,
                  ),
                  paddingOnly(const EdgeInsets.only(left: 8)),
                  Expanded(
                    flex: 1,
                    child: TextField(
                      controller: _textEditingController,
                      autofocus: true,
                      focusNode: _focusNode,
                      style: TextStyle(fontSize: 14, color: color333),
                      decoration: boxInputDecoration(widget.hintLabel),
                      maxLines: 1,
                    ),
                  ),
                  paddingOnly(const EdgeInsets.only(right: 8)),
                  Offstage(
                    offstage: _offstage,
                    child: GestureDetector(
                      onTap: () => {_textEditingController.clear()},
                      child: Image.asset(
                        "images/home_search_cancel.png",
                        width: 16,
                        height: 16,
                      ),
                    ),
                  ),
                  paddingOnly(const EdgeInsets.only(right: 8)),
                ],
              ),
            ),
          ),
          GestureDetector(
            onTap: () {
              _focusNode.unfocus();
            },
            child: Container(
              padding: const EdgeInsets.only(left: 16, right: 16),
              child: Text("Cancel",
                  style: TextStyle(fontSize: 16, color: Color(0xFF3D7DFF(() (() [(() [() [() }@override
  void dispose() {
    super.dispose(); _focusNode.unfocus(); }}Copy the code

Finally, for aesthetic reasons, make the status bar transparent as well.

void main() {
  // Set the screen rotation direction
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) {
    runApp(const MyApp());
  });
  // Make the status bar transparent
  if (Platform.isAndroid) {
    SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent, // Set it to transparent); SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); }}Copy the code