123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- import 'package:flutter/material.dart';
- class VSearchInput extends StatelessWidget {
- /// 占位提示
- final String? placeholder;
- /// 搜索回调
- final ValueChanged<String>? onSearch;
- /// 清空回调
- final VoidCallback? onClear;
- /// 是否可一键清空
- final bool? clearable;
- final TextEditingController? textEditingController;
- const VSearchInput({
- super.key,
- this.placeholder,
- this.onSearch,
- this.clearable,
- this.onClear,
- this.textEditingController,
- });
- @override
- Widget build(BuildContext context) {
- return LayoutBuilder(
- builder: (_, c) {
- final controller = textEditingController ?? TextEditingController();
- final radius = c.maxHeight / 2;
- final border = OutlineInputBorder(
- borderRadius: BorderRadius.all(Radius.circular(radius)),
- borderSide: BorderSide.none,
- );
- return TextField(
- style: const TextStyle(fontSize: 20),
- controller: controller,
- decoration: InputDecoration(
- enabledBorder: border,
- focusedBorder: border,
- fillColor: const Color.fromRGBO(238, 238, 238, 1),
- filled: true,
- hintText: placeholder,
- hintStyle: const TextStyle(
- fontSize: 20,
- color: Colors.black54,
- ),
- contentPadding: EdgeInsets.symmetric(
- horizontal: radius * 1.2,
- vertical: (c.maxHeight - 24) / 2,
- ),
- // isDense: true,
- isCollapsed: false,
- // prefixIcon: prefixIcon,
- // suffixIcon: suffixIcon,
- suffixIcon: Row(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- if (clearable == true)
- _ClearableSuffixIcon(
- controller: controller,
- onTap: onClear,
- ),
- IconButton(
- icon: const Icon(Icons.search, size: 36),
- onPressed: () {
- onSearch?.call(controller.text);
- },
- ),
- const SizedBox(width: 8),
- ],
- ),
- ),
- onSubmitted: (value) {
- onSearch?.call(value);
- },
- );
- },
- );
- }
- }
- class _ClearableSuffixIcon extends StatefulWidget {
- final TextEditingController controller;
- final VoidCallback? onTap;
- const _ClearableSuffixIcon({required this.controller, this.onTap});
- @override
- State<StatefulWidget> createState() => _ClearableSuffixIconState();
- }
- class _ClearableSuffixIconState extends State<_ClearableSuffixIcon> {
- late TextEditingController controller;
- bool isShowIcon = false;
- @override
- void initState() {
- controller = widget.controller;
- WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- if (mounted) {
- controller.addListener(onTextUpdate);
- }
- });
- super.initState();
- }
- @override
- void dispose() {
- controller.removeListener(onTextUpdate);
- super.dispose();
- }
- void onTextUpdate() {
- final isNeedShow = controller.text.isNotEmpty;
- if (isShowIcon != isNeedShow) {
- setState(() {
- isShowIcon = isNeedShow;
- });
- }
- }
- @override
- Widget build(BuildContext context) {
- if (isShowIcon) {
- return IconButton(
- color: Colors.black,
- icon: Container(
- padding: const EdgeInsets.all(4),
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(16),
- color: Colors.black26,
- ),
- child: const Icon(Icons.close, size: 22, color: Colors.white),
- ),
- onPressed: () {
- controller.clear();
- widget.onTap?.call();
- },
- );
- } else {
- return const SizedBox();
- }
- }
- }
|