我需要在XamarinForms上的datepicker中阻止粘贴功能

Vin*_*tto 3 xamarin.ios xamarin.android xamarin xamarin.forms

在我正在构建的解决方案中,我有一个工作正常的日期选择器.但是,如果用户按下触摸并粘贴某些内容,它将覆盖日期.

当用户粘贴时,事件OnElementChanged,OnElementPropertyChanged甚至INotifyPropertyChanged不会引发.我也找不到阻止粘贴功能的选项.(当正常选择日期时,将调用事件.)

这种情况发生在iOS和Android中.有人能帮我吗?我被困住了,我的研究对我帮助不大.

fox*_*nna 6

在iOS平台上

DatePicker表现得这样,因为它是通过引擎实现的UITextField.为了避免编辑,UITextField你必须为它分配一个falseShouldChangeCharacters方法返回的委托.

完整的解决方案如下:

DatePicker在共享项目中声明a的子级:

public class ExtendedDatePicker : DatePicker
{
}
Run Code Online (Sandbox Code Playgroud)

在iOS项目中声明相应的渲染器:

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

实施UneditableUITextFieldDelegate:

public class UneditableUITextFieldDelegate : NSObject, IUITextFieldDelegate
{
    [Export("textField:shouldChangeCharactersInRange:replacementString:")]
    public bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString) =>
        false;
}
Run Code Online (Sandbox Code Playgroud)

这不会阻止显示"复制"/"粘贴"菜单,但DatePicker按下后不会更改值.

在Android平台上

DatePickerAndroid上的底层UI元素是EditText.

我已经发布的文章解释如何操作的上下文菜单EditText中的原生AndroidXamarin.Forms.你可以在那里得到整体想法.

我无法长时间点击DatePicker以查看问题,因此我只能猜测正确的修复,但是类似于此的渲染器应该完全禁用所选文本的上下文菜单以及用户点击时的粘贴选项游标:

[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();
    }
}
Run Code Online (Sandbox Code Playgroud)

CustomInsertionActionModeCallback并且CustomInsertionActionModeCallback将返回falseOnCreateActionMode并防止菜单出现.

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) { }
}
Run Code Online (Sandbox Code Playgroud)

=======
更新:这个问题激发了我创建一篇文章,扩展了这个答案,并附有一些解释和细节.