|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public abstract class SearchDelegate<T> { |
|
|
|
public SearchDelegate( |
|
|
|
string searchFieldLabel = null, |
|
|
|
TextInputType keyboardType = null, |
|
|
|
TextInputAction textInputAction = TextInputAction.search |
|
|
|
) { |
|
|
|
this.searchFieldLabel = searchFieldLabel; |
|
|
|
this.keyboardType = keyboardType; |
|
|
|
this.textInputAction = textInputAction; |
|
|
|
} |
|
|
|
public abstract Widget buildSuggestions(BuildContext context); |
|
|
|
public abstract Widget buildResults(BuildContext context); |
|
|
|
public abstract Widget buildLeading(BuildContext context); |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public virtual void showResults(BuildContext context) { |
|
|
|
_focusNode.unfocus(); |
|
|
|
_focusNode?.unfocus(); |
|
|
|
FocusScope.of(context).requestFocus(_focusNode); |
|
|
|
D.assert(_focusNode != null, () => "_focusNode must be set by route before showSuggestions is called."); |
|
|
|
_focusNode.requestFocus(); |
|
|
|
_focusNode.unfocus(); |
|
|
|
_focusNode?.unfocus(); |
|
|
|
public readonly string searchFieldLabel; |
|
|
|
public readonly TextInputType keyboardType; |
|
|
|
|
|
|
|
public readonly TextInputAction textInputAction; |
|
|
|
|
|
|
|
readonly internal FocusNode _focusNode = new FocusNode(); |
|
|
|
internal FocusNode _focusNode; |
|
|
|
|
|
|
|
readonly internal TextEditingController _queryTextController = new TextEditingController(); |
|
|
|
|
|
|
|
|
|
|
public override Color barrierColor { |
|
|
|
get { return null; } |
|
|
|
} |
|
|
|
|
|
|
|
public override string barrierLabel => null; |
|
|
|
|
|
|
|
public override TimeSpan transitionDuration { |
|
|
|
get { return new TimeSpan(0, 0, 0, 0, 300); } |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
class _SearchPageState<T> : State<_SearchPage<T>> { |
|
|
|
|
|
|
|
FocusNode focusNode = new FocusNode(); |
|
|
|
queryTextController.addListener(_onQueryChanged); |
|
|
|
widget.del._queryTextController.addListener(_onQueryChanged); |
|
|
|
widget.del._focusNode.addListener(_onFocusChanged); |
|
|
|
focusNode.addListener(_onFocusChanged); |
|
|
|
widget.del._focusNode = focusNode; |
|
|
|
queryTextController.removeListener(_onQueryChanged); |
|
|
|
widget.del._queryTextController.removeListener(_onQueryChanged); |
|
|
|
widget.del._focusNode.removeListener(_onFocusChanged); |
|
|
|
widget.del._focusNode = null; |
|
|
|
focusNode.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
void _onAnimationStatusChanged(AnimationStatus status) { |
|
|
|
|
|
|
|
|
|
|
widget.animation.removeStatusListener(_onAnimationStatusChanged); |
|
|
|
if (widget.del._currentBody == _SearchBody.suggestions) { |
|
|
|
FocusScope.of(context).requestFocus(widget.del._focusNode); |
|
|
|
focusNode.requestFocus(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|
|
|
var _oldWidget = (_SearchPage<T>) oldWidget; |
|
|
|
base.didUpdateWidget(oldWidget); |
|
|
|
if (widget.del != _oldWidget.del) { |
|
|
|
_oldWidget.del._queryTextController.removeListener(_onQueryChanged); |
|
|
|
widget.del._queryTextController.addListener(_onQueryChanged); |
|
|
|
_oldWidget.del._currentBodyNotifier.removeListener(_onSearchBodyChanged); |
|
|
|
widget.del._currentBodyNotifier.addListener(_onSearchBodyChanged); |
|
|
|
_oldWidget.del._focusNode = null; |
|
|
|
widget.del._focusNode = focusNode; |
|
|
|
if (widget.del._focusNode.hasFocus && widget.del._currentBody != _SearchBody.suggestions) { |
|
|
|
if (focusNode.hasFocus && widget.del._currentBody != _SearchBody.suggestions) { |
|
|
|
widget.del.showSuggestions(context); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
material_.debugCheckHasMaterialLocalizations(context); |
|
|
|
|
|
|
|
ThemeData theme = widget.del.appBarTheme(context); |
|
|
|
string searchFieldLabel = MaterialLocalizations.of(context).searchFieldLabel; |
|
|
|
string searchFieldLabel = widget.del.searchFieldLabel ?? MaterialLocalizations.of(context).searchFieldLabel; |
|
|
|
Widget body = null; |
|
|
|
switch (widget.del._currentBody) { |
|
|
|
case _SearchBody.suggestions: |
|
|
|
|
|
|
string routeName; |
|
|
|
switch (Theme.of(this.context).platform) { |
|
|
|
case RuntimePlatform.IPhonePlayer: |
|
|
|
case RuntimePlatform.OSXEditor: |
|
|
|
case RuntimePlatform.OSXPlayer: |
|
|
|
routeName = ""; |
|
|
|
break; |
|
|
|
case RuntimePlatform.Android: |
|
|
|
|
|
|
brightness: theme.primaryColorBrightness, |
|
|
|
leading: widget.del.buildLeading(context), |
|
|
|
title: new TextField( |
|
|
|
controller: queryTextController, |
|
|
|
focusNode: widget.del._focusNode, |
|
|
|
style: theme.textTheme.title, |
|
|
|
textInputAction: TextInputAction.search, |
|
|
|
controller: widget.del._queryTextController, |
|
|
|
focusNode: focusNode, |
|
|
|
style: theme.textTheme.headline6, |
|
|
|
textInputAction: widget.del.textInputAction, |
|
|
|
keyboardType: widget.del.keyboardType, |
|
|
|
hintText: searchFieldLabel |
|
|
|
hintText: searchFieldLabel, |
|
|
|
hintStyle: theme.inputDecorationTheme.hintStyle |
|
|
|
) |
|
|
|
), |
|
|
|
actions: widget.del.buildActions(context) |
|
|
|