• Xamarin.Forms 导航栏中添加带搜索组件


    在使用NavigationPage导航的时候, 我们可以给里面添加一些功能按钮, 如下所示:

        <ContentPage.ToolbarItems>
            <ToolbarItem/>
            <ToolbarItem/>
        </ContentPage.ToolbarItems>
    

    点击观看视频

    但是如果需要给这个控件添加一些其他的控件的时候, 则无法满足我们的需求, 这个时候, 我们就需要使用 页面渲染器(Page Renderer)。

    真机效果演示:

    实现思路:
    1.添加用于搜索通知的接口 : ISearchPage
    2.自定义搜索的渲染器 : SearchPageRender
    3.添加Menu/Item Xml文件: mainmenu.xml
    4.添加 Nuget:Plugin.CurrentActivity
    5.给需要添加搜索功能的页面实现 (1)的接口
    6.为自定义搜索渲染器添加支持该功能的页面
    7.启动项初始化 : CrossCurrentActivity.Current.Init(this, savedInstanceState)

    添加搜索通知接口

        public interface ISearchPage
        {
            void OnSearchBarTextChanged(string text);
        }
    

    自定义渲染器

    在Android项目中创建 CustomRender文件夹定义 SearchPageRender

    SearchPageRender代码

         public class SearchPageRender : PageRenderer
        {
            public SearchPageRender(Context context) : base(context)
            {
    
            }
    
            protected override void OnAttachedToWindow()
            {
                base.OnAttachedToWindow();
    
                if (Element is ISearchPage
                    && Element is Page page
                    && page.Parent is NavigationPage navigationPage)
                {
                    //Workaround to re-add the SearchView when navigating back to an ISearchPage, because Xamarin.Forms automatically removes it
                    navigationPage.Popped += HandleNavigationPagePopped;
                    navigationPage.PoppedToRoot += HandleNavigationPagePopped;
                }
            }
    
            //Adding the SearchBar in OnSizeChanged ensures the SearchBar is re-added after the device is rotated, because Xamarin.Forms automatically removes it
            protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
            {
                base.OnSizeChanged(w, h, oldw, oldh);
    
                if (Element is ISearchPage && Element is Page page && page.Parent is NavigationPage navigationPage && navigationPage.CurrentPage is ISearchPage)
                {
                    AddSearchToToolbar(page.Title);
                }
            }
    
            protected override void Dispose(bool disposing)
            {
                if (GetToolbar() is Android.Support.V7.Widget.Toolbar toolBar)
                    toolBar.Menu?.RemoveItem(Resource.Menu.mainmenu);
    
                base.Dispose(disposing);
            }
    
            //Workaround to re-add the SearchView when navigating back to an ISearchPage, because Xamarin.Forms automatically removes it
            void HandleNavigationPagePopped(object sender, NavigationEventArgs e)
            {
                if (sender is NavigationPage navigationPage
                    && navigationPage.CurrentPage is ISearchPage)
                {
                    AddSearchToToolbar(navigationPage.CurrentPage.Title);
                }
            }
    
            void AddSearchToToolbar(string pageTitle)
            {
                if (GetToolbar() is Android.Support.V7.Widget.Toolbar toolBar
                && toolBar.Menu?.FindItem(Resource.Id.action_search)?.ActionView?.
                JavaCast<Android.Support.V7.Widget.SearchView>().GetType()
                != typeof(Android.Support.V7.Widget.SearchView))
                {
                    toolBar.Title = pageTitle;
                    toolBar.InflateMenu(Resource.Menu.mainmenu);
    
                    if (toolBar.Menu?.FindItem(Resource.Id.action_search)?.ActionView?.
                        JavaCast<Android.Support.V7.Widget.SearchView>() is
                         Android.Support.V7.Widget.SearchView searchView)
                    {
                        searchView.QueryTextChange += SearchView_QueryTextChange;
                        searchView.ImeOptions = (int)ImeAction.Search;
                        searchView.InputType = (int)InputTypes.TextVariationFilter;
                        searchView.MaxWidth = int.MaxValue;
                    }
                }
            }
    
            private void SearchView_QueryTextChange(object sender, Android.Support.V7.Widget.SearchView.QueryTextChangeEventArgs e)
            {
                if (Element is ISearchPage searchPage)
                    searchPage.OnSearchBarTextChanged(e.NewText);
            }
    
            private static Android.Support.V7.Widget.Toolbar GetToolbar() => (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
        }
    

    添加Xml文件引用SearchView

    创建mainmenu.xml

    在Android的Resources文件夹中, 创建menu文件夹创建mainmenu.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>
    

    添加NuGet:Plugin.CurrentActivity

    在Android项目中, 添加NuGet包: Plugin.CurrentActivity , 并且在SearchPageRender 中引用它。

    页面实现接口 ISearchPage

    6.渲染器添加实现页

    如下图所示, 第一个typeof 指向的就是实现搜索内容页的Page

    MainActivity初始化

    在MainActivity的 OnCreate 中, 添加初始化的代码, 如下:

    以上步骤完整之后, 通过导航页打开的页面即可自带搜索功能。

  • 相关阅读:
    Java Gradle
    C/C++ C++11新特性
    C/C++ C++11原子类型和内存序
    基于流的编程(Flow-Based Programming)
    算法和数据结构 筛法求素数
    数据库 悲观锁和乐观锁
    数据库 事务隔离级别
    Serverless 的 AI 写诗,程序员浪漫起来谁能顶得住啊!
    亮点前瞻 | 首届 ServerlesssDays · China 大会议程发布
    腾讯云云函数 SCF Node.js Runtime 最佳实践
  • 原文地址:https://www.cnblogs.com/zh7791/p/12690118.html
Copyright © 2020-2023  润新知