最近我一直对创建Android和iOS的自定义控件感兴趣,但也希望它们可以在Xamarin Forms中使用 . 这怎么可能?表格是否在幕后做了一些非常奇怪的事情?如何在堆叠布局或网格中进行大小调整?
作为一个非常简单的例子,Pluralsighti上的一个教程已经跟随自定义android控件创建了一个“lengthpicker”控件 . 它包括2个按钮和一个文本视图 .
Resources\layout\length_picker.axml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/minus_button"
android:text="-"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Large" />
<Button
android:id="@+id/plus_button"
android:text="+"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
LengthPicker.cs
public class LengthPicker : LinearLayout
{
private View mPlusButton;
private TextView mTextView;
private View mMinusButton;
private int mNumInches = 0;
public LengthPicker(Context context) :base(context)
{
Init();
}
public LengthPicker(Context context, IAttributeSet attrs): base(context, attrs)
{
Init();
}
private void Init()
{
LayoutInflater inflater = LayoutInflater.From(Context);
inflater.Inflate(Resource.Layout.length_picker,this);
mPlusButton = FindViewById<Button>(Resource.Id.plus_button);
mTextView = FindViewById<TextView>(Resource.Id.text);
mMinusButton = FindViewById<Button>(Resource.Id.minus_button);
UpdateControls();
ApplyButtonClickHandlers();
Orientation = Orientation.Horizontal;
this.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
}
private void ApplyButtonClickHandlers()
{
mPlusButton.Click += MPlusButton_Click;
mMinusButton.Click += MMinusButton_Click;
}
private void UpdateControls()
{
int feet = mNumInches / 12;
int inches = mNumInches % 12;
string text = $"{feet}' {inches}\"";
if(feet == 0)
{
text = $"{inches}\"";
}
else
{
if(inches == 0)
{
text = $"{feet}'";
}
}
mTextView.Text = text;
mMinusButton.Enabled = mNumInches > 0;
}
private void MMinusButton_Click(object sender, EventArgs e)
{
mNumInches--;
UpdateControls();
}
private void MPlusButton_Click(object sender, EventArgs e)
{
mNumInches++;
UpdateControls();
}
}
如何将此转换为Xamarin Forms可用控件?我试图这样做并且它有效(有一些小的警告,但我仍然不知道我是否正在做“对”
我在PCL中有一个从View扩展的类 . PCL LengthPicker.cs
public class LengthPicker : Xamarin.Forms.View
{
public static readonly BindableProperty MinusColorProperty = BindableProperty.Create("MinusColor", typeof(Color), typeof(LengthPicker), Color.Default);
public Color MinusColor
{
get { return (Color)GetValue(MinusColorProperty); }
set { SetValue(MinusColorProperty, value); }
}
}
在android项目中,我有一个扩展 LengthPickerRenderer.cs 的CustomRenderer
using ALengthPicker = MobileControls.Samples.LengthPicker; // LengthPicker in separater Android class library
using AButton = Android.Widget.Button;
using ATextView = Android.Widget.TextView;
namespace FormsMobileControlApp.Droid.Renderers
{
public class LengthPickerRenderer :ViewRenderer<LengthPicker,ALengthPicker>
{
private AButton _minusButton;
private AButton _plusButton;
private ATextView _text;
protected override void OnElementChanged(ElementChangedEventArgs<Controls.LengthPicker> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
if (Control == null)
SetNativeControl(new ALengthPicker(Forms.Context));
_minusButton = Control.FindViewById<AButton>(MobileControls.Resource.Id.minus_button);
_text = Control.FindViewById<ATextView>(MobileControls.Resource.Id.text);
_plusButton = Control.FindViewById<AButton>(MobileControls.Resource.Id.plus_button);
}
. . .
}
}
}
现在,就像我说的那样有效,但有一些奇怪的事情发生了,我也不知道这是否“正确” . 1.)lengthpicker的教程有控件XML将它的根作为合并 . 这在XF中使用时效果不佳,因此我将其更改为LinearLayout 2.)具有类似Color的按钮的可绑定属性是很奇怪的 . 为了更改自定义渲染器上的背景颜色,我必须调用_minusButton.SetBackground(Element.MinusColor.ToAndroid()),这使得按钮看起来非常扁平,甚至比其他xamarin表单按钮更大
我在android上看到了关于自定义xamarin表单控件的James Montemagno's blog post但它没有对膨胀布局做任何事情,而是覆盖了draw方法 .
有没有经验做过这样的事情?