问题描述
在我正在构建的解决方案中,我有一个可以正常工作的日期选择器.但是,如果用户按下触摸并粘贴了一些东西,它将覆盖日期.
In the solution that I'm building, I have a date-picker that works fine. But, if the user press the touch and paste something, it will overwrite the date.
用户粘贴时,不会引发OnElementChanged
,OnElementPropertyChanged
甚至INotifyPropertyChanged
的事件.我也找不到阻止粘贴功能的选项. (通常选择日期时,将调用事件.)
When the user pastes, the events of OnElementChanged
, OnElementPropertyChanged
and even the INotifyPropertyChanged
are not raised. I also can't find a option to block the paste function. (When the date is choose normally, the events are being called.)
这发生在iOS和Android中.有人能帮我吗?我被困住了,研究对我没有多大帮助.
This happens in iOS and Android. Can someone help me? I am stuck and my researches don't help me much.
推荐答案
在iOS平台上
DatePicker
的行为方式是这样的,因为它是通过UITextField
实现的.为了避免编辑UITextField
,您必须为其分配一个委托,该委托从ShouldChangeCharacters
方法返回false
.
DatePicker
behaves this way because under the hood it is implemented via UITextField
.To avoid editing of UITextField
you have to assign it a delegate which returns false
from ShouldChangeCharacters
method.
完整的解决方案如下:
在共享项目中声明DatePicker
的子代:
Declare a child of a DatePicker
in a shared project:
public class ExtendedDatePicker : DatePicker
{
}
在iOS项目中声明一个相应的渲染器:
Declare a corresponding renderer in iOS project:
[assembly: ExportRenderer(typeof(ExtendedDatePicker), typeof(ExtendedDatePickerRenderer))]
...
public class ExtendedDatePickerRenderer : DatePickerRenderer
{
private UneditableUITextFieldDelegate _delegate = new UneditableUITextFieldDelegate();
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
Control.Delegate = _delegate;
}
}
实施UneditableUITextFieldDelegate
:
public class UneditableUITextFieldDelegate : NSObject, IUITextFieldDelegate
{
[Export("textField:shouldChangeCharactersInRange:replacementString:")]
public bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString) =>
false;
}
这不会阻止'copy'/'paste'菜单的显示,但是DatePicker
的值在按下后将不会更改.
This will not prevent the 'copy'/'paste' menu from being shown but DatePicker
value will not be changed after pressing them.
在Android平台上
DatePicker
在Android上的基础UI元素是EditText
.
The underlying UI element for DatePicker
on Android is EditText
.
我在原生Android 和 Xamarin.Forms .您可以在那里获得总体思路.
I have posted articles explaining how to manipulate context menu of EditText
in native Android and Xamarin.Forms. You can get the overall idea there.
我无法在DatePicker
上进行长按才能看到问题,因此只能猜测正确的修复方法,但是与此类似的渲染器应完全禁用所选文本的上下文菜单以及用户点击光标时粘贴选项:
I was not able to perform a long tap on a DatePicker
to see the problem thus I can only guess about the proper fix, but a renderer similar to this one should completely disable context menu for selected text as well as a paste option when a user taps a cursor:
[assembly: ExportRenderer(typeof(ExtendedDatePicker), typeof(ExtendedDatePickerRenderer))]
...
public class ExtendedDatePickerRenderer : DatePickerRenderer
{
public ExtendedDatePickerRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
Control.CustomSelectionActionModeCallback = new CustomSelectionActionModeCallback();
Control.CustomInsertionActionModeCallback = new CustomInsertionActionModeCallback();
}
}
CustomInsertionActionModeCallback
和CustomInsertionActionModeCallback
将从OnCreateActionMode
返回false
,并阻止菜单出现.
CustomInsertionActionModeCallback
and CustomInsertionActionModeCallback
would return false
from OnCreateActionMode
and will prevent menu from appearing.
public class CustomInsertionActionModeCallback : Java.Lang.Object, ActionMode.ICallback
{
public bool OnCreateActionMode(ActionMode mode, IMenu menu) => false;
public bool OnActionItemClicked(ActionMode m, IMenuItem i) => false;
public bool OnPrepareActionMode(ActionMode mode, IMenu menu) => true;
public void OnDestroyActionMode(ActionMode mode) { }
}
public class CustomSelectionActionModeCallback : Java.Lang.Object, ActionMode.ICallback
{
public bool OnActionItemClicked(ActionMode m, IMenuItem i) => false;
public bool OnCreateActionMode(ActionMode mode, IMenu menu) => false;
public bool OnPrepareActionMode(ActionMode mode, IMenu menu) => true;
public void OnDestroyActionMode(ActionMode mode) { }
}
=======
更新:这个问题启发了我创建一个文章通过一些解释和详细信息扩展了此答案.
=======
UPDATE: this question inspired me to create an article extending this answer with some explanations and details.
这篇关于我需要在XamarinForms上的日期选择器中阻止粘贴功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!