Skip to content

Commit 146e4d3

Browse files
committed
优化桌面端搜索
1 parent d4793d3 commit 146e4d3

File tree

5 files changed

+259
-82
lines changed

5 files changed

+259
-82
lines changed

lib/app/router/unit_router.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// ignore_for_file: constant_identifier_names
22

3+
import 'dart:io';
4+
35
import 'package:app_config/app_config.dart';
46
import 'package:flutter/material.dart';
57
import 'package:flutter_unit/app/views/about/about_app_page.dart';
@@ -29,7 +31,7 @@ class UnitRouters {
2931

3032
static const String detail = 'detail';
3133
static const String search = 'search_bloc';
32-
static const String nav = 'nav';
34+
3335

3436
static const String collect = 'CollectPage';
3537
static const String point = 'IssuesPointPage';
@@ -58,7 +60,10 @@ class UnitRouters {
5860
static Route<dynamic> generateRoute(RouteSettings settings) {
5961
switch (settings.name) {
6062
//
61-
case nav:
63+
case UnitRouter.nav:
64+
if(Platform.isWindows||Platform.isMacOS||Platform.isLinux){
65+
return NoAnimRouter(child: UnitNavigation());
66+
}
6267
return Left2RightRouter(child: UnitNavigation());
6368

6469
// 组件详情页
Lines changed: 147 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,159 @@
1+
import 'dart:async';
2+
3+
import 'package:app_config/app_config.dart';
4+
import 'package:db_storage/db_storage.dart';
15
import 'package:flutter/material.dart';
6+
import 'package:flutter_bloc/flutter_bloc.dart';
7+
import 'package:widget_module/blocs/blocs.dart';
8+
import 'package:widget_repository/widget_repository.dart';
29

3-
class DeskSearchBar extends StatelessWidget {
10+
class DeskSearchBar extends StatefulWidget {
411
final ValueChanged<String>? onChanged;
512

13+
const DeskSearchBar({Key? key, this.onChanged}) : super(key: key);
14+
15+
@override
16+
State<DeskSearchBar> createState() => _DeskSearchBarState();
17+
}
618

7-
const DeskSearchBar({Key? key,this.onChanged}) : super(key: key);
19+
class _DeskSearchBarState extends State<DeskSearchBar> {
20+
late TextEditingController _controller;
821

922
@override
1023
Widget build(BuildContext context) {
24+
return Autocomplete<WidgetModel>(
25+
optionsBuilder: buildOptions,
26+
onSelected: onSelected,
27+
optionsViewBuilder: _buildOptionsView,
28+
fieldViewBuilder: _buildFieldView,
29+
);
30+
31+
}
32+
33+
void onSelected(WidgetModel model) {
34+
}
35+
36+
Future<Iterable<WidgetModel>> buildOptions(TextEditingValue textEditingValue) async {
37+
if (textEditingValue.text == '') {
38+
return const Iterable<WidgetModel>.empty();
39+
}
40+
return searchByArgs(textEditingValue.text);
41+
42+
}
43+
44+
Future<Iterable<WidgetModel>> searchByArgs(String text) {
45+
WidgetRepository repository = context.read<WidgetsBloc>().repository;
46+
return repository.searchWidgets(WidgetFilter(
47+
name: text
48+
));
49+
50+
}
51+
52+
Widget _buildOptionsView(BuildContext context, AutocompleteOnSelected<WidgetModel> onSelected, Iterable<WidgetModel> options) {
53+
return Align(
54+
alignment: Alignment.topLeft,
55+
child: Material(
56+
color: Colors.white,
57+
elevation: 6,
58+
borderRadius: BorderRadius.circular(8),
59+
shadowColor: Colors.black,
60+
child: ConstrainedBox(
61+
constraints: BoxConstraints(maxHeight: 350,maxWidth: 250),
62+
child:ListView.builder(
63+
itemCount:options.length ,
64+
padding: EdgeInsets.symmetric(vertical: 10),
65+
itemBuilder: (_,index) {
66+
WidgetModel model = options.elementAt(index);
67+
return InkWell(
68+
onTap: ()=>_toDetaile(model),
69+
child: Ink(
70+
padding: EdgeInsets.symmetric(vertical: 6, horizontal: 15),
71+
child: Row(children: [
72+
Expanded(child: Text.rich(formSpan(model.name,_controller.text),maxLines:1,
73+
overflow: TextOverflow.ellipsis,
74+
style: TextStyle(fontSize: 12))),
75+
// Spacer(),
76+
const SizedBox(width: 10,),
77+
Text(model.nameCN,style: TextStyle(fontSize: 12),),
78+
],),
79+
),
80+
);
81+
}),
82+
),
83+
),
84+
);
85+
}
86+
87+
Widget _buildFieldView(BuildContext context, TextEditingController textEditingController, FocusNode focusNode, VoidCallback onFieldSubmitted) {
88+
_controller = textEditingController;
1189
return TextField(
12-
// controller: _ctrl,
13-
onChanged: onChanged,
14-
style: const TextStyle(fontSize: 12),
15-
maxLines: 1,
16-
decoration: const InputDecoration(
17-
filled: true,
18-
hoverColor: Colors.transparent,
19-
contentPadding: EdgeInsets.only(top: 0),
20-
fillColor: Color(0xffF1F2F3),
21-
prefixIcon: Icon(Icons.search, size: 18,color: Colors.grey,),
22-
border: UnderlineInputBorder(
23-
borderSide: BorderSide.none,
24-
borderRadius: BorderRadius.all(Radius.circular(8)),
25-
),
26-
hintText: "输入组件名称",
27-
hintStyle: TextStyle(fontSize: 12,color: Colors.grey)),
90+
controller: textEditingController,
91+
onChanged: widget.onChanged,
92+
style: const TextStyle(fontSize: 12),
93+
maxLines: 1,
94+
focusNode: focusNode,
95+
decoration: InputDecoration(
96+
prefixIconConstraints: BoxConstraints(
97+
minWidth: 30,
98+
),
99+
filled: true,
100+
hoverColor: Colors.transparent,
101+
contentPadding: EdgeInsets.only(top: 0),
102+
fillColor: Color(0xffF1F2F3),
103+
prefixIcon: Icon(
104+
Icons.search,
105+
size: 18,
106+
color: Colors.grey,
107+
),
108+
focusedBorder: OutlineInputBorder(
109+
110+
borderSide: BorderSide(color: Theme.of(context).primaryColor),
111+
borderRadius: BorderRadius.all(Radius.circular(8)),
112+
),
113+
114+
enabledBorder : OutlineInputBorder(
115+
116+
borderSide: BorderSide.none,
117+
borderRadius: BorderRadius.all(Radius.circular(8)),
118+
),
119+
hintText: "输入组件名称",
120+
hintStyle: TextStyle(fontSize: 12, color: Colors.grey)),
121+
);
122+
123+
}
124+
125+
final TextStyle lightTextStyle = const TextStyle(
126+
color: Colors.red,
127+
fontSize: 12,
128+
fontWeight: FontWeight.bold,
129+
);
130+
131+
InlineSpan formSpan(String src, String pattern) {
132+
List<TextSpan> span = [];
133+
RegExp regExp = RegExp(pattern, caseSensitive: false);
134+
src.splitMapJoin(regExp, onMatch: (Match match) {
135+
span.add(TextSpan(text: match.group(0), style: lightTextStyle));
136+
return '';
137+
}, onNonMatch: (str) {
138+
span.add(TextSpan(
139+
text: str,
140+
style: lightTextStyle.copyWith(color: const Color(0xff2F3032),fontSize: 12)));
141+
return '';
142+
});
143+
return TextSpan(children: span);
144+
}
145+
146+
void _toDetaile(WidgetModel model) {
147+
final FocusScopeNode focusScope = FocusScope.of(context);
148+
if (focusScope.hasFocus) {
149+
focusScope.unfocus();
150+
}
151+
_controller.clear();
152+
153+
Navigator.pushNamed(
154+
context,
155+
UnitRouter.widget_detail,
156+
arguments: model,
28157
);
29158
}
30159
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_unit/app/plateform_adapter/window/windows_adapter.dart';
3+
import 'package:flutter_unit/components/permanent/decorations/round_rect_rab_indicator.dart';
4+
import 'package:flutter_unit/widget_system/views/desk_ui/widget_panel/window_buttons.dart';
5+
6+
import 'desk_search_bar.dart';
7+
8+
class DeskWidgetTopBar extends StatefulWidget {
9+
final ValueChanged<int> onTabPressed;
10+
11+
const DeskWidgetTopBar({Key? key,required this.onTabPressed}) : super(key: key);
12+
13+
@override
14+
State<DeskWidgetTopBar> createState() => _DeskWidgetTopBarState();
15+
}
16+
17+
class _DeskWidgetTopBarState extends State<DeskWidgetTopBar> with SingleTickerProviderStateMixin {
18+
late TabController tabController;
19+
static const List<String> _tabs = ['无态', '有态', '单渲', '多渲', '滑片', '代理', '其它'];
20+
21+
@override
22+
void initState() {
23+
// TODO: implement initState
24+
super.initState();
25+
tabController = TabController(length: _tabs.length, vsync: this);
26+
}
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
Color themeColor = Theme.of(context).primaryColor;
31+
32+
return DragToMoveAreaNoDouble(
33+
child: Container(
34+
padding: const EdgeInsets.symmetric(horizontal: 20),
35+
height: 64,
36+
color: Colors.white,
37+
child: Row(
38+
children: [
39+
SizedBox(
40+
width: 350,
41+
child: TabBar(
42+
onTap: widget.onTabPressed,
43+
indicatorSize: TabBarIndicatorSize.label,
44+
labelPadding: const EdgeInsets.symmetric(horizontal: 6),
45+
isScrollable: false,
46+
indicator: RoundRectTabIndicator(
47+
borderSide: BorderSide(color: themeColor, width: 3),
48+
),
49+
labelStyle: const TextStyle(
50+
fontSize: 14,
51+
fontWeight: FontWeight.bold,
52+
),
53+
controller: tabController,
54+
labelColor: themeColor,
55+
indicatorWeight: 3,
56+
unselectedLabelColor: Colors.grey,
57+
indicatorColor: themeColor,
58+
tabs:
59+
_tabs.map((String name) => Tab(text: name)).toList(),
60+
),
61+
),
62+
Spacer(),
63+
Padding(
64+
padding: const EdgeInsets.symmetric(horizontal: 8.0),
65+
child: SizedBox(
66+
width: 250, height: 30, child: DeskSearchBar(
67+
68+
)),
69+
),
70+
// const SizedBox(width: 20,),
71+
WindowButtons(),
72+
],
73+
),
74+
),
75+
);
76+
}
77+
}

0 commit comments

Comments
 (0)