【问题标题】:Xamarin Forms - ContentPage with SearchBar in the Navigation barXamarin 表单 - 导航栏中带有 SearchBar 的 ContentPage
【发布时间】:2018-05-11 07:30:38
【问题描述】:

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

我尝试实现上面的代码但没有成功,搜索图标没有进入页面,

在那之后我尝试了这个Adding a Search Bar in the toolbar of a navigationpage in Prism ,它会出现,但是一旦我更改方向或注销或单击其他页面并再次返回此页面,它就消失了

我从 git 下载了代码,但也无法运行。

<?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>

但是可绘制文件夹中没有ic_menu_search文件,这是个问题吗?

【问题讨论】:

  • 嘿,Avi,你有解决方案吗?我在这里面临同样的问题。
  • 还是没有运气..

标签: c# xamarin.forms xamarin.android xamarin.ios


【解决方案1】:

只需使用 TitleView 之类的东西:

<NavigationPage.TitleView>
        <StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
            <Label
                HorizontalOptions="FillAndExpand"
                Text="{StaticResource PageTitle}"
                TextColor="White"
                VerticalOptions="Center" />
            <SearchBar
                HorizontalOptions="End"
                Placeholder="Search"
                PlaceholderColor="{StaticResource GrayPlaceHolderColor}"
                TextColor="White"
                VerticalOptions="Center" />
        </StackLayout>
    </NavigationPage.TitleView>

【讨论】:

    【解决方案2】:

    我们可以在 Xamarin.iOS 和 Xamarin.Android 中创建一个自定义渲染器来完成它。

    这是一个示例应用程序供参考: https://github.com/brminnick/GitTrends

    这是一篇博文,展示了如何为 Xamarin.iOS 和 Xamarin.Android 的 Xamarin.Forms 应用添加搜索栏:https://www.codetraveler.io/2019/08/10/adding-a-search-bar-to-xamarin-forms-navigationpage/

    App.cs

    使用 Xamarin.Forms Platform-Specific 在 Xamarin.iOS 应用上使用 LargeTitles。

    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 接口

    创建可跨 Xamarin.Forms、Xamarin.Android 和 Xamarin.iOS 项目使用的接口。

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

    Xamarin.Forms 页面

    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 自定义渲染器

    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 菜单 XML

    1. 在 Xamarin.Android 项目的 Resources 文件夹中,创建一个名为 menu 的新文件夹(如果尚不存在)。

      • 注意:文件夹menu 有一个小写的“m”
    2. Resources &gt; menu 文件夹中,创建一个名为MainMenu.xml 的新文件。

    1. 打开Resources &gt; menu &gt; MainMenu.xml

    2. 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/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 自定义渲染器

    使用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 && page.Parent is NavigationPage navigationPage && navigationPage.CurrentPage is ISearchPage)
                    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.TextVariationFilter;
                        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);
        }
    }
    

    示例应用

    这是一个示例应用供参考: https://github.com/brminnick/GitTrends

    还有一篇博文展示了如何为 Xamarin.iOS 和 Xamarin.Android 添加搜索栏:https://www.codetraveler.io/2019/08/10/adding-a-search-bar-to-xamarin-forms-navigationpage/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2021-10-07
      相关资源
      最近更新 更多