107 lines
4.0 KiB
Dart
107 lines
4.0 KiB
Dart
|
import 'package:flutter/material.dart';
|
|||
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
|||
|
import 'package:sk_base_mobile/app_theme.dart';
|
|||
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
|||
|
|
|||
|
class SkSearchSelect<T> extends StatelessWidget {
|
|||
|
final TextEditingController textController;
|
|||
|
final Function? suggestionsCallback;
|
|||
|
final void Function(T)? onSelected;
|
|||
|
final VoidCallback? onClear;
|
|||
|
final String? labelText;
|
|||
|
final String hintText;
|
|||
|
final EdgeInsetsGeometry? contentPadding;
|
|||
|
final bool isRequired;
|
|||
|
final Widget Function(BuildContext, T) itemBuilder;
|
|||
|
const SkSearchSelect(
|
|||
|
{super.key,
|
|||
|
required this.textController,
|
|||
|
required this.itemBuilder,
|
|||
|
required this.suggestionsCallback,
|
|||
|
this.hintText = '请选择',
|
|||
|
this.onSelected,
|
|||
|
this.labelText,
|
|||
|
this.onClear,
|
|||
|
this.contentPadding,
|
|||
|
this.isRequired = false});
|
|||
|
|
|||
|
@override
|
|||
|
Widget build(BuildContext context) {
|
|||
|
return TypeAheadField(
|
|||
|
hideOnUnfocus: true,
|
|||
|
controller: textController,
|
|||
|
suggestionsCallback: (String keyword) {
|
|||
|
return suggestionsCallback != null
|
|||
|
? suggestionsCallback!(keyword)
|
|||
|
: [];
|
|||
|
},
|
|||
|
debounceDuration: const Duration(milliseconds: 500),
|
|||
|
itemSeparatorBuilder: (context, index) => const Divider(
|
|||
|
color: AppTheme.dividerColor,
|
|||
|
),
|
|||
|
builder: (context, _, focusNode) {
|
|||
|
return TextFormField(
|
|||
|
focusNode: focusNode,
|
|||
|
controller: _,
|
|||
|
decoration: InputDecoration(
|
|||
|
contentPadding: contentPadding,
|
|||
|
focusedBorder: OutlineInputBorder(
|
|||
|
borderSide: const BorderSide(
|
|||
|
color: AppTheme.primaryColorLight, width: 2),
|
|||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
|
|||
|
suffixIcon: _.text.isNotEmpty && focusNode.hasFocus
|
|||
|
? IconButton(
|
|||
|
icon: const Icon(Icons.clear),
|
|||
|
// 当点击这个按钮时,清除TextFormField的值
|
|||
|
onPressed: () {
|
|||
|
_.clear();
|
|||
|
if (onClear != null) {
|
|||
|
onClear!();
|
|||
|
}
|
|||
|
},
|
|||
|
)
|
|||
|
: null,
|
|||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
|||
|
hintText: hintText,
|
|||
|
label: labelText != null
|
|||
|
? Row(
|
|||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|||
|
mainAxisSize: MainAxisSize.min,
|
|||
|
children: [
|
|||
|
if (isRequired)
|
|||
|
Text(
|
|||
|
"*",
|
|||
|
style: TextStyle(
|
|||
|
color: Colors.red,
|
|||
|
fontSize: ScreenAdaper.height(30)),
|
|||
|
),
|
|||
|
Text(
|
|||
|
labelText ?? '',
|
|||
|
style: TextStyle(
|
|||
|
fontSize: ScreenAdaper.height(30)),
|
|||
|
),
|
|||
|
])
|
|||
|
: const SizedBox()));
|
|||
|
},
|
|||
|
emptyBuilder: (_) => Container(
|
|||
|
alignment: Alignment.center,
|
|||
|
width: ScreenAdaper.width(200),
|
|||
|
height: ScreenAdaper.height(50),
|
|||
|
child: Text(
|
|||
|
'未找到记录',
|
|||
|
style: TextStyle(fontSize: ScreenAdaper.height(20)),
|
|||
|
),
|
|||
|
),
|
|||
|
itemBuilder: (context, itemData) {
|
|||
|
return itemBuilder(context, itemData as T);
|
|||
|
},
|
|||
|
onSelected: (selectedItemData) {
|
|||
|
// 键盘关闭
|
|||
|
FocusScope.of(context).unfocus();
|
|||
|
if (onSelected != null) {
|
|||
|
onSelected!(selectedItemData as T);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
}
|