我正在开发一个 Xamarin.Forms Android-App ,在ContentPage上, CustomRenderer 用于在页面页眉中显示SearchView。 " SearchPage"的CustomRenderer; class类似于以下内容:
/// <summary>
/// The search page renderer.
/// </summary>
public class SearchPageRenderer : PageRenderer
{
/// <summary>
/// Gets or sets the search view.
/// </summary>
private SearchView searchView;
/// <summary>
/// Gets or sets the toolbar.
/// </summary>
private Toolbar toolbar;
/// <summary>
/// Reaction on the disposing of the page.
/// </summary>
/// <param name="disposing">A value indicating whether disposing.</param>
protected override void Dispose(bool disposing)
{
if (this.searchView != null)
{
this.searchView.QueryTextChange -= this.OnQueryTextChangeSearchView;
}
this.toolbar?.Menu?.RemoveItem(Resource.Menu.mainmenu);
base.Dispose(disposing);
}
/// <summary>
/// Reaction on the element changed event.
/// </summary>
/// <param name="e">The event argument.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e?.NewElement == null || e.OldElement != null)
{
return;
}
this.AddSearchToToolBar();
}
/// <summary>
/// Adds a search item to the toolbar.
/// </summary>
private void AddSearchToToolBar()
{
this.toolbar = (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Toolbar>(Resource.Id.toolbar);
if (this.toolbar != null)
{
this.toolbar.Title = this.Element.Title;
this.toolbar.InflateMenu(Resource.Menu.mainmenu);
this.searchView = this.toolbar.Menu?.FindItem(Resource.Id.action_search)?.ActionView?.JavaCast<SearchView>();
if (this.searchView != null)
{
this.searchView.QueryTextChange += this.OnQueryTextChangeSearchView;
this.searchView.ImeOptions = (int)ImeAction.Search;
this.searchView.MaxWidth = int.MaxValue;
this.searchView.SetBackgroundResource(Resource.Drawable.textfield_search_holo_light);
}
}
}
/// <summary>
/// Reaction on the text change event of the searchbar.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event argument.</param>
private void OnQueryTextChangeSearchView(object sender, SearchView.QueryTextChangeEventArgs e)
{
var searchPage = this.Element as SearchPage;
searchPage?.SearchCommand?.Execute(e?.NewText);
}
}
感谢this Stack-Overflow线程,到目前为止我的工作就像魅力一样。 现在,如果用户点击&#34; SearchPage&#34;中的项目,则使用以下方法将新的ContentPage(称为&#34; DetailPage&#34;)推送到NavigationStack:
private async Task PushPageAsync(object model, ContentPage page, INavigation navigation)
{
page.BindingContext = model;
await navigation.PushAsync(page).ConfigureAwait(false);
}
没有问题。但是,如果用户从&#34; DetailPage&#34;导航回到&#34; SearchPage&#34;通过使用后退按钮,自定义搜索标题根本不显示。
我尝试了什么:
使用&#34; OnAppearing&#34;页面的事件而不是&#34; OnElementChanged&#34;。这并没有乍一看解决问题。但是,如果我将一个Task.Delay(500)添加到OnAppearing-Method然后再添加SearchView ,则会显示它。但是这个修复看起来非常难看,如果我在使用SearchPage时使用应用程序并恢复,则Search-Widget显示两次。
所以我的问题是:
Xamarin是否有错误或我做错了什么?
答案 0 :(得分:3)
Xamarin是否有错误或我做错了什么?
我不能说这是一个错误,我更愿意认为它是设计的。真正的问题是您尝试修改自定义渲染器中的Toolbar
,并根据您的说明使用NavigationPage
,其NavigationPageRenderer将更新{{3}}的视图{1}}每次更改当前页面时。
所以你正确使用页面的“OnAppearing”事件而不是“OnElementChanged”,这会导致另一个问题,当您删除旧页面时,Toolbar
的更新会被延迟可以从Toolbar
方法的源代码中看到,而RemovePage
方法将在显示新页面时立即执行:
OnAppearing
所以我不认为你做错了什么,你使用Device.StartTimer(TimeSpan.FromMilliseconds(10), () =>
{
UpdateToolbar();
return false;
});
的方法可以快速解决这个问题。
根据您的描述:
但是这个修复看起来很难看,如果我在使用SearchPage时使用应用程序并恢复,则Search-Widget会显示两次。
我建议您将await Task.Delay(500);
更改为SearchPage
,然后从页面中动态添加/删除此视图:
View
和它的渲染器(其他代码相同,只更改为从public class SearchPage : View
{
...
}
继承而且ViewRenderer
的参数不同):
OnElementChanged
然后,您可以将其用作要显示的页面中的控件/视图,而不是直接用作public class SearchPageRenderer : ViewRenderer
{
private SearchView searchView;
/// <summary>
/// Gets or sets the toolbar.
/// </summary>
private Android.Support.V7.Widget.Toolbar toolbar;
...
/// <summary>
/// Reaction on the element changed event.
/// </summary>
/// <param name="e">The event argument.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (e?.NewElement == null || e.OldElement != null)
{
return;
}
this.AddSearchToToolBar();
}
...
}
。例如,我想在Page
中显示此搜索视图,然后导航到App.xaml.cs中的MainPage
:
MainPage
MainPage = new NavigationPage(new MainPage());
的布局:
MainPage
最后覆盖<StackLayout>
...
</StackLayout>
的{{1}}和OnAppearing
方法:
OnDisappearing
顺便说一下,如果你想从这里的MainPage
导航到其他页面,你可以像这样编码:
protected override async void OnAppearing()
{
base.OnAppearing();
await Task.Delay(500);
var content = this.Content as StackLayout;
content.Children.Add(new SearchPage());
}
protected override void OnDisappearing()
{
base.OnDisappearing();
var content = this.Content as StackLayout;
foreach (var child in content.Children)
{
var searchpage = child as SearchPage;
if (searchpage != null)
{
content.Children.Remove(searchpage);
return;
}
}
}
无需为其创建MainPage
任务。