是的,我找到了解决方案。要遵循的代码。但在此之前,让我稍微解释我所做的一切。
因此,肯定需要在我们自己的手中使用maters来处理图像及其底层资源(位图或可绘制,但是您想称之为)。基本上,它归结为处理原生的'ImageRenderer'对象。
现在,无法从任何地方获取对该ImageRenderer的引用,因为要这样做,需要能够调用Platform.GetRenderer(...)。由于其范围被声明为“内部”,因此无法访问“平台”类。
因此,除了为Image类和它的(Android)Renderer子类并从内部销毁这个Renderer本身(作为参数传递'true')之外,我没有别的选择。不要尝试'false “)。在渲染器内部,我挂钩页面消失(如果是TabbedPage)。在大多数情况下,页面消失事件不会很好地发挥作用,例如当页面仍处于屏幕堆栈中时,由于另一个页面正在绘制在顶部之上而消失。如果您丢弃图像,则当页面再次被覆盖(显示)时,它将不会显示图像。在这种情况下,我们必须挂钩主导航页面的“弹出”事件。
我试图尽我所能解释。剩下的 - 我希望 - 你将能够从代码中获得:
这是PCL项目中的图像子类。
using System;
using Xamarin.Forms;
namespace ApplicationClient.CustomControls
{
public class LSImage : Image
{
}
}
以下代码在Droid项目中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Android.Util;
using Application.Droid.CustomControls;
using ApplicationClient.CustomControls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ApplicationClient.CustomControls.LSImage), typeof(LSImageRenderer))]
namespace Application.Droid.CustomControls
{
public class LSImageRenderer : ImageRenderer
{
Page page;
NavigationPage navigPage;
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
if (GetContainingViewCell(e.NewElement) != null)
{
page = GetContainingPage(e.NewElement);
if (page.Parent is TabbedPage)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
return;
}
navigPage = GetContainingNavigationPage(page);
if (navigPage != null)
navigPage.Popped += OnPagePopped;
}
else if ((page = GetContainingTabbedPage(e.NewElement)) != null)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
}
}
}
void PageContainedInTabbedPageDisapearing (object sender, EventArgs e)
{
this.Dispose(true);
page.Disappearing -= PageContainedInTabbedPageDisapearing;
}
protected override void Dispose(bool disposing)
{
Log.Info("**** LSImageRenderer *****", "Image got disposed");
base.Dispose(disposing);
}
private void OnPagePopped(object s, NavigationEventArgs e)
{
if (e.Page == page)
{
this.Dispose(true);
navigPage.Popped -= OnPagePopped;
}
}
private Page GetContainingPage(Xamarin.Forms.Element element)
{
Element parentElement = element.ParentView;
if (typeof(Page).IsAssignableFrom(parentElement.GetType()))
return (Page)parentElement;
else
return GetContainingPage(parentElement);
}
private ViewCell GetContainingViewCell(Xamarin.Forms.Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(ViewCell).IsAssignableFrom(parentElement.GetType()))
return (ViewCell)parentElement;
else
return GetContainingViewCell(parentElement);
}
private TabbedPage GetContainingTabbedPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(TabbedPage).IsAssignableFrom(parentElement.GetType()))
return (TabbedPage)parentElement;
else
return GetContainingTabbedPage(parentElement);
}
private NavigationPage GetContainingNavigationPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(NavigationPage).IsAssignableFrom(parentElement.GetType()))
return (NavigationPage)parentElement;
else
return GetContainingNavigationPage(parentElement);
}
}
}
最后,我在PCL项目改变了应用程序的名称的命名空间“ApplicationClient”和Droid的项目为“Application.Droid”。您应该将其更改为您的应用程序名称。
此外,Renderer类末尾的几个递归方法,我知道我可以将它组合成一个Generic方法。事情是,当我需要时,我一次一个建立一个。所以,我就是这样离开它的。
快乐编码,
Avrohom
什么的4K PNG的位图大小? PNG存储在内存中而不压缩。当转换为位图时,可以创建一个超过1GB数据的4K PNG。 另外,是的,你真的需要检查位图是否处置。也许答案是,不,他们不是。 – Frank 2014-09-12 11:35:03
我目前使用的PNG被定义为512 x 512. – Avrohom 2014-09-12 12:02:01
因此,4kB PNG需要512 x 512 x 32位= 1MB的RAM来存储/显示。所以你很可能不会处置它们。 – Frank 2014-09-12 12:04:33