search_bar.dart 4.27 KB
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:Parlando/res/resources.dart';
import 'package:Parlando/util/theme_utils.dart';
import 'package:Parlando/extension/int_extension.dart';
import 'load_image.dart';
import 'my_button.dart';

/// 搜索页的AppBar
class SearchBar extends StatefulWidget implements PreferredSizeWidget {
  const SearchBar({
    Key? key,
    this.hintText = '',
    this.backImg = 'assets/images/ic_back_black.png',
    this.onPressed,
  }) : super(key: key);

  final String backImg;
  final String hintText;
  final Function(String)? onPressed;

  @override
  _SearchBarState createState() => _SearchBarState();

  @override
  Size get preferredSize => Size.fromHeight(48.px);
}

class _SearchBarState extends State<SearchBar> {
  final TextEditingController _controller = TextEditingController();
  final FocusNode _focus = FocusNode();

  @override
  void dispose() {
    _focus.dispose();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final bool isDark = context.isDark;
    final Color iconColor =
        isDark ? Colours.dark_text_gray : Colours.text_gray_c;

    final Widget back = Semantics(
      label: '返回',
      child: SizedBox(
        width: 48.px,
        height: 48.px,
        child: InkWell(
          onTap: () {
            _focus.unfocus();
            Navigator.maybePop(context);
          },
          borderRadius: BorderRadius.circular(24.px),
          child: Padding(
            key: const Key('search_back'),
            padding: EdgeInsets.all(12.px),
            child: Image.asset(
              widget.backImg,
              color: isDark ? Colours.dark_text : Colours.text,
            ),
          ),
        ),
      ),
    );

    final Widget textField = Expanded(
      child: Container(
        height: 32.px,
        decoration: BoxDecoration(
          color: isDark ? Colours.dark_material_bg : Colours.bg_gray,
          borderRadius: BorderRadius.circular(4.px),
        ),
        child: TextField(
          key: const Key('search_text_field'),
          controller: _controller,
          focusNode: _focus,
          textInputAction: TextInputAction.search,
          onSubmitted: (String val) {
            _focus.unfocus();
            // 点击软键盘的动作按钮时的回调
            widget.onPressed?.call(val);
          },
          decoration: InputDecoration(
            contentPadding:
                EdgeInsets.only(left: -8.px, right: -16.px, bottom: 14.px),
            border: InputBorder.none,
            icon: Padding(
              padding: EdgeInsets.only(top: 8.px, bottom: 8.px, left: 8.px),
              child: LoadAssetImage(
                'poem/poem_search',
                color: iconColor,
              ),
            ),
            hintText: widget.hintText,
            suffixIcon: GestureDetector(
              child: Semantics(
                label: '清空',
                child: Padding(
                  padding:
                      EdgeInsets.only(left: 16.px, top: 8.px, bottom: 8.px),
                  child: LoadAssetImage('poem/poem_delete', color: iconColor),
                ),
              ),
              onTap: () {
                /// https://github.com/flutter/flutter/issues/35848
                SchedulerBinding.instance.addPostFrameCallback((_) {
                  _controller.text = '';
                });
              },
            ),
          ),
        ),
      ),
    );

    final Widget search = MyButton(
      minHeight: 32.px,
      minWidth: 44.px,
      fontSize: Dimens.font_sp14,
      radius: 4.px,
      padding: EdgeInsets.symmetric(horizontal: 8.px),
      text: '搜索',
      onPressed: () {
        _focus.unfocus();
        widget.onPressed?.call(_controller.text);
      },
    );

    return AnnotatedRegion<SystemUiOverlayStyle>(
      value: isDark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
      child: Material(
        color: context.backgroundColor,
        child: SafeArea(
          child: Row(
            children: <Widget>[
              back,
              textField,
              Gaps.hGap8,
              search,
              Gaps.hGap16,
            ],
          ),
        ),
      ),
    );
  }
}