Xamarin - 没有 NumberPicker 的自定义选择器
Xamarin - Custom Picker without NumberPicker
我的 Xamarin 项目中有一个自定义选择器,我花了很长时间才达到我想要的效果。
我希望我的 CustomPicker 像这样显示
而不是这个,因为我无法将单词居中,而且 select 与另一个单词相比会更快。
我不想要取消按钮,我已经实现了,但我想不出同时拥有这两个按钮的方法
- 没有取消按钮
- 像第一张图片一样的选择器视图
这是我的CustomPicker
class
public class CustomPicker : Picker
{
public static readonly BindableProperty DonebuttonTextProperty = BindableProperty.Create("DonebuttonText", typeof(string),
typeof(string), null);
public string CancelButtonText
{
get { return (string)GetValue(DonebuttonTextProperty); }
set { SetValue(DonebuttonTextProperty, value); }
}
}
我的 CustomPickerRenderer
在 Android
public class CustomPickerRenderer : Xamarin.Forms.Platform.Android.AppCompat.PickerRenderer
{
public CustomPickerRenderer(Context context) : base(context) { }
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || e.OldElement != null)
return;
Control.Click += Control_Click;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click;
base.Dispose(disposing);
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
var picker = new NumberPicker(Context);
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
builder.SetPositiveButton("Done", (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
// It is possible for the Content of the Page to be changed on SelectedIndexChanged.
// In this case, the Element & Control will no longer exist.
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is also possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
如您所见,我使用了 Xamarin.Forms.Platform.Android.AppCompat.Picker
来使用我想要显示的视图,但是如果我使用 NumberPicker
,它将像第二张照片一样显示。
请帮助我还没有看到任何关于如何执行此操作的示例,我一直在搜索很多。谢谢。
如果您希望选择器像第一个屏幕截图那样显示。您可以重置选择器布局以将项目放在列表视图中。对于 ietview 中项目之间的分隔符,您可以设置 divider
ro null.
Xaml:
<Picker x:Name="picker"
Title="Select"
TitleColor="Red">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>item1</x:String>
<x:String>item2</x:String>
<x:String>item3</x:String>
<x:String>item4</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
自定义渲染器:
[assembly: ExportRenderer(typeof(Picker), typeof(CustomPickerRenderer2))]
namespace App1.Droid
{
public class CustomPickerRenderer2 : PickerRenderer
{
AlertDialog listDialog;
string[] items;
public CustomPickerRenderer2(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Click += Control_Click; ;
}
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
items = model.Items.ToArray();
AlertDialog.Builder builder = new AlertDialog.Builder(this.Context);
builder.SetTitle(model.Title ?? "");
builder.SetNegativeButton("Cancel", (s, a) =>
{
Control?.ClearFocus();
builder = null;
});
Android.Views.View view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.listview, null);
Android.Widget.ListView listView = view.FindViewById<Android.Widget.ListView>(Resource.Id.listView1);
MyAdapter myAdapter = new MyAdapter(items, Element.SelectedIndex);
listView.Adapter = myAdapter;
listView.ItemClick += ListView_ItemClick;
builder.SetView(view);
listDialog = builder.Create();
listDialog.Show();
}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Control.Text = items[e.Position];
Element.SelectedIndex = e.Position;
Console.WriteLine(items[e.Position]);
listDialog.Dismiss();
listDialog = null;
}
}
class MyAdapter : BaseAdapter
{
private string[] items;
private int selectedIndex;
public MyAdapter(string[] items)
{
this.items = items;
}
public MyAdapter(string[] items, int selectedIndex) : this(items)
{
this.selectedIndex = selectedIndex;
}
public override int Count => items.Length;
public override Java.Lang.Object GetItem(int position)
{
return items[position];
}
public override long GetItemId(int position)
{
return position;
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.listview_item, null);
}
TextView textView = convertView.FindViewById<TextView>(Resource.Id.textView1);
textView.Text = items[position];
return convertView;
}
}
}
listview.xml:您可以在 android 项目中创建 Resources/layout
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listView1"
android:divider="@null"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
listview_item.xml :您可以在 android 项目中的 Resources/layout
中创建。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
我的 Xamarin 项目中有一个自定义选择器,我花了很长时间才达到我想要的效果。
我希望我的 CustomPicker 像这样显示
而不是这个,因为我无法将单词居中,而且 select 与另一个单词相比会更快。
我不想要取消按钮,我已经实现了,但我想不出同时拥有这两个按钮的方法
- 没有取消按钮
- 像第一张图片一样的选择器视图
这是我的CustomPicker
class
public class CustomPicker : Picker
{
public static readonly BindableProperty DonebuttonTextProperty = BindableProperty.Create("DonebuttonText", typeof(string),
typeof(string), null);
public string CancelButtonText
{
get { return (string)GetValue(DonebuttonTextProperty); }
set { SetValue(DonebuttonTextProperty, value); }
}
}
我的 CustomPickerRenderer
在 Android
public class CustomPickerRenderer : Xamarin.Forms.Platform.Android.AppCompat.PickerRenderer
{
public CustomPickerRenderer(Context context) : base(context) { }
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || e.OldElement != null)
return;
Control.Click += Control_Click;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click;
base.Dispose(disposing);
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
var picker = new NumberPicker(Context);
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
builder.SetPositiveButton("Done", (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
// It is possible for the Content of the Page to be changed on SelectedIndexChanged.
// In this case, the Element & Control will no longer exist.
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is also possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
如您所见,我使用了 Xamarin.Forms.Platform.Android.AppCompat.Picker
来使用我想要显示的视图,但是如果我使用 NumberPicker
,它将像第二张照片一样显示。
请帮助我还没有看到任何关于如何执行此操作的示例,我一直在搜索很多。谢谢。
如果您希望选择器像第一个屏幕截图那样显示。您可以重置选择器布局以将项目放在列表视图中。对于 ietview 中项目之间的分隔符,您可以设置 divider
ro null.
Xaml:
<Picker x:Name="picker"
Title="Select"
TitleColor="Red">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>item1</x:String>
<x:String>item2</x:String>
<x:String>item3</x:String>
<x:String>item4</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
自定义渲染器:
[assembly: ExportRenderer(typeof(Picker), typeof(CustomPickerRenderer2))]
namespace App1.Droid
{
public class CustomPickerRenderer2 : PickerRenderer
{
AlertDialog listDialog;
string[] items;
public CustomPickerRenderer2(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Click += Control_Click; ;
}
}
private void Control_Click(object sender, EventArgs e)
{
Picker model = Element;
items = model.Items.ToArray();
AlertDialog.Builder builder = new AlertDialog.Builder(this.Context);
builder.SetTitle(model.Title ?? "");
builder.SetNegativeButton("Cancel", (s, a) =>
{
Control?.ClearFocus();
builder = null;
});
Android.Views.View view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.listview, null);
Android.Widget.ListView listView = view.FindViewById<Android.Widget.ListView>(Resource.Id.listView1);
MyAdapter myAdapter = new MyAdapter(items, Element.SelectedIndex);
listView.Adapter = myAdapter;
listView.ItemClick += ListView_ItemClick;
builder.SetView(view);
listDialog = builder.Create();
listDialog.Show();
}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Control.Text = items[e.Position];
Element.SelectedIndex = e.Position;
Console.WriteLine(items[e.Position]);
listDialog.Dismiss();
listDialog = null;
}
}
class MyAdapter : BaseAdapter
{
private string[] items;
private int selectedIndex;
public MyAdapter(string[] items)
{
this.items = items;
}
public MyAdapter(string[] items, int selectedIndex) : this(items)
{
this.selectedIndex = selectedIndex;
}
public override int Count => items.Length;
public override Java.Lang.Object GetItem(int position)
{
return items[position];
}
public override long GetItemId(int position)
{
return position;
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.listview_item, null);
}
TextView textView = convertView.FindViewById<TextView>(Resource.Id.textView1);
textView.Text = items[position];
return convertView;
}
}
}
listview.xml:您可以在 android 项目中创建 Resources/layout
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listView1"
android:divider="@null"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
listview_item.xml :您可以在 android 项目中的 Resources/layout
中创建。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>