Reputation: 2374
I got my view with SearchView component. The problem is every new symbol in the input field toggling Query
action, so there are some http
request are fire etc, so it starts to working slow.
I want it to run only after I click on search button on virtual keyboard (bellow button ).
Is there any properties for that in SearchView
?
layout code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
local:MvxBind="Query SearchString" />
</LinearLayout>
Or I should make something like custom binding which detects keyboard key click?
UPD:
Some code to make clear part of how search works:
View model
public class RemoteMusicSearchViewModel : MvxViewModel
{
private IMvxNavigationService _mvxNavigationService;
private IRemoteMusicDataService _remoteMusicDataService;
private int _currentPage;
public RemoteMusicSearchViewModel(IMvxNavigationService mvxNavigationService,
IRemoteMusicDataService remoteMusicDataService)
{
_mvxNavigationService = mvxNavigationService;
_remoteMusicDataService = remoteMusicDataService;
}
public override void Start()
{
base.Start();
_currentPage = 0;
}
private string _searchString;
public string SearchString
{
get { return _searchString; }
set
{
_searchString = value;
RaisePropertyChanged(() => SearchString);
PerformBasicSearch().ConfigureAwait(false);
}
}
private ObservableCollection<DownloadableEntity> _foundItems;
public ObservableCollection<DownloadableEntity> FoundItems
{
get { return _foundItems; }
set
{
if (_currentPage > 0)
{
_foundItems = new ObservableCollection<DownloadableEntity>(_foundItems.Concat(value));
}
else
{
_foundItems = value;
}
RaisePropertyChanged(() => FoundItems);
}
}
private async Task PerformBasicSearch(int page = 0)
{
string request = SearchString;
string result = await _remoteMusicDataService.SearchByProperty(request, MusicSearchType.ByTracks, page).ConfigureAwait(false);
var searchResult = MusicSearchResult.FromJson(result);
await PrepareDataForOutput(searchResult).ConfigureAwait(false);
}
}
full layout code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
local:MvxBind="Query SearchString"
/>
<MvvmCross.Binding.Droid.Views.MvxListView
android:id="@+id/searchlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
local:MvxBind="ItemsSource FoundItems"
local:MvxItemTemplate="@layout/listitem"/>
</LinearLayout>
Upvotes: 0
Views: 585
Reputation: 2374
I found the solution - I just created new binding for that:
public class SearchViewKeyPressEventsBinding : MvxAndroidTargetBinding
{
private readonly SearchView _searchView;
private IMvxAsyncCommand _command;
public SearchViewKeyPressEventsBinding(SearchView searchView) : base(searchView)
{
_searchView = searchView;
_searchView.QueryTextSubmit += _searchView_KeyPress;
}
private void _searchView_KeyPress(object sender, SearchView.QueryTextSubmitEventArgs e)
{
try
{
if (_command != null)
{
_command.ExecuteAsync();
}
}
catch (Exception ex)
{
throw ex;
}
}
public override Type TargetType
{
get { return typeof(IMvxAsyncCommand); }
}
protected override void SetValueImpl(object target, object value)
{
try
{
_command = (IMvxAsyncCommand)value;
}
catch (Exception e)
{
Log.Error("SOME BINDER FAIL\n\t" + e.Message + "\n", "SOME BINDER FAIL\n\t" + e.Message + "\n");
throw;
}
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_searchView.QueryTextSubmit -= _searchView_KeyPress;
}
base.Dispose(isDisposing);
}
}
}
Then registred it and it worked:
registry.RegisterFactory(new MvxCustomBindingFactory<SearchView>("OnSearchSubmit", (sv) => new SearchViewKeyPressEventsBinding(sv)))
In layout:
<SearchView
android:id="@+id/search10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
local:MvxBind="Query SearchString; OnSearchSubmit OnSubmitPressCommand" />
And don't forget to set up viewmodel's property:
public IMvxAsyncCommand OnSubmitPressCommand
{
get
{
return new MvxAsyncCommand(OnSearchSubmit);
}
}
private async Task OnSearchSubmit()
{
//HideKeyboardOnSearchStart.Invoke(this, null);
await PerformBasicSearch().ConfigureAwait(false);
}
Upvotes: 0
Reputation: 3263
I am guessing you are looking for a manual solution for the problem.
With each key event you get you can fire a delayed action after a certain threshold 500 milliseconds for example.
Maybe using Handler.postDelayed()
Then there three scenarios
Handler.removeCallbacks()
and fire another delayed actionHowever, if you are willing to use any Reactive variant, there are more sophisticated solutions for that, by basically debouncing the events of keyboard strokes.
Upvotes: 1