收录Autocomplete组件

This commit is contained in:
toly
2022-04-18 13:26:26 +08:00
parent 4e705934c2
commit 1812ab8042
12 changed files with 330 additions and 24 deletions

Binary file not shown.

View File

@@ -20,7 +20,10 @@ class EventLoadCategory extends CategoryEvent{
class EventToggleWidget extends CategoryEvent{
final int widgetId;
final int categoryId;
const EventToggleWidget({required this.widgetId, required this.categoryId});
const EventToggleWidget({
required this.widgetId,
required this.categoryId,
});
@override
List<Object> get props => [widgetId,categoryId];
@@ -42,8 +45,11 @@ class EventAddCategory extends CategoryEvent{
final String? info;
final String? color;
const EventAddCategory(
{required this.name, required this.info, required this.color});
const EventAddCategory({
required this.name,
required this.info,
required this.color,
});
@override
List<Object?> get props => [name, info, color];
@@ -58,13 +64,14 @@ class EventUpdateCategory extends CategoryEvent {
final int? priority;
final String? image;
const EventUpdateCategory(
{required this.name,
required this.info,
required this.color,
this.priority,
this.image,
required this.id});
const EventUpdateCategory({
required this.name,
required this.info,
required this.color,
this.priority,
this.image,
required this.id,
});
@override
List<Object?> get props => [name, info, color, priority, image, id];

View File

@@ -19,7 +19,11 @@ class DetailWithData extends DetailState {
final List<WidgetModel> links;
final List<NodeModel> nodes;
const DetailWithData({required this.widgetModel,required this.nodes,required this.links});
const DetailWithData({
required this.widgetModel,
required this.nodes,
required this.links,
});
@override
List<Object> get props => [widgetModel,nodes];

View File

@@ -24,7 +24,6 @@ class _AppSearchBarState extends State<AppSearchBar> {
height: 35,
child: TextField(
autofocus: true,
//自动聚焦,闪游标
controller: _controller,
maxLines: 1,
decoration: const InputDecoration(
@@ -39,8 +38,8 @@ class _AppSearchBarState extends State<AppSearchBar> {
hintStyle: TextStyle(fontSize: 14)),
onChanged: _doSearch,
onSubmitted: (str) {
//提交后
FocusScope.of(context).requestFocus(FocusNode()); //收起键盘
//提交后,收起键盘
FocusScope.of(context).requestFocus(FocusNode());
},
)),
_buildClearIcon()

View File

@@ -7,7 +7,6 @@ class NotSearchPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Color color = Theme.of(context).primaryColor;
return Container(
height: 300,
alignment: Alignment.center,

View File

@@ -51,6 +51,16 @@ class _TolyAppBarState extends State<TolyAppBar>
'Other'
];
static const List<String> semantics = [
'无状态组件',
'有状态组件',
'单子组件',
'多子组件',
'滑动组件',
'代理组件',
'其他组件'
];
late AnimationController _controller;
late Animation<double> circleAnim;
late Animation<double> heightAnim;
@@ -113,7 +123,7 @@ class _TolyAppBarState extends State<TolyAppBar>
Widget _buildChild(int color) {
ThemeData themeData = Theme.of(context);
bool isDark = themeData.brightness == Brightness.dark;
int index = colors.indexOf(color);
return Container(
alignment: const Alignment(0, 0.4),
decoration: BoxDecoration(boxShadow: [
@@ -128,8 +138,9 @@ class _TolyAppBarState extends State<TolyAppBar>
height: widget.maxHeight + 20,
width: _width,
child: Text(
info[colors.indexOf(color)],
info[index],
style: _kTabTextStyle,
semanticsLabel: '您当前点击了:${semantics[index]}',
),
);
}

View File

@@ -7,8 +7,7 @@ import 'package:flutter/cupertino.dart';
// "widgetId": 143,
// "name": 'CupertinoContextMenu基本使用',
// "priority": 1,
// "subtitle":
// "【child】 : 子组件 【Widget】\n"
// "subtitle": "【child】 : 子组件 【Widget】\n"
// "【actions】 : 行为组件集 【List<Widget>】\n"
// "【previewBuilder】 : 动画构造器 【ContextMenuPreviewBuilder】",
// }

View File

@@ -0,0 +1,47 @@
import 'dart:async';
import 'package:flutter/material.dart';
/// create by 张风捷特烈 on 2022-04-18
/// contact me by email 1981462002@qq.com
/// 说明:
// {
// "widgetId": 356,
// "name": 'Autocomplete基本使用',
// "priority": 1,
// "subtitle": "【optionsBuilder】 : 选项构造器 【AutocompleteOptionsBuilder<T>】\n"
// "【onSelected】 : 选择时回调 【AutocompleteOnSelected<T>】",
// }
class AutocompleteDemo extends StatelessWidget {
const AutocompleteDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Autocomplete<String>(
optionsBuilder: buildOptions,
onSelected: onSelected,
);
}
void onSelected(String selection) {
debugPrint('当前选择了 $selection');
}
Future<Iterable<String>> buildOptions(
TextEditingValue textEditingValue,
) async {
if (textEditingValue.text == '') {
return const Iterable<String>.empty();
}
return searchByArgs(textEditingValue.text);
}
Future<Iterable<String>> searchByArgs(String args) async{
// 模拟网络请求
await Future.delayed(const Duration(milliseconds: 200));
const List<String> data = [
'toly', 'toly49', 'toly42', 'toly56',
'card', 'ls', 'alex', 'fan sha',
];
return data.where((String name) => name.contains(args));
}
}

View File

@@ -0,0 +1,227 @@
import 'dart:async';
import 'package:flutter/material.dart';
/// create by 张风捷特烈 on 2022-04-18
/// contact me by email 1981462002@qq.com
/// 说明:
// {
// "widgetId": 356,
// "name": 'Autocomplete的泛型',
// "priority": 2,
// "subtitle": "【optionsViewBuilder】 : 面板构造器 【AutocompleteOptionsViewBuilder<T>】\n"
// "【fieldViewBuilder】 : 输入构造器 【AutocompleteFieldViewBuilder】\n"
// "【displayStringForOption】 : 文字展示 【AutocompleteOptionToString】\n",
// }
class AutocompleteType extends StatefulWidget {
const AutocompleteType({Key? key}) : super(key: key);
@override
State<AutocompleteType> createState() => _AutocompleteTypeState();
}
class _AutocompleteTypeState extends State<AutocompleteType> {
late TextEditingController _controller;
User? user;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: buildAutocomplete(),
),
body: Center(
child: Text(
user != null ? user!.name : '未选择',
style: const TextStyle(fontSize: 40),
)),
),
);
}
Widget buildAutocomplete() {
return Autocomplete<User>(
optionsBuilder: buildOptions,
onSelected: onSelected,
optionsViewBuilder: _buildOptionsView,
fieldViewBuilder: _buildFieldView,
displayStringForOption: (user) => user.name,
);
}
@override
void dispose() {
// _controller.dispose();
super.dispose();
}
void onSelected(User selection) {
debugPrint('当前选择了 $selection');
setState(() {
user = selection;
});
}
Future<Iterable<User>> buildOptions(
TextEditingValue textEditingValue,
) async {
if (textEditingValue.text == '') {
return const Iterable<User>.empty();
}
return searchByArgs(textEditingValue.text);
}
Future<Iterable<User>> searchByArgs(String args) async {
// 模拟网络请求
await Future.delayed(const Duration(milliseconds: 200));
const List<User> data = [
User('toly', true, 'icon_5.webp'),
User('toly49', false, 'icon_6.webp'),
User('toly42', true, 'icon_7.webp'),
User('toly56', false, 'icon_8.webp'),
User('card', true, 'icon_5.webp'),
User('ls', true, 'icon_6.webp'),
User('alex', true, 'icon_7.webp'),
User('fan sha', false, 'icon_8.webp'),
];
return data.where((User user) => user.name.contains(args));
}
Widget _buildFieldView(
BuildContext context,
TextEditingController textEditingController,
FocusNode focusNode,
VoidCallback onFieldSubmitted) {
_controller = textEditingController;
return SizedBox(
height: 34,
child: TextFormField(
controller: textEditingController,
decoration: const InputDecoration(
filled: true,
fillColor: Color(0xffF7F8FA),
prefixIcon: Icon(Icons.search),
contentPadding: EdgeInsets.only(top: 1),
border: UnderlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(19)),
),
hintText: "输入用户名 (toly)",
hintStyle: TextStyle(fontSize: 13)),
focusNode: focusNode,
onFieldSubmitted: (String value) {
onFieldSubmitted();
},
),
);
}
Widget _buildOptionsView(BuildContext context,
AutocompleteOnSelected<User> onSelected, Iterable<User> options) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Material(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 150),
child: ListView.builder(
padding: EdgeInsets.zero,
itemBuilder: (_, index) {
final User option = options.elementAt(index);
return _UserItem(
onSelected: onSelected,
user: option,
args: _controller.text,
);
},
itemCount: options.length,
),
),
),
),
);
}
}
class _UserItem extends StatelessWidget {
final AutocompleteOnSelected<User>? onSelected;
final String args;
final User user;
const _UserItem({
Key? key,
this.onSelected,
required this.user,
required this.args,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => onSelected?.call(user),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 6),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
foregroundColor: Colors.transparent,
backgroundImage:
AssetImage('assets/images/head_icon/${user.image}'),
),
const SizedBox(width: 20),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text.rich(formSpan(user.name, args)),
Text(
'性别: ${user.man ? '' : ''}',
style: const TextStyle(color: Colors.grey),
),
],
),
],
),
),
);
}
final TextStyle lightTextStyle = const TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
);
InlineSpan formSpan(String src, String pattern) {
List<TextSpan> span = [];
List<String> parts = src.split(pattern);
if (parts.length > 1) {
for (int i = 0; i < parts.length; i++) {
span.add(TextSpan(text: parts[i]));
if (i != parts.length - 1) {
span.add(TextSpan(text: pattern, style: lightTextStyle));
}
}
} else {
span.add(TextSpan(text: src));
}
return TextSpan(children: span);
}
}
class User {
final String name;
final bool man;
final String image;
const User(this.name, this.man, this.image);
@override
String toString() {
return 'User{name: $name, man: $man, image: $image}';
}
}

View File

@@ -194,4 +194,7 @@ export '../StatelessWidget/PageStorage/node1_base.dart';
export '../StatelessWidget/NotificationListener/node1_base.dart';
export '../StatelessWidget/NotificationListener/node2_update.dart';
export '../StatelessWidget/Autocomplete/node1_base.dart';
export '../StatelessWidget/Autocomplete/node2_type.dart';

View File

@@ -26,6 +26,12 @@ class WidgetsMap {
const CupertinoSegmentedControlDemo(),
const CupertinoSegmentedControlColor()
];
case "Autocomplete":
return [
const AutocompleteDemo(),
const AutocompleteType()
];
case "CompositedTransformTarget":
return [
const CompositedTransformTargetDemo(),
@@ -33,16 +39,20 @@ class WidgetsMap {
case "CompositedTransformFollower":
return [
const CompositedTransformFollowerDemo(),
]; case "PrimaryScrollController":
];
case "PrimaryScrollController":
return [
const PrimaryScrollControllerDemo(),
];case "CupertinoFullscreenDialogTransition":
];
case "CupertinoFullscreenDialogTransition":
return [
const CupertinoFullscreenDialogTransitionDemo(),
];case "CupertinoPageTransition":
];
case "CupertinoPageTransition":
return [
const CupertinoPageTransitionDemo(),
];case "HtmlElementView":
];
case "HtmlElementView":
return [
const HtmlElementViewDemo(),
];

View File

@@ -1,7 +1,7 @@
name: flutter_unit
description: A new Flutter application.
version: 2.0.0
version: 2.0.1
author: 张风捷特烈 <1981462002@qq.com>
homepage: https://juejin.cn/user/149189281194766/posts