C# 在Xamarin表单的主/详细布局中从当前页面切换时,保留WebView加载的页面内容
我正在使用C# 在Xamarin表单的主/详细布局中从当前页面切换时,保留WebView加载的页面内容,c#,xamarin,webview,xamarin.ios,xamarin.forms,C#,Xamarin,Webview,Xamarin.ios,Xamarin.forms,我正在使用Master/Detaillayout构建一个导航菜单和一些页面。其中一个页面是WebView控件,没有其他内容。当我从导航菜单中切换离开这个WebView页面,然后再切换回来时,WebView的内容消失了,状态也消失了。这在iOS和Android上都会发生 但如果我从WebView页面导航到一个完全不同的页面(非主控/详细页面),在返回WebView页面后,一切都很好。将保留所有内容和状态 我必须重新加载页面,但用户的操作将丢失。是否有办法保留页面的内容和状态,并在不重新加载页面的情
Master/Detail
layout构建一个导航菜单和一些页面。其中一个页面是WebView
控件,没有其他内容。当我从导航菜单中切换离开这个WebView页面,然后再切换回来时,WebView的内容消失了,状态也消失了。这在iOS
和Android
上都会发生
但如果我从WebView页面导航到一个完全不同的页面(非主控/详细页面),在返回WebView页面后,一切都很好。将保留所有内容和状态
我必须重新加载页面,但用户的操作将丢失。是否有办法保留页面的内容和状态,并在不重新加载页面的情况下还原它们 导航控制器将现有UIViewController保留在导航堆栈上,但当您弹出UIViewController时,它会从堆栈中删除视图控制器,因此其内容会被删除 要保留它,您需要有一个WebViewController的共享实例,并且始终使用相同的WebViewController 在WebView控制器中,编写以下代码以创建共享实例:
private static ViewController vc;
public static WebViewController SharedInstance()
{
if (vc == null)
{
var storyboard = UIStoryboard.FromName("MainStoryboard", null);
vc = storyboard.InstantiateViewController("WevViewController") as WevViewController;
}
return vc;
}
每当您想要显示web视图控制器时,请使用以下命令
public void DisplayWebview()
{
WevViewController webvw = WevViewController.SharedInstance();
NavigationController.PushViewController(webvw,true);
}
在
App
类中,创建包含WebView
的ContentPage
实例。在App
类中将ContentPage
创建为静态变量将保留其状态,并确保其打开到用户最近查看的同一网页
示例代码
不幸的是,您需要修改以提供所需的行为。问题是,当细节页面从MasterDetail中移除(从Webview切换到另一个页面)时,所有本机控件都被释放;即使您硬引用
Xamarin.Forms.Webview
或Xamarin.Forms.Page
对象
在源代码中,您可以看到,如果\u detail
属性不为null,则它将从MasterDetailPage.PageController.InternalChildren
中删除。您需要在那里签入包含Xamarin.Forms.Webview
的Xamarin.Forms.Page
,并确保未将其从页面控制器中删除。这将保留本机webview和webview处理程序,因此不会重新加载任何内容。需要注意的几点:
PageController.InternalChildren
App
类代码来验证所有这些:
public class App : Application
{
public App()
{
MainPage = new MasterDetail();
}
}
public class MasterDetail : MasterDetailPage
{
static WebViewPage persistentWebPage = new WebViewPage();
public MasterDetail()
{
var masterPage = new MasterPage();
persistentWebPage = new WebViewPage();
Master = masterPage;
Detail = persistentWebPage;
masterPage.listview.ItemSelected += (sender, e) =>
{
var item = e.SelectedItem as string;
if (string.IsNullOrEmpty(item))
return;
switch (item)
{
case "1":
Detail = persistentWebPage;
break;
default:
Detail = new ContentPage { BackgroundColor = Color.Red };
break;
}
masterPage.listview.SelectedItem = null;
IsPresented = false;
};
}
}
public class MasterPage : ContentPage
{
public ListView listview = new ListView { ItemsSource = new string[] { "1", "2", "3" } };
public MasterPage()
{
Title = "Master";
Content = listview;
}
}
public class WebViewPage : ContentPage
{
public static WebView webView = new WebView { Source = "https://www.google.com/" };
public WebViewPage()
{
Content = webView;
}
}
接下来,在Android项目中创建一个渲染器(您也可以使用iOS,我只是使用Android)并复制以下代码:
public class WebViewRenderer_Droid : WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
if (e.NewElement == null)
Console.WriteLine("*********e.NewElement is null");
else
Console.WriteLine("*********e.NewElement is not null");
if (e.OldElement == null)
Console.WriteLine("*********e.OldElement is null");
else
Console.WriteLine("*********e.OldElement is not null");
if (Control == null)
Console.WriteLine("*********Control is null");
else
Console.WriteLine("*********Control is not null");
base.OnElementChanged(e);
}
}
公共类WebViewRenderer\u Droid:WebViewRenderer
{
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
if(e.NewElement==null)
Console.WriteLine(“*********e.NewElement为空”);
其他的
Console.WriteLine(“*********e.NewElement不为空”);
if(e.OldElement==null)
Console.WriteLine(“******e.OldElement为空”);
其他的
Console.WriteLine(“*********e.OldElement不为空”);
if(Control==null)
Console.WriteLine(“*********控件为空”);
其他的
Console.WriteLine(“*********控件不为空”);
基础。一个要素发生变化(e);
}
}
运行该项目并从webview页面切换回来。您将看到Control
和e.OldElement
在一个点上都为null。这证明即使使用硬引用,也会处理本机处理程序。这是因为您无法控制Xamarin.Forms如何处理本机控件引用,我们可以看到,如果Control
为null,那么所有内容都将被重新创建
我希望这有帮助!深入挖掘来找出这一点很有趣 我找到了一个有效的解决方案,尽管更像是一个黑客。也就是说,当触摸一个菜单项时,我没有导航到主控/详细信息中的子页面,而是导航到另一个页面,这意味着向下1级。当用户从该页面返回时,所有内容都将被保留。但这样一来,导航菜单就不再总是在那里了。不过没关系 为了解决这个问题,我创建了一个自定义webview渲染器。当我在渲染器中创建新的webview时(例如,new WKWebView(Frame,opts)),我将其替换为覆盖Dispose的WKWebView子类,使其不做任何操作。根据需要跟踪OnElementChanged中的原始webview。您需要在OnAppearing()方法中设置webview的内容或来源否,这正是我不想做的,因为我只想加载一次页面,并在导航离开该页面后将内容保留在那里,然后再导航回来。为此,您可以在页面的override方法OnDisappearing()上将webview的源设置为“about:blank”,确定吗?由于将其设置为大约:空白,因此明确销毁上一页。我不想破坏页面,我想保存页面状态查看我的帖子,你必须修改MasterDetail的源代码以保留本机WebView谢谢你的回答,但我使用的是Xamarin Forms,它是Android/iOS api的包装器,您的答案是关于本机iOS api。似乎无法使用母版/详细页导航它似乎保存了webView的URL,但仍在重新加载该URL。重新加载就像重新访问pageHi,我想你找到了原因,但解决方案显然比你建议的要多
public class WebViewRenderer_Droid : WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
if (e.NewElement == null)
Console.WriteLine("*********e.NewElement is null");
else
Console.WriteLine("*********e.NewElement is not null");
if (e.OldElement == null)
Console.WriteLine("*********e.OldElement is null");
else
Console.WriteLine("*********e.OldElement is not null");
if (Control == null)
Console.WriteLine("*********Control is null");
else
Console.WriteLine("*********Control is not null");
base.OnElementChanged(e);
}
}