LCOV - code coverage report
Current view: top level - components/widget_detail_inspector - search_bar.dart (source / functions) Hit Total Coverage
Test: new_lcov.info Lines: 62 100 62.0 %
Date: 2021-11-22 14:23:42 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/material.dart';
       2             : import 'package:flutter/services.dart';
       3             : import 'icon.dart' as icon;
       4             : import 'dart:convert';
       5             : 
       6             : typedef void OnSubmitHandle(String text);
       7             : typedef void OnChangeHandle(String text);
       8             : typedef void OnFocusChangeHandle(bool focus);
       9             : 
      10           3 : enum BarStyle {
      11             :   solid,
      12             :   border,
      13             : }
      14             : 
      15             : class SearchBar extends StatefulWidget {
      16             :   final String placeHolder;
      17             :   final bool autofocus;
      18             :   final bool enabled;
      19             :   final String? cancelText;
      20             :   final Color? cursorColor;
      21             :   final Color? searchIconColor;
      22             :   final Brightness keyboardAppearance;
      23             :   final BarStyle style;
      24             :   final Widget? right;
      25             :   final int inputCharactersLength;
      26             :   final Function? rightAction;
      27             :   final OnChangeHandle? onChangeHandle;
      28             :   final OnSubmitHandle? onSubmitHandle;
      29             :   final OnFocusChangeHandle? onFocusChangeHandle;
      30             : 
      31           1 :   SearchBar({
      32             :     Key? key,
      33             :     this.placeHolder = '请输入要搜索的内容',
      34             :     this.autofocus = false,
      35             :     this.enabled = true,
      36             :     this.cancelText,
      37             :     this.cursorColor,
      38             :     this.right,
      39             :     this.style = BarStyle.solid,
      40             :     this.keyboardAppearance = Brightness.light,
      41             :     this.rightAction,
      42             :     this.searchIconColor,
      43             :     this.onChangeHandle,
      44             :     this.onSubmitHandle,
      45             :     this.onFocusChangeHandle,
      46             :     this.inputCharactersLength = 100,
      47           1 :   }) : super(key: key);
      48             : 
      49           1 :   @override
      50           1 :   _SearchInputState createState() => _SearchInputState();
      51             : }
      52             : 
      53             : class _SearchInputState extends State<SearchBar> {
      54             :   bool _showClearIcon = false;
      55             :   TextEditingController _inputController = TextEditingController();
      56             :   FocusNode _focusNode = FocusNode();
      57             : 
      58           1 :   @override
      59             :   void initState() {
      60           1 :     super.initState();
      61           2 :     _focusNode.addListener(() {
      62           0 :       if (widget.onFocusChangeHandle != null) {
      63           0 :         widget.onFocusChangeHandle!(_focusNode.hasFocus);
      64             :       }
      65             :     });
      66             :   }
      67             : 
      68           1 :   @override
      69             :   void dispose() {
      70           2 :     _inputController.dispose();
      71           1 :     super.dispose();
      72             :   }
      73             : 
      74           0 :   void _focus() {
      75           0 :     _unfocus();
      76           0 :     FocusScope.of(context).requestFocus(_focusNode);
      77             :   }
      78             : 
      79           0 :   void _unfocus() {
      80           0 :     FocusScope.of(context).requestFocus(FocusNode());
      81             :   }
      82             : 
      83           0 :   void _inputSubmitHandle(String query) {
      84           0 :     _unfocus();
      85           0 :     if (widget.onSubmitHandle is OnSubmitHandle) {
      86           0 :       widget.onSubmitHandle!(query);
      87             :     }
      88             :   }
      89             : 
      90           0 :   void _inputChangeHandle(String query) {
      91           0 :     bool curClearIconStatus = query.isNotEmpty;
      92           0 :     if (curClearIconStatus != _showClearIcon) {
      93           0 :       setState(() {
      94           0 :         _showClearIcon = curClearIconStatus;
      95             :       });
      96             :     }
      97           0 :     if (widget.onChangeHandle != null) {
      98           0 :       widget.onChangeHandle!(query);
      99             :     }
     100             :   }
     101             : 
     102           1 :   Widget _buildSearcIcon() {
     103           1 :     return Container(
     104             :         margin: const EdgeInsets.only(right: 11.0),
     105           1 :         child: Image.memory(
     106           1 :           base64.decode(icon.searchIconData),
     107             :           width: 16,
     108             :           height: 16,
     109             :         ));
     110             :   }
     111             : 
     112           1 :   Widget _buildClearIcon() {
     113           1 :     if (!_showClearIcon) {
     114           1 :       return Container(width: 0, height: 0);
     115             :     }
     116           0 :     return GestureDetector(
     117           0 :       onTap: () {
     118           0 :         WidgetsBinding.instance!.addPostFrameCallback((_) {
     119           0 :           _inputController.clear();
     120           0 :           _focus();
     121             :         });
     122           0 :         _inputChangeHandle('');
     123             :       },
     124           0 :       child: Container(
     125           0 :           margin: EdgeInsets.only(left: 16.0),
     126           0 :           child: Image.memory(base64.decode(icon.searchClearIconData),
     127             :               width: 16, height: 16)),
     128             :     );
     129             :   }
     130             : 
     131           1 :   Widget _buildTextField() {
     132           1 :     List<TextInputFormatter> formatters = [];
     133           3 :     if (widget.inputCharactersLength > 0) {
     134           1 :       formatters = [
     135           3 :         LengthLimitingTextInputFormatter(widget.inputCharactersLength)
     136             :       ];
     137             :     }
     138             : 
     139           1 :     return Theme(
     140           3 :       data: Theme.of(context).copyWith(splashColor: Colors.transparent),
     141           1 :       child: TextField(
     142           2 :         enabled: widget.enabled,
     143             :         textAlignVertical: TextAlignVertical.center,
     144           2 :         keyboardAppearance: widget.keyboardAppearance,
     145           1 :         focusNode: _focusNode,
     146           1 :         controller: _inputController,
     147           1 :         onChanged: _inputChangeHandle,
     148           2 :         autofocus: widget.autofocus,
     149             :         maxLines: 1,
     150           1 :         onSubmitted: _inputSubmitHandle,
     151             :         // ignore: deprecated_member_use
     152             :         maxLengthEnforced: false,
     153           1 :         style: TextStyle(
     154             :           fontSize: 15.0,
     155             :           color: Colors.black,
     156             :           textBaseline: TextBaseline.alphabetic,
     157             :         ),
     158           2 :         cursorColor: widget.cursorColor ?? Colors.red,
     159           1 :         decoration: InputDecoration(
     160             :             isDense: true,
     161             :             contentPadding: EdgeInsets.zero,
     162             :             border: InputBorder.none,
     163           2 :             hintText: widget.placeHolder,
     164             :             hintMaxLines: 1,
     165           1 :             hintStyle: TextStyle(
     166             :               fontSize: 15.0,
     167           3 :               color: widget.style == BarStyle.border
     168             :                   ? Colors.black38
     169             :                   : Colors.black54,
     170             :               textBaseline: TextBaseline.alphabetic,
     171             :             )),
     172             :         inputFormatters: formatters,
     173             :       ),
     174             :     );
     175             :   }
     176             : 
     177           1 :   Widget _buildInput() {
     178           1 :     return Container(
     179           3 :       decoration: widget.style == BarStyle.border
     180           0 :           ? BoxDecoration(
     181             :               color: Colors.white,
     182             :               borderRadius: const BorderRadius.all(Radius.circular(6.0)),
     183           0 :               border: Border.all(
     184             :                   color: Colors.black12, style: BorderStyle.solid, width: 1))
     185           1 :           : BoxDecoration(
     186           1 :               color: Colors.black.withOpacity(0.04),
     187             :               borderRadius: const BorderRadius.all(Radius.circular(6.0))),
     188             :       padding:
     189             :           const EdgeInsets.only(top: 9.0, left: 12.0, right: 12.0, bottom: 8.0),
     190           1 :       child: Flex(
     191             :         direction: Axis.horizontal,
     192           1 :         children: <Widget>[
     193           1 :           Expanded(
     194             :             flex: 0,
     195           1 :             child: _buildSearcIcon(),
     196             :           ),
     197           2 :           Expanded(flex: 1, child: _buildTextField()),
     198           2 :           Expanded(flex: 0, child: _buildClearIcon())
     199             :         ],
     200             :       ),
     201             :     );
     202             :   }
     203             : 
     204           1 :   Widget _buildClickButton() {
     205             :     Widget right;
     206           2 :     if (widget.right != null) {
     207           0 :       right = Container(
     208             :           constraints: const BoxConstraints(maxHeight: 38),
     209             :           padding: const EdgeInsets.only(left: 20.0, right: 20),
     210           0 :           child: widget.right);
     211             :     } else {
     212           2 :       if (widget.cancelText == null) {
     213           1 :         right = Container(width: 0, height: 0);
     214             :       } else {
     215           0 :         right = Padding(
     216             :             padding: const EdgeInsets.only(left: 20.0, right: 20),
     217           0 :             child: Text(widget.cancelText!,
     218           0 :                 style: TextStyle(
     219             :                     fontSize: 15.0,
     220             :                     fontWeight: FontWeight.bold,
     221             :                     color: Colors.black)));
     222             :       }
     223             :     }
     224           1 :     return GestureDetector(
     225           0 :         onTap: () {
     226           0 :           _inputSubmitHandle(_inputController.text);
     227           0 :           if (widget.rightAction != null) {
     228           0 :             widget.rightAction!();
     229             :           }
     230             :         },
     231             :         child: right);
     232             :   }
     233             : 
     234           1 :   @override
     235             :   Widget build(BuildContext context) {
     236           1 :     return Container(
     237           1 :         child: Flex(
     238             :       direction: Axis.horizontal,
     239           1 :       children: <Widget>[
     240           1 :         Expanded(
     241             :           flex: 1,
     242           1 :           child: _buildInput(),
     243             :         ),
     244           2 :         Expanded(flex: 0, child: _buildClickButton())
     245             :       ],
     246             :     ));
     247             :   }
     248             : }

Generated by: LCOV version 1.15