fsearch 1.0.0

  • Readme
  • Changelog
  • Example
  • Installing
  • new70

fsearch

Help developers build the most beautiful search bar🍹.

[FSearch] provides developers with a one-stop search bar construction service. Supports borders, corners, gradient background colors and shadows, as well as any number of prefix and suffix action buttons. Provides beautiful Hint animation.

Author:Newton(coorchice.cb@alibaba-inc.com)

English | 简体中文

Like it? Please cast your Star 🥰 !

✨ Features #

  • Support beautiful border effect

  • Provide rich corner configuration

  • Support stunning gradient effects

  • Provides easy to use shadow capabilities

  • Support any number of prefix and suffix action buttons

  • Provide colorful, flexible and powerful Hint effects

  • Controllers that are easier to use for developers

🛠 Guide #

⚙️ Parameter & Interface #

🔩 FSearch Param #

ParamTypeNecessaryDefaultdesc
controllerFSearchControllerfalsenullController. See [FSearchController] for details
widthdoublefalsenullwidth
heightdoublefalsenullheight
enableboolfalsetrueenable
onTapVoidCallbackfalsenullCallback when the input box is clicked
textStringfalsenullInput content
onSearchValueChangedfalsenullCallback when the keyboard search button is clicked
cornerFSearchCornerfalsenullCorner effect. See [FSearchCorner] for details
cornerStyleFSearchCornerStylefalsenullCorner style. The default [FSearchCornerStyle.round]. See [FSearchCornerStyle] for details
strokeColorColorfalsenullBorder color
strokeWidthdoublefalsenullborder width
backgroundColorColorfalsenullbackground color
gradientGradientfalsenullBackground gradient. Will overwrite [backgroundColor]
shadowColorColorfalsenullSet widget shadow color
shadowOffsetOffsetfalsenullSet widget shadow color
shadowBlurdoublefalsenullSet the standard deviation of the widget Gaussian and shadow shape convolution
cursorColorColorfalsenullCursor color
cursorWidthdoublefalsenullCursor width
cursorRadiusdoublefalsenullCursor corner size
prefixesListfalsenullPrefix action widget
suffixesListfalsenullSuffix action widget
paddingEdgeInsetsfalsenullThe distance between the actual input area and the edge of [FSearch]
marginEdgeInsetsfalsenull[FSearch] outer spacing
styleTextStylefalsenullInput text style
hintStyleTextStylefalsenullHint text style
hintsListfalsenullHint. If there is only one Hint, Hint swap animation cannot be enabled.
hintSwitchDurationDurationfalsenullHint exchange interval
hintSwitchAnimDurationDurationfalsenullHint swap animation time
hintSwitchEnableboolfalsenullWhether to enable Hint swap animation
hintSwitchTypeFSearchAnimationTypefalsenullHint exchanges animation types. The default [FSearchAnimationType.Scroll]. See [FSearchAnimationType] for details.
stopHintSwitchOnFocusbooltruenullWhen the focus is obtained, whether to automatically stop the Hint exchange animation.
hintPrefixWidgetfalsenullHint prefix widget
centerboolfalsenullCentered。

💻 FSearchController #

FSearchController is the controller of FSearch, which can return to the input text, Hint, focus status and other information. At the same time provide a variety of monitoring and text update capabilities.

🔩 Param

ParamTypeDesc
textStringInput text
hintStringCurrent Hint text
focusboolFocus state

📲 Interface

  • setListener(VoidCallback listener)

Set input monitor

  • setOnFocusChangedListener(ValueChanged<bool> listener)

Set focus change monitoring

  • requestFocus()

Request focus

  • clearFocus()

Remove focus

🎥 FSearchAnimationType #

FSearchAnimationType Used to specify the FSearch Hint exchange animation type.

enum FSearchAnimationType {
  /// 渐变动画
  ///
  /// Alpha animation
  Fade,

  /// 缩放动画
  ///
  /// Scale animation
  Scale,

  /// 上下滚动动画
  ///
  /// Scroll up and down animation
  Scroll,
}

📺 Demo #

🔩 Base Demo #

FSearch(

  /// 设置高
  ///
  /// Set height
  height: 30.0,
  
  /// 设置背景颜色
  ///
  /// Set background color
  backgroundColor: color,

  /// 设置输入内容样式
  ///
  /// Set input text style
  style: style,

  /// 点击键盘搜索时触发
  ///
  /// Fired when you click on the keyboard to search
  onSearch: (value) {
    /// do something
  },

  prefixes: [buildAction()],
)

Using FSearch to build a search bar is very relaxing.

Through some simple parameters, developers can easily change the size, color, and font of the search bar.

When the user clicks on the keyboard to search for Action, onSearch will be triggered, allowing the developer to perform some search operations here.

🌖 Prefixes & Suffixes #

FSearch(
  height: 30.0,
  backgroundColor: mainBackgroundColor,
  style: style,

  /// 前缀 Widget
  ///
  /// prefix widget
  prefixes: [ buildAction() ],

  /// 后缀 Widget
  ///
  /// suffix widget
  suffixes: [
    buildAction_1(),
    buildAction_2(),
    buildAction_3(),
  ],
  onSearch: _onSearch,
)

In FSearch, developers can configure any number of prefix or suffix action buttons for the search bar through the prefixes and suffixes parameters.

🌈 Gradient #

FSearch(
  height: 30.0,
  backgroundColor: mainBackgroundColor,
  style: style,

  /// 配置渐变色
  ///
  /// Set gradient
  gradient: _gradient,
  prefixes: [ buildAction() ],
)

FSearch can support developers to create a beautiful gradient search bar.

Only need to configure through the gradient parameter.

🍄 Corner & Stroke & Shadow #


/// #1
FSearch(
  height: 30.0,
  backgroundColor: color,
  style: style,

  /// 边角
  ///
  /// Corner
  corner: FSearchCorner(
      leftTopCorner: 15.0,
      leftBottomCorner: 15.0,
      rightBottomCorner: 15.0),

  /// 边框宽
  ///
  /// border width
  strokeWidth: 1.0,

  /// 边框颜色
  ///
  /// border color
  strokeColor: mainTextTitleColor,

  /// 阴影
  ///
  /// shadow
  shadowColor: Colors.black38,
  shadowBlur: 5.0,
  shadowOffset: Offset(2.0, 2.0),
  prefixes: [buildAction()],
)

The Border and Shadow effects of FSearch are the same as those of other FWidget members, and are simple and easy to use.

Through the corner parameter, developers can use FSearchCorner to freely control the table corner size of FSearch.

/// #2
FSearch(
  height: 30.0,
  backgroundColor: color,
  style: style,

  /// 边角
  ///
  /// Corner
  corner: FSearchCorner.all(6.0),

  /// 边角风格
  ///
  /// Corner style
  cornerStyle: FSearchCornerStyle.bevel,
  prefixes: [buildAction()],
)

If combined with cornerStyle, more complex and exquisite effects can be achieved.

📍 Cursor #

FSearch(
  /// 光标配置
  ///
  /// Cursor
  cursorColor: Colors.red[200],
  cursorRadius: 5.0,
  cursorWidth: 5.0,

  height: 36.0,
  style: style,
  gradient: _gradient,
  corner: _corner,
  prefixes: [ buildAction() ],
  suffixes: [ buildAction() ],
)

FSearch supports modifying the cursor in the input box of the search bar. You can change it to whatever you want.

🗂 Hint #

/// #1
FSearch(
  height: 36.0,
  style: style,
  color: _color,
  corner: _corner,
  prefixes: [ buildAction() ],
  suffixes: [ buildAction() ],

  /// Hints
  hints: [
    "FSuper is awesome 👍",
    "Come to use FButton",
    "You will love FSearch",
  ],

  /// 开启 hint 交换动画
  ///
  /// Turn on hint exchange animation
  hintSwitchEnable: true,

  /// 配置 hint 交换动画类型
  ///
  /// Configure hint exchange animation type
  hintSwitchType: FSearchAnimationType.Fade,
)

FSearch provides developers with a very powerful Hint effect.

Developers can easily set multiple Hint for FSearch, and can configure multiple Hint swap animations by configuring hintSwitchEnable: true.

When the user starts typing, Hint will be automatically hidden, and the swap animation will also be stopped.

When the content of the search input box becomes empty again, Hint will appear again, and the exchange animation will start playing.

/// #2
FSearch(
  height: 36.0,
  style: style,
  color: _color,
  corner: _corner,
  prefixes: [ buildAction() ],
  suffixes: [ buildAction1(),  buildAction2()],
  hints: [
    "Do you want to try FFloat?😃",
    "FRadio can do more 😱 !",
    "I heard that you have been waiting for FDottedLine for a long time...",
  ],
  hintSwitchEnable: true,
)

FSearch has prepared rich exchange animations for developers. By default, FSearch will use the most common scroll swap animation, which is FSearchAnimationType.Scroll.

Of course, developers can configure their favorite animation types through the hintSwitchType parameter.

💡 Note that when hints.length == 1, the Hint swap animation will not be played. Only an ordinary Hint will be displayed at this time.

/// #3
FSearch(
  height: 36.0,
  style: style,
  color: _color,
  corner: _corner,
  prefixes: [ buildAction() ],
  suffixes: [ buildAction() ],

  /// Hints
  hints: [
    "Embrace FWidget 👬",
    "We care about your app 🥰",
    "Want to build beautiful apps 🤨 ?",
  ],
  hintSwitchEnable: true,

  /// 配置 hint 交换动画类型
  ///
  /// Configure hint exchange animation type
  hintSwitchType: FSearchAnimationType.Scale,

  /// 获得焦点时是否停止交换动画
  ///
  /// Whether to stop exchanging animation when focus is obtained
  stopHintSwitchOnFocus: false,
)

By default, when FSearch gains input focus, FSearch will automatically pause Hint to swap animations; when it gets focus again, it will resume automatically.

By configuring stopHintSwitchOnFocus: false, you can continue to play Hint swap animation until the user starts typing when FSearch has the focus.

💻 Controller #

FSearch(
  controller: _controller,
  height: 36.0,
  style: style,
  gradient: _gradient,
  corner: _corner,
  prefixes: [ buildAction() ],
  suffixes: [ buildAction() ],
  hints: [
    "Want more beautiful widgets 🤨 ?",
    "We will launch the official website of FWidget",
    "Will you expect it?",
  ],
  hintStyle: hintStyle,
  hintSwitchEnable: true,
)

/// 获取输入框内容
///
/// Get the input box content
String input = controller.text;

/// 清空输入框内容
///
/// Clear the contents of the input box
controller.text = null;

/// 获取当前 hint,如果有的话
///
/// Get the current hint, if any
String hint = controller.hint;

/// 移除焦点
/// 
/// Remove focus
controller.clearFocus();


/// 获取焦点
///
/// Request focus
controller.requestFocus();

FSearch provides developers with simple, easy-to-use, certain controllers, through which developers can modify or obtain the contents of the search bar at any location.

😃 How to use? #

Add dependencies in the project pubspec.yaml file:

🌐 pub dependency #

dependencies:
  fsearch: ^<version number>

⚠️ Attention,please go to [pub] (https://pub.dev/packages/fsearch) to get the latest version number of FSearch

🖥 Git dependency #

dependencies:
  fsearch:
    git:
      url: 'git@github.com:Fliggy-Mobile/fsearch.git'
      ref: '<Branch number or tag number>'

⚠️ Attention,please refer to [FSearch] (https://github.com/Fliggy-Mobile/fsearch) official project for branch number or tag.

💡 License #

Copyright 2020-present Fliggy Android Team <alitrip_android@list.alibaba-inc.com>.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at following link.

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Like it? Please cast your Star 🥰 ! #


How to run Demo project? #

  1. clone project to local

  2. Enter the project example directory and run the following command

flutter create .
  1. Run the demo in example

1.0.0 #

  • the first version

example/lib/main.dart

import 'dart:async';

import 'package:fbutton/fbutton.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fsearch/fsearch.dart';
import 'package:fsearch_example/color.dart';
import 'package:fsearch_example/part.dart';
import 'package:fsuper/fsuper.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  FSearchController controller1;
  FSearchController controller2;
  FSearchController controller3;
  FSearchController controller4;
  FSearchController controller5;
  FSearchController controller6_1;
  FSearchController controller6_2;
  FSearchController controller6_3;
  FSearchController controller7;

  bool searching1 = false;
  bool searching2 = false;
  bool searching3 = false;
  bool searching4 = false;
  bool searching5 = false;
  bool searching6_1 = false;
  bool searching6_2 = false;
  bool searching6_3 = false;
  bool searching7 = false;

  @override
  void initState() {
    controller1 = FSearchController();
    controller2 = FSearchController();
    controller3 = FSearchController();
    controller3.setListener(() {
      print(
          'controller3.text = ${controller3.text}, controller3.hint = ${controller3.hint}');
    });
    controller4 = FSearchController();
    controller5 = FSearchController();
    controller6_1 = FSearchController();
    controller6_2 = FSearchController();
    controller6_3 = FSearchController();
    controller7 = FSearchController();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: mainBackgroundColor,
        appBar: AppBar(
          backgroundColor: mainBackgroundColor,
          title: const Text(
            'FSearch',
            style: TextStyle(color: mainTextTitleColor),
          ),
          centerTitle: true,
        ),
        body: Builder(builder: (context) {
          return SingleChildScrollView(
            physics: BouncingScrollPhysics(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                buildTitle("Base Demo"),
                buildBigMargin(),

                /// demo1
                buildDemo1(),

                buildBigMargin(),
                buildTitle("Prefixes & Suffixes"),
                buildBigMargin(),

                /// demo2
                buildDemo2(),

                buildBigMargin(),
                buildTitle("Gradient"),
                buildBigMargin(),

                /// demo3
                buildDemo3(),

                buildBigMargin(),
                buildTitle("Corner & Stroke & Shadow"),
                buildBigMargin(),

                /// demo4
                buildDemo4(),

                buildBigMargin(),
                buildTitle("Cursor"),
                buildBigMargin(),

                /// demo5
                buildDemo5(),

                buildBigMargin(),
                buildTitle("Hint"),
                buildBigMargin(),

                /// demo6
                buildDemo6(),

                buildBigMargin(),
                buildTitle("Controller"),
                buildBigMargin(),

                /// demo7
                buildDemo7(),

                buildBigMargin(),
                buildTitle("More"),
                buildBigMargin(),

                buildBiggestMargin(),
                buildBiggestMargin(),
                buildBiggestMargin(),
                buildBiggestMargin(),
                buildBiggestMargin(),
                buildBiggestMargin(),
                buildBiggestMargin(),
              ],
            ),
          );
        }),
      ),
    );
  }

  Widget buildDemo1() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        searching: searching1,
        done: () => searching1 = false,
        child: FSearch(
          height: 30.0,
          backgroundColor: mainBackgroundColor,
          style: TextStyle(fontSize: 16.0, height: 1.0, color: Colors.grey),
          margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0),
          padding:
              EdgeInsets.only(left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
          prefixes: [
            const SizedBox(width: 6.0),
            Icon(
              Icons.search,
              size: 18,
              color: mainTextTitleColor,
            ),
            const SizedBox(width: 3.0)
          ],

          /// 点击键盘搜索时触发
          ///
          /// Fired when you click on the keyboard to search
          onSearch: (value) {
            setState(() {
              searching1 = true;
            });
          },
        ),
      );
    });
  }

  Widget buildDemo2() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        searching: searching2,
        done: () => searching2 = false,
        child: FSearch(
          controller: controller2,
          height: 30.0,
          backgroundColor: mainBackgroundColor,
          style: TextStyle(fontSize: 16.0, height: 1.0, color: Colors.grey),
          margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0),
          padding:
              EdgeInsets.only(left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
          prefixes: [
            const SizedBox(width: 6.0),
            Icon(
              Icons.search,
              size: 18,
              color: mainTextTitleColor,
            ),
            const SizedBox(width: 3.0)
          ],
          suffixes: [
            FButton(
              onPressed: () {
                dialog(context, "Smile 😊");
              },
              padding: EdgeInsets.only(left: 6.0, right: 6.0),
              color: Colors.transparent,
              effect: true,
              image: Icon(
                Icons.camera_enhance,
                size: 18,
                color: mainTextTitleColor,
              ),
            ),
            FButton(
              onPressed: () {
                controller2.text = null;
              },
              padding: EdgeInsets.only(left: 6.0, right: 6.0),
              color: Colors.transparent,
              effect: true,
              image: Icon(
                Icons.clear,
                size: 18,
                color: mainTextTitleColor,
              ),
            ),
            FSuper(
              text: "Back",
              textColor: mainTextTitleColor,
              fontHeight: 1.0,
              height: 30,
              textAlignment: Alignment.center,
              backgroundColor: Colors.white,
              padding: EdgeInsets.only(left: 6.0),
              onClick: () {
                dialog(context, "Back!");
              },
            )
          ],
          onSearch: (value) {
            setState(() {
              searching2 = true;
            });
          },
        ),
      );
    });
  }

  Widget buildDemo3() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        searching: searching3,
        done: () => searching3 = false,
        child: Center(
          child: FSearch(
            /// 渐变色
            ///
            /// gradient
            gradient: LinearGradient(
              colors: [
                Colors.blue[50],
                Colors.red[50],
              ],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
            height: 30.0,
//          backgroundColor: mainBackgroundColor,
            style: TextStyle(fontSize: 16.0, height: 1.0, color: Colors.grey),
            margin: EdgeInsets.only(left: 12.0, right: 12.0, bottom: 38.0),
            corner: FSearchCorner.all(6.0),
            padding:
                EdgeInsets.only(left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
            prefixes: [
              const SizedBox(width: 6.0),
              Icon(
                Icons.search,
                size: 18,
                color: mainTextTitleColor,
              ),
              const SizedBox(width: 3.0)
            ],

            /// 点击键盘搜索时触发
            ///
            /// Fired when you click on the keyboard to search
            onSearch: (value) {
              setState(() {
                searching3 = true;
              });
            },
          ),
        ),
      );
    });
  }

  Widget buildDemo4() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        searching: searching4,
        done: () => searching4 = false,
        child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              FSearch(
                height: 30.0,
                backgroundColor: mainBackgroundColor,

                /// 边角
                ///
                /// Corner
                corner: FSearchCorner(
                    leftTopCorner: 15.0,
                    leftBottomCorner: 15.0,
                    rightBottomCorner: 15.0),

                /// 边框宽
                ///
                /// border width
                strokeWidth: 1.0,

                /// 边框颜色
                ///
                /// border color
                strokeColor: mainTextTitleColor,

                /// 阴影
                ///
                /// shadow
                shadowColor: Colors.black38,
                shadowBlur: 5.0,
                shadowOffset: Offset(2.0, 2.0),
                style:
                    TextStyle(fontSize: 16.0, height: 1.0, color: Colors.grey),
                margin: EdgeInsets.only(left: 12.0, right: 12.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 18,
                    color: mainTextTitleColor,
                  ),
                  const SizedBox(width: 3.0)
                ],

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching4 = true;
                  });
                },
              ),
              const SizedBox(height: 56.0),
              FSearch(
                height: 30.0,
                backgroundColor: mainBackgroundColor,

                /// 边角
                ///
                /// Corner
                corner: FSearchCorner.all(6.0),

                /// 边角风格
                ///
                /// Corner style
                cornerStyle: FSearchCornerStyle.bevel,

                /// 边框宽
                ///
                /// border width
                strokeWidth: 0.5,

                /// 边框颜色
                ///
                /// border color
                strokeColor: mainTextTitleColor,

                /// 阴影
                ///
                /// shadow
                shadowColor: Colors.black38,
                shadowBlur: 5.0,
                shadowOffset: Offset(2.0, 2.0),
                style:
                    TextStyle(fontSize: 16.0, height: 1.0, color: Colors.grey),
                margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 18,
                    color: mainTextTitleColor,
                  ),
                  const SizedBox(width: 3.0)
                ],

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching4 = true;
                  });
                },
              ),
            ],
          ),
        ),
      );
    });
  }

  Widget buildDemo5() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        searching: searching5,
        done: () => searching5 = false,
        child: Center(
          child: FSearch(
            /// 光标
            ///
            /// Cursor
            cursorColor: Colors.red[200],
            cursorRadius: 5.0,
            cursorWidth: 5.0,
            gradient: LinearGradient(
              colors: [
                Colors.deepOrange[100],
                Colors.amber[50],
              ],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
            shadowColor: mainShadowColor,
            shadowBlur: 5.0,
            shadowOffset: Offset(3.0, 3.0),
            height: 36.0,
            corner: FSearchCorner(
                leftTopCorner: 18.0,
                leftBottomCorner: 18.0,
                rightBottomCorner: 18.0),
            style: TextStyle(fontSize: 18.0, height: 1.2, color: Colors.white),
            margin: EdgeInsets.only(left: 12.0, right: 12.0, bottom: 38.0),
            padding:
                EdgeInsets.only(left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
            prefixes: [
              const SizedBox(width: 6.0),
              Icon(
                Icons.search,
                size: 22,
                color: Colors.white,
              ),
              const SizedBox(width: 3.0)
            ],
            suffixes: [
              FButton(
                onPressed: () {
                  dialog(context, "Smile 😊");
                },
                padding: EdgeInsets.only(left: 12.0, right: 12.0),
                effect: true,
                corner: FButtonCorner(rightBottomCorner: 18.0),
                color: Colors.transparent,
                image: Icon(
                  Icons.camera_enhance,
                  color: Colors.white,
                ),
              )
            ],

            /// 点击键盘搜索时触发
            ///
            /// Fired when you click on the keyboard to search
            onSearch: (value) {
              setState(() {
                searching5 = true;
              });
            },
          ),
        ),
      );
    });
  }

  Widget buildDemo6() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        width: 300,
        height: 400,
        searching: searching6_1,
        done: () => searching6_1 = false,
        child: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              /// #1
              FSearch(
                shadowColor: mainShadowColor,
                shadowBlur: 5.0,
                shadowOffset: Offset(3.0, 3.0),
                height: 36.0,
                corner: FSearchCorner.all(3.0),
                backgroundColor: Colors.white,
                style: TextStyle(
                    fontSize: 14.0, height: 1.2, color: Color(0xff333333)),
                margin: EdgeInsets.only(left: 12.0, right: 12.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 20,
                    color: Colors.grey,
                  ),
                  const SizedBox(width: 3.0)
                ],
                suffixes: [
                  FButton(
                    onPressed: () {
                      dialog(context, "Speaking...");
                    },
                    padding: EdgeInsets.only(left: 12.0, right: 12.0),
                    effect: true,
                    color: Colors.transparent,
                    image: Icon(
                      Icons.mic,
                      color: Colors.grey,
                      size: 20,
                    ),
                  )
                ],

                /// Hints
                hints: [
                  "FSuper is awesome 👍",
                  "Come to use FButton",
                  "You will love FRefresh",
                ],

                /// 开启 hint 交换动画
                ///
                /// Turn on hint exchange animation
                hintSwitchEnable: true,

                /// 配置 hint 交换动画类型
                ///
                /// Configure hint exchange animation type
                hintSwitchType: FSearchAnimationType.Fade,

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching6_1 = true;
                  });
                },
              ),
              const SizedBox(height: 36.0),

              /// #2
              FSearch(
                shadowColor: mainShadowColor,
                shadowBlur: 5.0,
                shadowOffset: Offset(3.0, 3.0),
                height: 36.0,
                corner: FSearchCorner.all(18.0),
                backgroundColor: Colors.white,
                style: TextStyle(
                    fontSize: 14.0, height: 1.2, color: Color(0xff333333)),
                margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 20,
                    color: Colors.grey[400],
                  ),
                  const SizedBox(width: 3.0)
                ],
                suffixes: [
                  FButton(
                    onPressed: () {
                      dialog(context, "Smile 😊");
                    },
                    padding: EdgeInsets.only(left: 3.0, right: 3.0),
                    effect: true,
                    color: Colors.transparent,
                    image: Icon(
                      Icons.photo_camera,
                      color: Colors.grey[400],
                      size: 20,
                    ),
                  ),
                  const SizedBox(width: 6.0),
                  FButton(
                    text: "Search",
                    textColor: Colors.white,
                    fontSize: 10.0,
                    height: 30.0,
                    onPressed: () {
                      setState(() {
                        searching6_1 = true;
                      });
                    },
                    padding: EdgeInsets.only(left: 6.0, right: 6.0),
                    corner: FButtonCorner.all(15.0),
                    effect: true,
                    gradient: LinearGradient(colors: [
                      Colors.orange[500],
                      Colors.orange[900],
                    ]),
                  ),
                  const SizedBox(width: 6.0),
                ],
                hints: [
                  "Do you want to try FFloat?😃",
                  "FRadio can do more 😱 !",
                  "I heard that you have been waiting for FDottedLine for a long time...",
                ],
                hintSwitchEnable: true,

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching6_1 = true;
                  });
                },
              ),
              const SizedBox(height: 36.0),

              /// #3
              FSearch(
                shadowColor: Colors.blue[100],
                shadowBlur: 5.0,
                shadowOffset: Offset(3.0, 3.0),
                height: 36.0,
                corner: FSearchCorner.all(9.0),
                cornerStyle: FSearchCornerStyle.bevel,
                strokeColor: Colors.blue[200],
                strokeWidth: 0.5,
                backgroundColor: Colors.white,
                style: TextStyle(
                    fontSize: 14.0, height: 1.2, color: Color(0xff333333)),
                margin: EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 20,
                    color: Colors.grey[400],
                  ),
                  const SizedBox(width: 3.0)
                ],
                suffixes: [
                  FButton(
                    text: "Inquire",
                    textColor: Colors.white,
                    fontSize: 10.0,
                    corner: FButtonCorner(
                        leftTopCorner: 5.0,
                        leftBottomCorner: 5.0,
                        rightBottomCorner: 9.0,
                        rightTopCorner: 9.0),
                    cornerStyle: FButtonCornerStyle.bevel,
                    onPressed: () {
                      dialog(context, "Inquiry...");
                    },
                    padding: EdgeInsets.only(left: 14.0, right: 12.0),
                    effect: true,
                    color: Colors.blue[300],
                  )
                ],

                /// Hints
                hints: [
                  "Embrace FWidget 👬",
                  "We care about your app 🥰",
                  "Want to build beautiful apps 🤨 ?",
                ],

                /// 开启 hint 交换动画
                ///
                /// Turn on hint exchange animation
                hintSwitchEnable: true,

                /// 配置 hint 交换动画类型
                ///
                /// Configure hint exchange animation type
                hintSwitchType: FSearchAnimationType.Scale,

                /// 获得焦点时是否停止交换动画
                ///
                /// Whether to stop exchanging animation when focus is obtained
                stopHintSwitchOnFocus: false,

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching6_1 = true;
                  });
                },
              ),
            ],
          ),
        ),
      );
    });
  }

  String text_7 = "";

  Widget buildDemo7() {
    return StatefulBuilder(builder: (context, setState) {
      return PageWidget(
        width: 300,
        height: 250,
        searching: searching7,
        done: () => searching7 = false,
        child: Padding(
          padding: EdgeInsets.only(top: 38.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              FSearch(
                controller: controller7,
                cursorColor: Colors.red[200],
                cursorRadius: 2.0,
                cursorWidth: 3.0,
                gradient: LinearGradient(
                  colors: [
                    Colors.red[100],
                    Colors.purple[50],
                  ],
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                ),
                shadowColor: mainShadowColor,
                shadowBlur: 5.0,
                shadowOffset: Offset(3.0, 3.0),
                height: 36.0,
                corner: FSearchCorner(
                    leftTopCorner: 18.0,
                    leftBottomCorner: 18.0,
                    rightBottomCorner: 18.0),
                style:
                    TextStyle(fontSize: 16.0, height: 1.2, color: Colors.white),
                margin: EdgeInsets.only(left: 12.0, right: 12.0),
                padding: EdgeInsets.only(
                    left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                prefixes: [
                  const SizedBox(width: 6.0),
                  Icon(
                    Icons.search,
                    size: 22,
                    color: Colors.white,
                  ),
                  const SizedBox(width: 3.0)
                ],
                suffixes: [
                  FButton(
                    onPressed: () {
                      dialog(context, "Say something.. 😊");
                    },
                    padding: EdgeInsets.only(left: 12.0, right: 12.0),
                    effect: true,
                    corner: FButtonCorner(rightBottomCorner: 18.0),
                    color: Colors.transparent,
                    image: Icon(
                      Icons.mic,
                      color: Colors.white,
                    ),
                  )
                ],

                hints: [
                  "Want more beautiful widgets 🤨 ?",
                  "We will launch the official website of FWidget",
                  "Will you expect it?",
                ],
                hintStyle: TextStyle(
                    fontSize: 12.0, height: 1.0, color: Colors.grey[400]),
                hintSwitchEnable: true,

                /// 点击键盘搜索时触发
                ///
                /// Fired when you click on the keyboard to search
                onSearch: (value) {
                  setState(() {
                    searching7 = true;
                  });
                },
              ),
              const SizedBox(height: 38.0),
              Wrap(
                alignment: WrapAlignment.start,
                crossAxisAlignment: WrapCrossAlignment.center,
                spacing: 6.0,
                runSpacing: 9.0,
                children: [
                  FButton(
                    width: 60,
                    text: "GetText",
                    textColor: Colors.white,
                    fontSize: 12.0,
                    color: Colors.teal[200],
                    padding: EdgeInsets.only(
                        left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                    corner: FButtonCorner.all(10.0),
                    shadowColor: mainShadowColor,
                    shadowBlur: 5.0,
                    shadowOffset: Offset(3.0, 3.0),
                    effect: true,
                    onPressed: () {
                      setState(() {
                        text_7 = "text = ${controller7.text}";
                      });
                    },
                  ),
                  FButton(
                    width: 60,
                    text: "GetHint",
                    textColor: Colors.white,
                    fontSize: 12.0,
                    color: Colors.teal[200],
                    padding: EdgeInsets.only(
                        left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                    corner: FButtonCorner.all(10.0),
                    shadowColor: mainShadowColor,
                    shadowBlur: 5.0,
                    shadowOffset: Offset(3.0, 3.0),
                    effect: true,
                    onPressed: () {
                      setState(() {
                        text_7 = "hint = ${controller7.hint}";
                      });
                    },
                  ),
                  FButton(
                    width: 50,
                    text: "Clear",
                    textColor: Colors.white,
                    fontSize: 12.0,
                    color: Colors.teal[200],
                    padding: EdgeInsets.only(
                        left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                    corner: FButtonCorner.all(10.0),
                    shadowColor: mainShadowColor,
                    shadowBlur: 5.0,
                    shadowOffset: Offset(3.0, 3.0),
                    effect: true,
                    onPressed: () {
                      controller7.text = null;
                    },
                  ),
                  FButton(
                    width: 80,
                    text: "ClearFocus",
                    textColor: Colors.white,
                    fontSize: 12.0,
                    color: Colors.teal[200],
                    padding: EdgeInsets.only(
                        left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                    corner: FButtonCorner.all(10.0),
                    shadowColor: mainShadowColor,
                    shadowBlur: 5.0,
                    shadowOffset: Offset(3.0, 3.0),
                    effect: true,
                    onPressed: () {
                      controller7.clearFocus();
                    },
                  ),
                  FButton(
                    width: 100,
                    text: "RequestFocus",
                    textColor: Colors.white,
                    fontSize: 12.0,
                    color: Colors.teal[200],
                    padding: EdgeInsets.only(
                        left: 6.0, right: 6.0, top: 3.0, bottom: 3.0),
                    corner: FButtonCorner.all(10.0),
                    shadowColor: mainShadowColor,
                    shadowBlur: 5.0,
                    shadowOffset: Offset(3.0, 3.0),
                    effect: true,
                    onPressed: () {
                      controller7.requestFocus();
                    },
                  ),
                ],
              ),
              const SizedBox(height: 30.0),
              Container(
                width: 280.0,
                alignment: Alignment.center,
                child: Text(
                  text_7,
                  style: TextStyle(color: Colors.grey[300]),
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ],
          ),
        ),
      );
    });
  }
}

class PageWidget extends StatefulWidget {
  Widget child;
  bool searching;
  VoidCallback done;
  double width;
  double height;

  PageWidget({
    this.width = 200.0,
    this.height = 300.0,
    this.child,
    this.done,
    this.searching = false,
  });

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

class _PageWidgetState extends State<PageWidget> {
  Timer hideSearching;

  @override
  Widget build(BuildContext context) {
    hideSearching?.cancel();
    List<Widget> children = [];
    children.add(Positioned(
      child: widget.child,
    ));
    if (widget.searching) {
      children.add(FSuper(
        width: widget.width,
        height: widget.height,
        backgroundColor: Colors.black26,
        corner: Corner.all(6.0),
      ));
      children.add(Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            CupertinoActivityIndicator(),
            const SizedBox(height: 6.0),
            Text(
              "Searching...",
              style: TextStyle(color: mainTextTitleColor),
            )
          ],
        ),
      ));
      hideSearching = Timer(Duration(milliseconds: 2000), () {
        setState(() {
          widget.searching = false;
          widget.done?.call();
        });
      });
    }
    return Container(
      width: widget.width,
      height: widget.height,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.all(Radius.circular(6.0)),
        boxShadow: [
          BoxShadow(
              color: mainShadowColor, blurRadius: 6.0, offset: Offset(3, 3)),
        ],
      ),
      child: Stack(
        alignment: Alignment.topCenter,
        children: children,
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  fsearch: ^1.0.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:fsearch/fsearch.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
41
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
95
Overall:
Weighted score of the above. [more]
70
Learn more about scoring.

We analyzed this package on Jul 9, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • fsearch that is a package requiring null.

Health suggestions

Format lib/fsearch.dart.

Run flutter format to format lib/fsearch.dart.

Maintenance suggestions

The package description is too short. (-5 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8 1.2.2
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test