import 'package:flutter/material.dart'; /// 全屏输入框 class VFullViewInput extends StatefulWidget { /// 初始值 final String? value; /// 占位文本 final String? placeholder; /// 值变更事件 final ValueChanged? onChanged; /// 是否可清除(一键) final bool? clearable; /// 前缀 final Widget? prefix; /// 后缀 final Widget? suffix; /// 字号 final double? fontSize; const VFullViewInput({ super.key, this.value, this.placeholder, this.onChanged, this.clearable, this.prefix, this.suffix, this.fontSize, }); @override State createState() => _InputState(); } class _InputState extends State { late String value; late final double fontSize; @override void initState() { fontSize = widget.fontSize ?? 20; value = widget.value ?? ""; super.initState(); } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (_, c) { final height = c.maxHeight; final borderRadius = height / 2; final border = OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(borderRadius)), borderSide: BorderSide.none, ); final suffix = _buildSuffix(); return SizedBox( height: height, child: TextField( controller: TextEditingController(text: value), readOnly: true, style: TextStyle(fontSize: fontSize), decoration: InputDecoration( border: border, enabledBorder: border, focusedBorder: border, filled: true, fillColor: Colors.grey.shade300, contentPadding: EdgeInsets.symmetric( vertical: (height - fontSize * 1.2) / 2, horizontal: borderRadius, ), hintStyle: TextStyle(fontSize: fontSize), labelStyle: TextStyle(fontSize: fontSize), hintText: widget.placeholder, prefixIcon: widget.prefix, suffixIcon: suffix != null ? Row( mainAxisSize: MainAxisSize.min, children: [ suffix, SizedBox(width: borderRadius / 4), ], ) : null, isCollapsed: true, ), onTap: () { _onTap(height); }, ), ); }, ); } void _onTap(double height) async { final result = await Navigator.of(context).push( MaterialPageRoute( fullscreenDialog: true, builder: (context) { return _InputDialog( height: height, fontSize: fontSize, title: widget.placeholder ?? "请输入", value: value, ); }, ), ); if (result != null) { setState(() { value = result; widget.onChanged?.call(value); }); } } Widget? _buildSuffix() { if (widget.suffix != null) { return widget.suffix; } if (widget.clearable == true && value.isNotEmpty) { return IconButton( icon: Icon( Icons.close, size: fontSize * 1.2, color: Colors.grey, ), onPressed: () { setState(() { value = ""; widget.onChanged?.call(value); }); }, ); } return null; } } class _InputDialog extends StatelessWidget { late final _controller = TextEditingController(text: value); final String value; final String title; final double fontSize; final double height; _InputDialog({ super.key, required this.value, required this.title, required this.fontSize, required this.height, }); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(title), titleTextStyle: TextStyle(color: Colors.grey.shade700, fontSize: 20), centerTitle: true, leading: IconButton( icon: const Icon(Icons.arrow_back, size: 28), onPressed: () { Navigator.of(context).pop(); }, ), actions: [ IconButton( icon: const Icon(Icons.check, size: 28), onPressed: () { _onCompleted(context); }, ) ], ), body: Container( alignment: Alignment.topCenter, padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), child: SizedBox( height: height, child: _buildInput(context), ), ), ); } Widget _buildInput(BuildContext context) { final borderRadius = height / 2; return TextField( autofocus: true, controller: _controller, style: TextStyle(fontSize: fontSize), decoration: InputDecoration( filled: true, fillColor: Colors.grey.shade300, focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(borderRadius), // borderSide: BorderSide(color: Theme.of(context).primaryColor), borderSide: BorderSide.none, ), contentPadding: EdgeInsets.symmetric( vertical: (height - fontSize * 1.2) / 2, horizontal: borderRadius, ), hintStyle: TextStyle(fontSize: fontSize), labelStyle: TextStyle(fontSize: fontSize), ), onEditingComplete: () { _onCompleted(context); }, onChanged: (value) { _controller.text = value; }, ); } void _onCompleted(BuildContext context) { Navigator.of(context).pop(_controller.text); } }