之前有介绍了forms和native的交互处理,为了使用第三方的android插件,做了forms到native的跳转,这时会有个性能问题:forms和native的出入口必须为指定的MainActivity和Application class,而每次经过这两个类时,所有的成员都会重新初始化。使用android的renderer自定义控件可以避免这个问题。
1、PCL中的Demo.xaml,在根节点ContentPage(举个例子)设置xmlns声明自定义控件所在的命名空间及程序集
xmlns:customcontrols="clr-namespace:AppPortable;assembly=AppPortable"
在控件调用处使用自定义节点
<customcontrols:Demo></customcontrols:Demo>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customcontrols="clr-namespace:AppPortable;assembly=AppPortable"
x:Class="StoneAppPortable.CropImage">
<customcontrols:Demo></customcontrols:Demo>
</ContentPage>
2、PCL中的Demo.cs,继承自View(举个例子,Forms内置很多控件类用来继承,与android项目中的renderer对应)
namespace AppPortable
{
public class Demo : View
{
public Demo()
{
}
}
}
3、android中的renderer,render的说明之前介绍过,这边只对实现逻辑说明
[assembly: ExportRenderer(typeof(StoneAppPortable.Demo), typeof(StoneApp.Droid.Renderers.DemoRenderer))]
namespace StoneApp.Droid.Renderers
{
public class CropPageRenderer : ViewRenderer<Demo, Android.Views.View>
{
protected override void OnElementChanged(ElementChangedEventArgs<Demo> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
//获取绑定的自定义控件对象
var demo = e.NewElement as Demo;
//获取当前上下文环境
var activity = this.Context as Activity;
//使用LayoutInflater获取Resource下layout,即用户自定义的控件布局
var layoutId = Context.Resources.GetIdentifier("demolayout", "layout", activity.PackageName);
var inflater = LayoutInflater.FromContext(activity);
var customView = inflater.Inflate(layoutId, null, false);\\参数请看官方api
//获取layout中的控件,innerControlView为自定义的相应View,GetIdentifier的参数请看官方api
var innerControlId = Context.Resources.GetIdentifier("innerControl", "id", activity.PackageName);
innerControlView = customView.FindViewById<innerControlView>(imageId);
//renderder结束后回调,这边假设自定义layout中按钮点击调用PCL中Demo类的成员函数OnSaveClicked
var buttonId = Context.Resources.GetIdentifier("save", "id", activity.PackageName);
customView.FindViewById<Android.Widget.Button>(buttonId).Click += async (sender, args) => {
await Elemnt.OnSaveClicked(activity);//Element为PCL中的绑定类
};
//完成控件的设置,若customView已存在则移除,最后加载
var contentView = (ViewGroup)customView.Parent;
if (contentView != null)
{
var oldLayout = contentView.GetChildAt(1);
contentView.RemoveView(oldLayout);
}
SetNativeControl(customView);
}
}
}
}