2017-08-29 63 views

回答

1

我寫了一個關於如何實現此功能的簡單演示,效果如this。你可以在這個GitHub Repository看到它。

  1. 設置了搜索查看

在文件夾res/menu創建一個名爲main.xml新文件。在其中添加一個項目並將actionViewClass設置爲android.support.v7.widget.SearchView。由於您使用的是支持庫,因此必須使用支持庫的名稱空間來設置actionViewClass屬性。你main.xml文件應該是這個樣子:

<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto"> 
    <item android:id="@+id/action_search" 
     android:title="Search" 
     android:icon="@android:drawable/ic_menu_search" 
     app:showAsAction="always|collapseActionView" 
     app:actionViewClass="android.support.v7.widget.SearchView" /> 
</menu> 

在你Activity你有誇大像往常這個菜單XML,那麼你可以看看其中包含SearchViewMenuItemQueryTextChange添加一個委託,我們正在準備用來監聽更改到文本輸入到SearchView

protected override void OnCreate(Bundle bundle) 
    { 
     base.OnCreate(bundle); 

     SetContentView(Resource.Layout.Main); 
     SupportActionBar.SetDisplayShowHomeEnabled(true); 

     var chemicals = new List<Chemical> 
     { 
      new Chemical {Name = "Niacin", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Biotin", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Chromichlorid", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Natriumselenit", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Manganosulfate", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Natriummolybdate", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Ergocalciferol", DrawableId = Resource.Drawable.Icon}, 
      new Chemical {Name = "Cyanocobalamin", DrawableId = Resource.Drawable.Icon}, 
     }; 

     _recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView); 
     _adapter = new RecyclerViewAdapter(this,chemicals); 
     _LayoutManager = new LinearLayoutManager(this); 
     _recyclerView.SetLayoutManager(_LayoutManager); 
     _recyclerView.SetAdapter(_adapter);// 
    } 

public override bool OnCreateOptionsMenu(IMenu menu) 
{ 
    MenuInflater.Inflate(Resource.Menu.main, menu); 

    var item = menu.FindItem(Resource.Id.action_search); 
    var searchView = MenuItemCompat.GetActionView(item); 
    _searchView = searchView.JavaCast<Android.Support.V7.Widget.SearchView>(); 

    _searchView.QueryTextChange += (s, e) => _adapter.Filter.InvokeFilter(e.NewText); 

    _searchView.QueryTextSubmit += (s, e) => 
    { 
     // Handle enter/search button on keyboard here 
     Toast.MakeText(this, "Searched for: " + e.Query, ToastLength.Short).Show(); 
     e.Handled = true; 
    }; 

    MenuItemCompat.SetOnActionExpandListener(item, new SearchViewExpandListener(_adapter)); 

    return true; 
} 

private class SearchViewExpandListener : Java.Lang.Object, MenuItemCompat.IOnActionExpandListener 
{ 
    private readonly IFilterable _adapter; 

    public SearchViewExpandListener(IFilterable adapter) 
    { 
     _adapter = adapter; 
    } 

    public bool OnMenuItemActionCollapse(IMenuItem item) 
    { 
     _adapter.Filter.InvokeFilter(""); 
     return true; 
    } 

    public bool OnMenuItemActionExpand(IMenuItem item) 
    { 
     return true; 
    } 
} 
  • 要使用一個Java類型包.NET類型
  • 您必須實現自己的Filter,因爲自定義適配器的本質是您呈現自定義內容。因此默認的Filter實現無法知道如何過濾。

    正如Cheesebaron所說,FilterResult用於臨時存儲過濾值,預計存儲的對象是Java類型。因此,無論您的模型如何填寫您的Adapte r必須實施Java.Lang.Object或者您將不得不包裝您的值。我將向您展示後者,因爲它將適用於更多的使用案例,因爲您可能無法也可能不希望在您的合同中實施Java.Lang.Object,或者您正在使用什麼來存儲數據,尤其是當您正在通信和共享代碼時平臺之間。

    爲了結束.NET類型的我使用修改後的代碼從該monodroid mailing list thread一個Java類型,它看起來像這樣:

    public class JavaHolder : Java.Lang.Object 
    { 
        public readonly object Instance; 
    
        public JavaHolder(object instance) 
        { 
         Instance = instance; 
        } 
    } 
    
    public static class ObjectExtensions 
    { 
        public static TObject ToNetObject<TObject>(this Java.Lang.Object value) 
        { 
         if (value == null) 
          return default(TObject); 
    
         if (!(value is JavaHolder)) 
          throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted."); 
    
         TObject returnVal; 
         try { returnVal = (TObject)((JavaHolder)value).Instance; } 
         finally { value.Dispose(); } 
         return returnVal; 
        } 
    
        public static Java.Lang.Object ToJavaObject<TObject>(this TObject value) 
        { 
         if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType) 
          return null; 
    
         var holder = new JavaHolder(value); 
    
         return holder; 
        } 
    } 
    

    的主要區別是,在Java保持器對象被銷燬的立即當它是轉換爲.NET對象。此外,原始來源中的比較,值是否爲空是不安全的,因爲它不考慮價值類型。對象處置對於保持GREF引用最小化非常有用。我真的不希望應用程序在內存上運行得很高。

  • 濾波定製適配器
  • Adapter看起來像這樣:

    public class RecyclerViewAdapter : RecyclerView.Adapter, IFilterable 
    { 
        private List<Chemical> _originalData; 
        private List<Chemical> _items; 
        private readonly Activity _context; 
    
        public Filter Filter { get; private set; } 
    
        public RecyclerViewAdapter(Activity activity, IEnumerable<Chemical> chemicals) 
        { 
         _items = chemicals.OrderBy(s => s.Name).ToList(); 
         _context = activity; 
    
         Filter = new ChemicalFilter(this); 
        } 
    
        public override long GetItemId(int position) 
        { 
         return position; 
        } 
    
    
        public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) 
        { 
         View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.Chemical, parent, false); 
         ChemicalHolder vh = new ChemicalHolder(itemView); 
         return vh; 
        } 
    
        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) 
        { 
         ChemicalHolder vh = holder as ChemicalHolder; 
    
         var chemical = _items[position]; 
    
         vh.Image.SetImageResource(chemical.DrawableId); 
         vh.Caption.Text = chemical.Name; 
        } 
    
        public override int ItemCount 
        { 
         get { return _items.Count; } 
        } 
    
        public class ChemicalHolder : RecyclerView.ViewHolder 
        { 
         public ImageView Image { get; private set; } 
         public TextView Caption { get; private set; } 
    
         public ChemicalHolder(View itemView) : base(itemView) 
         { 
          Image = itemView.FindViewById<ImageView>(Resource.Id.chemImage); 
          Caption = itemView.FindViewById<TextView>(Resource.Id.chemName); 
         } 
        } 
    
        private class ChemicalFilter : Filter 
        { 
         private readonly RecyclerViewAdapter _adapter; 
         public ChemicalFilter(RecyclerViewAdapter adapter) 
         { 
          _adapter = adapter; 
         } 
    
         protected override FilterResults PerformFiltering(ICharSequence constraint) 
         { 
          var returnObj = new FilterResults(); 
          var results = new List<Chemical>(); 
          if (_adapter._originalData == null) 
           _adapter._originalData = _adapter._items; 
    
          if (constraint == null) return returnObj; 
    
          if (_adapter._originalData != null && _adapter._originalData.Any()) 
          { 
           // Compare constraint to all names lowercased. 
           // It they are contained they are added to results. 
           results.AddRange(
            _adapter._originalData.Where(
             chemical => chemical.Name.ToLower().Contains(constraint.ToString()))); 
          } 
    
          // Nasty piece of .NET to Java wrapping, be careful with this! 
          returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray()); 
          returnObj.Count = results.Count; 
    
          constraint.Dispose(); 
    
          return returnObj; 
         } 
    
         protected override void PublishResults(ICharSequence constraint, FilterResults results) 
         { 
          using (var values = results.Values) 
           _adapter._items = values.ToArray<Java.Lang.Object>() 
            .Select(r => r.ToNetObject<Chemical>()).ToList(); 
    
          _adapter.NotifyDataSetChanged(); 
    
          // Don't do this and see GREF counts rising 
          constraint.Dispose(); 
          results.Dispose(); 
         } 
        } 
    } 
    
    +1

    @Divya,你解決了你的問題? –

    +0

    我必須在Google Map上使用Actiobar的SearchView實現搜索..約克如何使ActionBarSearchView自動完成? – Divya

    +0

    約克它應該是這樣的http://www.appliedcodelog.com/2015/05/google-place-api-with-autocomplete-in.html,但它應該與ActionBar SearchView不與自動完成TextView – Divya

    相關問題