How to add search bar in navigation bar in Xamarin forms

gdkgdk INMember ✭✭✭

Hi every one, I am try to add search bar in navigation bar in both Xamarin.android and Xamarin.Ios. I have tried the below post it not working in above 'nougat' versions. Please suggest any idea how to add search bar in both android and Ios.'

I am tried link : https://www.linkedin.com/pulse/xamarin-forms-contentpage-searchbar-navigation-bar-vipin-mathews

I have tried above code but doesn't work in above nougat version's in android.

Answers

  • DarshanJSDarshanJS USMember ✭✭✭✭

    @gdk said:

    see this video it may help you

  • gdkgdk INMember ✭✭✭

    Thanks Darshan. I want search bar in navigation bar, it seems that in below the navigation bar.

  • SebastianKruseSebastianKruse USMember ✭✭✭

    I'm searching for this too (iOS + Android). The video is a joke, isn't it? cO How to add a search bar inside the content should not be a question for any serious developer..

  • BrandonMinnickBrandonMinnick USXamarin Team Xamurai
    edited August 13

    Here's a sample application for reference:
    https://github.com/brminnick/GitTrends

    And here's a blog post that shows how to add a search bar to a Xamarin.Forms app for both Xamarin.iOS & Xamarin.Android: https://www.codetraveler.io/2019/08/10/adding-a-search-bar-to-xamarin-forms-navigationpage/

    App.cs

    Use a Xamarin.Forms Platform-Specific to use LargeTitles on the Xamarin.iOS app.

    using Xamarin.Forms.PlatformConfiguration;
    using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
    
    public class App : Xamarin.Forms.Application
    {
        public App()
        {
            var navigationPage = new Xamarin.Forms.NavigationPage(new MyContentPage());
    
            navigationPage.On<iOS>().SetPrefersLargeTitles(true);
    
            MainPage = navigationPage;
        }
    }
    

    ISearchPage Interface

    Create an Interface that can be used across the Xamarin.Forms, Xamarin.Android and Xamarin.iOS projects.

    public interface ISearchPage
    {
        void OnSearchBarTextChanged(in string text);
        event EventHandler<string> SearchBarTextChanged;
    }
    

    Xamarin.Forms Page

    public class MyContentPage : ContentPage, ISearchPage
    {
        public MyContentPage()
        {
            SearchBarTextChanged += HandleSearchBarTextChanged
        }
    
        public event EventHandler<string> SearchBarTextChanged;
    
        public void OnSearchBarTextChanged(in string text) => SearchBarTextChanged?.Invoke(this, text);
    
        void HandleSearchBarTextChanged(object sender, string searchBarText)
        {
            //Logic to handle updated search bar text
        }     
    }
    

    iOS Custom Renderer

    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UIKit;
    using MyNamespace;
    using MyNamespace.iOS;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: ExportRenderer(typeof(MyContentPage), typeof(SearchPageRenderer))]
    namespace MyNamespace.iOS
    {
        public class SearchPageRenderer : PageRenderer, IUISearchResultsUpdating
        {
            bool _isFirstAppearing = true;
    
            public override void WillMoveToParentViewController(UIViewController parent)
            {
                base.WillMoveToParentViewController(parent);
    
                var searchController = new UISearchController(searchResultsController: null)
                {
                    SearchResultsUpdater = this,
                    DimsBackgroundDuringPresentation = false,
                    HidesNavigationBarDuringPresentation = false,
                    HidesBottomBarWhenPushed = true
                };
                searchController.SearchBar.Placeholder = string.Empty;
    
                parent.NavigationItem.SearchController = searchController;
    
                DefinesPresentationContext = true;
            }
    
            public override void ViewDidAppear(bool animated)
            {
                base.ViewDidAppear(animated);
    
                //Work-around to ensure the SearchController appears when the page first appears https://stackoverflow.com/a/46313164/5953643
                if (_isFirstAppearing)
                {
                    ParentViewController.NavigationItem.SearchController.Active = true;
                    ParentViewController.NavigationItem.SearchController.Active = false;
    
                    _isFirstAppearing = false;
                }
            }
    
            public void UpdateSearchResultsForSearchController(UISearchController searchController)
            {
                if (Element is ISearchPage searchPage)
                    searchPage.OnSearchBarTextChanged(searchController.SearchBar.Text);
            }
        }
    }
    

    Xamarin.Android Menu XML

    1. In the Xamarin.Android project, in the Resources folder, create a new folder called menu (if one doesn't already exist).

      • Note: the folder, menu, has a lowercase 'm'
    2. In the Resources > menu folder, create a new file called MainMenu.xml.

    1. Open Resources > menu > MainMenu.xml

    2. In MainMenu.xml add the following code:

    <?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/ActionSearch"
            android:title="Filter"
            android:icon="@android:drawable/ic_menu_search"
            app:showAsAction="always|collapseActionView"
            app:actionViewClass="android.support.v7.widget.SearchView"/>
    </menu>
    

    Xamarin.Android CustomRenderer

    Uses the Plugin.CurrentActivity NuGet Package.

    using Android.Content;
    using Android.Runtime;
    using Android.Support.V7.Widget;
    using Android.Text;
    using Android.Views.InputMethods;
    using Plugin.CurrentActivity;
    using MyNamespace;
    using MyNamespace.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    
    [assembly: ExportRenderer(typeof(MyContentPage), typeof(SearchPageRenderer))]
    namespace MyNamespace.Droid
    {
        public class SearchPageRenderer : PageRenderer
        {
            public SearchPageRenderer(Context context) : base(context)
            {
    
            }
    
            protected override void OnAttachedToWindow()
            {
                base.OnAttachedToWindow();
    
                if (Application.Current.MainPage is NavigationPage navigationPage)
                    navigationPage.Popped += HandleNavigationPagePopped;
    
                if (Element is ISearchPage && Element is Page page)
                    AddSearchToToolbar(page);
            }
    
            protected override void Dispose(bool disposing)
            {
                if (GetToolbar() is Toolbar toolBar)
                    toolBar.Menu?.RemoveItem(Resource.Menu.MainMenu);
    
                base.Dispose(disposing);
            }
    
            void AddSearchToToolbar(in Page page)
            {
                if (GetToolbar() is Toolbar toolBar
                    && toolBar.Menu?.FindItem(Resource.Id.ActionSearch)?.ActionView?.JavaCast<SearchView>().GetType() != typeof(SearchView))
                {
                    toolBar.Title = page.Title;
                    toolBar.InflateMenu(Resource.Menu.MainMenu);
    
                    if (toolBar.Menu?.FindItem(Resource.Id.ActionSearch)?.ActionView?.JavaCast<SearchView>() is SearchView searchView)
                    {
                        searchView.QueryTextChange += HandleQueryTextChange;
                        searchView.ImeOptions = (int)ImeAction.Search;
                        searchView.InputType = (int)InputTypes.TextVariationNormal;
                        searchView.MaxWidth = int.MaxValue; //Set to full width - http://stackoverflow.com/questions/31456102/searchview-doesnt-expand-full-width
                    }
                }
            }
    
            void HandleQueryTextChange(object sender, SearchView.QueryTextChangeEventArgs e)
            {
                if (Element is ISearchPage searchPage)
                    searchPage.OnSearchBarTextChanged(e.NewText);
    
            }
    
            void HandleNavigationPagePopped(object sender, NavigationEventArgs e)
            {
                if (sender is NavigationPage navigationPage
                    && navigationPage.CurrentPage is ISearchPage)
                {
                    AddSearchToToolbar(navigationPage.CurrentPage);
                }
            }
    
            Toolbar GetToolbar() => CrossCurrentActivity.Current.Activity.FindViewById<Toolbar>(Resource.Id.toolbar);
        }
    }
    

    Sample App

    Here's a sample app for reference:
    https://github.com/brminnick/GitTrends

    And a blog post that shows how to add a search bar for both Xamarin.iOS and Xamarin.Android: https://www.codetraveler.io/2019/08/10/adding-a-search-bar-to-xamarin-forms-navigationpage/

    iOS Gif

Sign In or Register to comment.