123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /*
- * @Author: XianKaiQun
- * @Date: 2020-09-14 09:34:57
- * @LastEditors: wjc
- * @LastEditTime: 2023-01-11 09:42:06
- * @Description:
- */
- import 'package:flutter/material.dart';
- import 'package:wisdom_cli/src/assets.gen.dart';
- import 'package:wisdom_cli/wisdom_cli.dart';
- ///搜索组件
- class WSearch extends StatefulWidget {
- WSearch({
- Key? key,
- this.hintText,
- this.controller,
- this.onSubmitted,
- this.onCancel,
- this.onChanged,
- this.moonlight = true,
- this.isDark = false,
- this.padding,
- this.backColor,
- this.isStatic = false,
- this.isControlOutside = false,
- this.initValue,
- this.onInput,
- }) : super(key: key);
- final String? hintText;
- final TextEditingController? controller;
- final void Function(String value)? onSubmitted;
- final void Function(String value)? onChanged;
- final void Function()? onCancel;
- final void Function(bool value)? onInput;
- final EdgeInsetsGeometry? padding;
- final backColor;
- final String? initValue;
- final bool? isControlOutside;
- /// 搜索文字是否固定显示
- final bool isStatic;
- ///朦胧层
- final bool moonlight;
- /// 背景是否深色 默认是白色
- final bool isDark;
- @override
- _WSearchState createState() => _WSearchState();
- }
- class _WSearchState extends State<WSearch> {
- FocusNode? focusNode;
- TextEditingController? controller;
- GlobalKey globalKey = GlobalKey();
- String? value;
- Size? size;
- Offset? offset;
- OverlayEntry? entry;
- bool hasEntry = false;
- @override
- void initState() {
- controller = new TextEditingController();
- focusNode = new FocusNode();
- value = widget.initValue ?? '';
- if (widget.isControlOutside! && controller?.value != null) {
- controller!.value = TextEditingValue(
- text: widget.initValue ?? '',
- selection: TextSelection.fromPosition(
- TextPosition(
- affinity: TextAffinity.downstream, offset: value!.length),
- ),
- );
- }
- focusNode!.addListener(onfocus);
- super.initState();
- }
- @override
- void didUpdateWidget(WSearch oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (widget.isControlOutside! && controller?.value != null) {
- controller!.value = TextEditingValue(
- text: widget.initValue ?? '',
- selection: TextSelection.fromPosition(
- TextPosition(
- affinity: TextAffinity.downstream, offset: value!.length),
- ),
- );
- setState(() {});
- }
- }
- ///获取焦点时,显示朦胧层。
- ///通过globalKey获取当前input组件的绝对位置,
- ///然后通过[OverlayEntry]显示朦胧层铺满剩余位置,
- ///点击朦胧层触发`onCancel`事件
- onfocus() {
- if (focusNode!.hasFocus && widget.moonlight) {
- final RenderBox renderBox =
- globalKey.currentContext!.findRenderObject() as RenderBox;
- offset = renderBox.localToGlobal(Offset.zero);
- size = renderBox.size;
- entry = OverlayEntry(
- builder: (_) {
- return Positioned.fill(
- top: offset!.dy + size!.height,
- child: GestureDetector(
- onTap: () => onCancel(),
- child: ColoredBox(
- color: Colors.black26,
- ),
- ),
- );
- },
- );
- Overlay.of(context).insert(entry!);
- hasEntry = true;
- } else {
- hasEntry = false;
- entry?.remove();
- }
- setState(() {});
- }
- @override
- void dispose() {
- value = '';
- focusNode!.dispose();
- controller!.dispose();
- if (hasEntry) {
- entry!.remove();
- }
- super.dispose();
- }
- void onCancel() {
- setState(() {
- value = '';
- controller!.clear();
- focusNode!.unfocus();
- if (widget.onInput != null) {
- widget.onInput!(false);
- }
- if (widget.onCancel != null) {
- widget.onCancel!();
- }
- });
- }
- void onSubmitted(String v) {
- value = v;
- controller!.value = TextEditingValue(
- text: value!,
- selection: TextSelection.fromPosition(
- TextPosition(affinity: TextAffinity.downstream, offset: value!.length),
- ),
- );
- setState(() {});
- if (widget.onSubmitted != null) {
- widget.onSubmitted!(v);
- }
- if (widget.onInput != null) {
- widget.onInput!(false);
- }
- }
- void onChanged(String v) {
- value = v;
- setState(() {});
- if (widget.onChanged != null) {
- widget.onChanged!(v);
- }
- if (widget.onInput != null) {
- widget.onInput!(false);
- }
- }
- @override
- Widget build(BuildContext context) {
- final style = WTheme.of(context);
- final colorScheme = style.colorScheme;
- final _isStatic = widget.isStatic;
- return Wisdom.row(
- key: globalKey,
- padding: widget.padding ?? EdgeInsets.symmetric(vertical: 12.pt),
- color: widget.backColor ?? Colors.transparent,
- children: [
- SizedBox(width: 15.pt),
- TextFormField(
- onTap: () => {
- if (widget.onInput != null)
- {
- widget.onInput!(true),
- }
- },
- controller: controller,
- onFieldSubmitted: onSubmitted,
- focusNode: focusNode,
- onChanged: onChanged,
- textInputAction: TextInputAction.search,
- style: TextStyle(
- fontSize: 15.pt,
- textBaseline: TextBaseline.alphabetic,
- ),
- decoration: InputDecoration(
- hintText: widget.hintText,
- isCollapsed: true,
- hintStyle: TextStyle(
- color: Color(0xff999999),
- fontSize: 14.pt,
- textBaseline: TextBaseline.alphabetic,
- ),
- prefixIcon: Image(
- image: AssetList.$search_png_image,
- height: 15.pt,
- ),
- prefixIconConstraints: BoxConstraints(
- minWidth: 32.pt,
- ),
- // suffix: Text.rich(
- // WidgetSpan(
- // alignment: PlaceholderAlignment.middle,
- // baseline: TextBaseline.alphabetic,
- // child: WDot.delete(
- // onTap: () => {
- // value = '',
- // controller.clear(),
- // setState(() {}),
- // },
- // color: Colors.black12,
- // iconTheme: IconThemeData(color: Colors.grey, size: 13.pt),
- // ),
- // ),
- // ),
- filled: true,
- isDense: true,
- fillColor: widget.isDark ? colorScheme.background4 : Colors.white,
- contentPadding: EdgeInsets.symmetric(vertical: 11.pt),
- enabledBorder: UnderlineInputBorder(
- /// 边框不设置一个值会有个黑边
- borderSide: BorderSide(color: Colors.white, width: 0.1.pt),
- borderRadius: BorderRadius.circular(25.pt),
- ),
- focusedBorder: UnderlineInputBorder(
- /// 边框不设置一个值会有个黑边
- borderSide: BorderSide(color: Colors.white, width: 0.1.pt),
- borderRadius: BorderRadius.circular(25.pt),
- ),
- ),
- ).nestExpanded(),
- if (!focusNode!.hasFocus && !_isStatic) SizedBox(width: 15.pt),
- if (_isStatic)
- Wisdom(
- onTap: () => {
- onSubmitted(value!),
- focusNode!.unfocus(),
- },
- alignment: Alignment.center,
- margin: EdgeInsets.symmetric(horizontal: 5.pt),
- padding: EdgeInsets.symmetric(horizontal: 10.pt),
- child: WisText(
- '搜索',
- size: 14.pt,
- color: colorScheme.primary,
- weight: FontWeight.w400,
- textAlign: TextAlign.center,
- ),
- ),
- if (focusNode!.hasFocus && !_isStatic)
- Wisdom(
- onTap: () => onCancel(),
- height: 25.pt,
- alignment: Alignment.center,
- margin: EdgeInsets.symmetric(horizontal: 5.pt),
- padding: EdgeInsets.symmetric(horizontal: 10.pt),
- child: Text(
- '取消',
- textAlign: TextAlign.center,
- style: TextStyle(fontSize: 13.pt),
- ),
- ),
- ],
- );
- }
- }
|