1

我有扩展入口和自定义渲染器类

public class ExtendedEntryRenderer : EntryRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);

        if (Control != null)
        {
            Control.Click += (sender, evt) =>
            {
                var nativeEditText = (global::Android.Widget.EditText)Control;
                nativeEditText.SetSelectAllOnFocus(true);

                new Handler().PostDelayed(delegate
                {
                     Control.InputType = 0;
                     try
                     {
                         InputMethodManager inputMethodManager = Control.Context.GetSystemService(Android.Content.Context.InputMethodService) as InputMethodManager;
                         if (inputMethodManager != null)
                         {
                             inputMethodManager.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
                         }
                     }
                     catch (Exception Ex)
                     {

                     }
                 }, 300L);
            };


            // Hide soft input keyboard
            Control.FocusChange += (sender, evt) =>
            {
                // Select all on entry focus
                var nativeEditText = (global::Android.Widget.EditText)Control;

                nativeEditText.SetSelectAllOnFocus(true);

                new Handler().PostDelayed(delegate
                 {
                     Control.InputType = 0;
                     try
                     {
                         InputMethodManager inputMethodManager = Control.Context.GetSystemService(Android.Content.Context.InputMethodService) as InputMethodManager;
                         if (inputMethodManager != null)
                         {
                            inputMethodManager.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
                         }
                     }
                     catch (Exception Ex)
                     {

                     }
                 }, 300L);
            };
        }
    }
}

我的自定义条目:

public class ExtendedEntry : Entry
{

}

我的 XAML 文件是这样的:

<local:ExtendedEntry x:Name="BarcodeEntry" Text="{Binding Barcode}" Margin="0,0,0,0" HorizontalOptions="FillAndExpand" VerticalOptions="Start">
    <Entry.Triggers>
        <Trigger TargetType="Entry" Property="IsFocused" Value="True">
            <Setter Property="BackgroundColor" Value="Yellow" />
            <Setter Property="TextColor" Value="Black" />
        </Trigger>
    </Entry.Triggers>       
</local:ExtendedEntry>

Trigger不起作用。

但是当我像这样更改为默认进入控件时:

<Entry x:Name="BarcodeEntry" Text="{Binding Barcode}" Margin="0,0,0,0"HorizontalOptions="FillAndExpand" VerticalOptions="Start">
    <Entry.Triggers>
        <Trigger TargetType="Entry" Property="IsFocused" Value="True">
            <Setter Property="BackgroundColor" Value="Yellow" />
            <Setter Property="TextColor" Value="Black" />
        </Trigger>
    </Entry.Triggers>       
</Entry>

Trigger作品。

我做错了什么?

编辑

Xamarin.Forms 中的ExportRenderer行在我的渲染器类中。

[assembly: ExportRenderer(typeof(ExtendedEntry), typeof(ExtendedEntryRenderer))]
4

2 回答 2

0
  1. 您不必在每个事件下都做。你只能做一次

    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
    
        if (e.NewElement != null)
        {
            var nativeEditText = (global::Android.Widget.EditText)Control;
            // Select all on entry focus
            nativeEditText.SetSelectAllOnFocus(true);
    
  2. 您在 Control.Click 和 Control.FocusChange 中有相同的代码。您可能想考虑以某种方式将其用于单独的功能。请记住,当焦点丢失时也会调用 FocusChange,因此您可能需要检查

    if (evt.HasFocus)
    
  3. 创建 Control 时,其 OnFocusChangeListener 设置为 ExtendedEntryRenderer。但是,一旦您调用 Control.FocusChange+= 它就会更改为 mono.android.view.View_OnFocusChangeListenerImplementor@a25f36e 并且显然会导致问题。

注释掉 Control.FocusChange 它将起作用。当用户将焦点设置为您的条目时,您将获得足够的 Click 事件。如果需要,您将不知道何时失去焦点。

于 2016-12-02T22:12:41.223 回答
0

不幸的是,Xamarin 中的 Entry/EntryRenderer 系统非常有问题,这使得添加效果非常困难。更糟糕的是,我创建了一个可以工作的自定义渲染器,但有时会导致冻结,因为底层条目控件已添加到布局中。如果我向一个条目添加两种不同的效果,我仍然会卡住,但我能够获得焦点触发并成功使用单个效果。

为了避免丢失原始的焦点处理程序,我抓住了它:

private Android.Views.View.IOnFocusChangeListener focusListener = null;

private void ConfigureControl()
{
  EditText editText;

  editText = ((EditText)Control);
  this.focusListener = Control.OnFocusChangeListener;
  editText.FocusChange += EditText_FocusChange;

...

private void EditText_FocusChange(object sender, Android.Views.View.FocusChangeEventArgs e)
{
  EditText editText;

  editText = (EditText) sender;
  ...
  if (this.focusListener != null)
  {
    this.focusListener.OnFocusChange(editText,
      e.HasFocus);
  }

这允许效果运行并将焦点事件触发回 xamarin 表单。不幸的是,在两种不同的效果中执行此操作不起作用 - 可能是因为 mono.android.view.View_OnFocusChangeListenerImplementor@a25f36e 处理程序要么不转换为 Android.Views.View.IOnFocusChangeListener 要么它确实但是一些内部错误正在进入无限循环。

我正在使用一个效果来添加一个“x”来清除 android 条目,并且我还试图使用我创建的一个效果来选择所有焦点。两者都是包含在 Xamarin 中的明显候选者,因为基本选项过于频繁地需要证明将它们留给效果或自定义渲染器是合理的。如果你想达到同样的效果,你可以做我所做的——添加效果来添加“x”,然后不是一个效果来做一个非常简单的全选,你可以用这个不太漂亮但xamarin 视图中的功能代码:

  entry.Focused += (s, a) =>
  {
    Device.StartTimer(TimeSpan.FromMilliseconds(1),
      () =>
      {
        entry.CursorPosition = 0;
        entry.SelectionLength = (entry.Text ?? string.Empty).Length;
        return false;
      });
    ...
  };
  entry.Unfocused += (s, a) =>
  {
    ...
  };

我希望这可以为某人节省浪费时间的自定义渲染器开发和无休止的效果实验,直到我终于得到了一些如此令人沮丧的基本功能以可靠地工作。

于 2019-09-01T04:42:30.840 回答