Last active
August 29, 2015 14:20
-
-
Save kjeremy/5cb27c19787789e0b1db to your computer and use it in GitHub Desktop.
Adapter for SearchView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class SearchFilterAdapterBase : MvxAdapter, IFilterable | |
{ | |
protected SearchFilterAdapterBase(Context context) | |
: base(context) {} | |
protected SearchFilterAdapterBase(Context context, IMvxAndroidBindingContext bindingContext) | |
: base(context, bindingContext) {} | |
protected abstract Filter CreateFilter(); | |
private Filter _filter; | |
public Filter Filter | |
{ | |
get { return this._filter ?? (this._filter = this.CreateFilter()); } | |
} | |
private readonly object _lock = new object(); | |
public object Lock | |
{ | |
get { return this._lock; } | |
} | |
[MvxSetToNullAfterBinding] | |
public IEnumerable FilteredSubset { get; set; } | |
protected override void SetItemsSource(IEnumerable value) | |
{ | |
lock (this.Lock) | |
{ | |
this.FilteredSubset = null; | |
base.SetItemsSource(value); | |
} | |
} | |
public override int GetPosition(object item) | |
{ | |
lock (this.Lock) | |
{ | |
IEnumerable source = this.FilteredSubset ?? ItemsSource; | |
return MvxEnumerableExtensions.GetPosition(source, item); | |
} | |
} | |
public override object GetRawItem(int position) | |
{ | |
lock (this.Lock) | |
{ | |
IEnumerable source = this.FilteredSubset ?? ItemsSource; | |
return MvxEnumerableExtensions.ElementAt(source, position); | |
} | |
} | |
public override View GetView(int position, View convertView, ViewGroup parent) | |
{ | |
lock (this.Lock) | |
{ | |
return base.GetView(position, convertView, parent); | |
} | |
} | |
public override int Count | |
{ | |
get | |
{ | |
lock (this.Lock) | |
{ | |
return MvxEnumerableExtensions.Count(this.FilteredSubset ?? ItemsSource); | |
} | |
} | |
} | |
} | |
public class SearchFilter<T> : Filter | |
{ | |
private readonly SearchFilterAdapterBase _adapter; | |
public SearchFilter(SearchFilterAdapterBase adapter) | |
{ | |
this._adapter = adapter; | |
} | |
public Func<T, string, bool> SearchFunc { get; set; } | |
protected override FilterResults PerformFiltering(ICharSequence constraint) | |
{ | |
// If there is no constraint return the original data set | |
var returnObject = new FilterResults(); | |
if (constraint == null || constraint.Length() == 0) | |
return returnObject; | |
var results = new List<T>(); | |
try | |
{ | |
lock (this._adapter.Lock) | |
{ | |
if (this._adapter.ItemsSource.Count() > 0) | |
{ | |
IEnumerable<T> source = this._adapter.ItemsSource as IEnumerable<T>; | |
if (source == null) | |
return returnObject; | |
string c = constraint.ToString(); | |
results.AddRange(source.Where(o => this.SearchFunc(o, c))); | |
returnObject.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray()); | |
returnObject.Count = results.Count; | |
} | |
} | |
} | |
catch (System.Exception ex) | |
{ | |
throw; | |
var table = new Dictionary<string, string>(); | |
try | |
{ | |
table.Add("constraint handle", constraint.Handle.ToString()); | |
if (constraint.Handle != IntPtr.Zero) | |
table.Add("constraint", constraint.ToString()); | |
} | |
catch (System.Exception) | |
{ | |
// Swallow | |
} | |
finally | |
{ | |
Mvx.Resolve<IAppInsights>().Report(ex, table, ReportSeverity.Error); | |
} | |
throw; | |
} | |
finally | |
{ | |
// Without the dispose GREFs go up, but maybe it contributes to the | |
// Java GC destroying constraint before we're done using it. | |
//constraint.Dispose(); | |
} | |
return returnObject; | |
} | |
protected override void PublishResults(ICharSequence constraint, FilterResults results) | |
{ | |
lock (this._adapter.Lock) | |
{ | |
// Use the original data set if there is no constraint | |
if (this._adapter.ItemsSource.Count() == 0 || constraint == null || constraint.Length() == 0) | |
{ | |
// When there is nothing in the items source make sure | |
// the filter is null. | |
this._adapter.FilteredSubset = null; | |
this._adapter.NotifyDataSetInvalidated(); | |
} | |
else | |
{ | |
using (var values = results.Values) | |
{ | |
this._adapter.FilteredSubset = values.ToArray<Java.Lang.Object>() | |
.Select(r => r.ToNetObject<T>()).ToList(); | |
} | |
} | |
this._adapter.NotifyDataSetChanged(); | |
} | |
//constraint.Dispose(); | |
//results.Dispose(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public override void OnCreateOptionsMenu(IMenu menu, MenuInflater inflater) | |
{ | |
// The view pager sets this hint (through our parent fragment) so we need | |
// to figure out if the menu items are visible or not. | |
if (!UserVisibleHint) | |
return; | |
base.OnCreateOptionsMenu(menu, inflater); | |
inflater.Inflate(Resource.Menu.ListMenu, menu); | |
var searchMenu = menu.FindItem(Resource.Id.action_search); | |
this._searchView = MenuItemCompat.GetActionView(searchMenu).JavaCast<SearchView>(); | |
this._searchView.QueryHint = "Search for assets."; | |
this._searchView.LayoutParameters = new ActionBar.LayoutParams(GravityFlags.Right); | |
this._searchView.QueryTextChange += (s, e) => { ViewModel.Constraint = e.NewText; }; | |
this._searchView.QueryTextSubmit += (s, e) => { e.Handled = true; }; | |
MenuItemCompat.SetOnActionExpandListener(searchMenu, new SearchViewExpandListener(this._adapter)); | |
} | |
public string SearchTerm | |
{ | |
get { return ViewModel.Constraint; /* just to make the compiler happy */ } | |
set | |
{ | |
// Do not use string variant. | |
// See: https://bugzilla.xamarin.com/show_bug.cgi?id=25995 | |
this._adapter.Filter.InvokeFilter(new Java.Lang.String(ViewModel.Constraint)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment