【问题标题】:Xamarin Layout can't receive focusXamarin 布局无法获得焦点
【发布时间】:2019-03-01 17:18:33
【问题描述】:

我正在尝试在 Xamarin Forms 中创建一个名为 FormElement 的复合视图组件,它由两个标签和一个条目组成:

<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:custom="clr-namespace:Mynamespace;assembly=Mynamespace"
         x:Class="Mynamespace.Components.FormEntry">
    <StackLayout Orientation="Horizontal">
        <Label x:Name="formRequiredStar"
               IsVisible="{Binding IsRequired}"
               Text="*" TextColor="Red"
               FontSize="15"
               FontAttributes="Bold"
               Margin="-12,0,0,0"
               HorizontalOptions="Start" />
        <Label x:Name="formLabel"
               HorizontalOptions="Start"
               Text="{Binding LabelText}"
               TextColor="{Binding LabelTextColor}"
               FontSize="{Binding LabelTextFontSize}"
               FontAttributes="{Binding LabelTextFontStyle}" />
    </StackLayout>
    <Frame BorderColor="Black"
           CornerRadius="7"
           Padding="5,0"
           Margin="0,-3,0,0"
           HasShadow="false">
        <Entry x:Name="mainEntry"
               Keyboard="{Binding KeybdType}"
               Placeholder="{Binding EntryPlaceHolder}"
               TextColor="Black"
               FontSize="Default"
               HeightRequest="{Binding EntryHeight}" />
    </Frame>
</StackLayout>

接下来,当用户点击 DONE 按钮时,我想将焦点从 Entry 切换到“下一个”元素,所以我这样做了:

    namespace Mynamespace.Components
    {
        public partial class FormEntry : StackLayout
        {
            public VisualElement NextFocus
            {
                get { return (VisualElement)GetValue(NextFocusProperty); }
                set { SetValue(NextFocusProperty, value); }
            }

            public static readonly BindableProperty NextFocusProperty =
                BindableProperty.Create(nameof(NextFocus),
                                        typeof(VisualElement),
                                        typeof(FormEntry),
                                        null,
                                     Xamarin.Forms.BindingMode.OneWay);

            public FormEntry()
            {
                InitializeComponent();
                BindingContext = this;

                mainEntry.Completed += (s, e) =>
                {
                    if (NextFocus != null)
                    {
                        NextFocus.Focus();
                    }
                };
            }
        }
    }

接下来,为了让 FormEntry 成为 NextFocus 的目标,我尝试添加

    this.Focused += (s,e) => { mainEntry.Focus(); };

到构造函数,但从不调用处理程序,我也尝试过覆盖

    public new void Focus() {
        mainEntry.Focus();
    }

但是这个方法永远不会被调用。布局类是 VisualElement 的后代,因此它们应该继承 Focused。布局对象有什么我缺少的吗?我可以理解 Layout 对象通常不是焦点目标,但事件处理程序应该在那里,所以我应该能够使用它。

这是我如何在登录屏幕上使用 FormEntry 的示例:

    <!-- Email -->
    <controls:FormEntry x:Name="usernameEntry"
                        Margin="25,40,25,0"
                        IsRequired="true"
                        EntryHeight="40"
                        KeybdType="Email"
                        NextFocus="{x:Reference passwordEntry}"
                        LabelText="{il8n:Translate Emailorusername}"
                        EntryPlaceHolder="{il8n:Translate EnterUsername}">
    </controls:FormEntry>

    <!-- Password -->
    <controls:FormEntry x:Name="passwordEntry"
                        Margin="25,0,25,0"
                        IsRequired="true"
                        EntryHeight="40"
                        LabelText="{il8n:Translate Password}"
                        EntryPlaceHolder="{il8n:Translate EnterPassword}" />

【问题讨论】:

  • 注意:如果 NextFocus 引用一个简单的 Entry 组件,上面的代码可以正常工作。我只是不知道如何捕捉 FormEntry 组件的 Focused 事件。
  • 你能在这里提供完整的演示吗?因为我对你的问题不是特别清楚。
  • 在我已经包含的示例 sn-p 中,登录屏幕,我的问题是:如何让用户从“u​​sernameEntry”FormEntry 组件切换到“passwordEntry”FormEntry 组件按下键盘完成按钮?如果“passwordEntry”只是一个条目,而不是我的 FormEntry 组件,那么一切正常:焦点从“usernameEntry”切换到“passwordEntry”;我无法让 FormEntry 获得焦点。

标签: forms xamarin layout focus


【解决方案1】:

我认为你已经获得了 nextfocus 元素,你可以从 nextfocus 获得 mainEntry,像这样:

 public FormEntry ()
    {
        InitializeComponent ();
        BindingContext = this;

        mainEntry.Completed += (s, e) =>
        {
            if (NextFocus != null)
            {
                FormEntry formentry = (FormEntry)NextFocus;
                Entry entry = formentry.mainEntry;
                entry.Focus();
            }
        };
    }

然后你会发现你会得到焦点。

【讨论】:

  • 我会接受这个答案。我已经考虑过了,但它没有涵盖下一个控件不是 FormEntry 的情况。但现在我已经考虑到,在移动应用程序中,其他类型的组件接收焦点可能没有意义(例如在 Windows 中)。
  • 您能帮忙找到下一个代码的解决方案吗?如何为标签触发 Focused 事件...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 2015-03-29
相关资源
最近更新 更多