【问题标题】:How to create placeholder with Editor control in Xamarin.Form?如何在 Xamarin.Form 中使用编辑器控件创建占位符?
【发布时间】:2018-03-15 07:35:41
【问题描述】:

我遇到了自定义控件EditorWithPlaceholder 的问题。它与文本重叠,当我单击内部时也不会删除,它不会删除占位符文本。

Xaml

<local:EditorWithPlaceholder Margin="0,16,0,0" WidthRequest="345" HeightRequest="119"
     Placeholder="This is test description of an editor with, placeholder control of Xamarin.Form. This is test description of an editor with, placeholder control of Xamarin.Form."
     />

自定义控件

public class EditorWithPlaceholder : Editor
{
    public static readonly BindableProperty PlaceholderProperty =
        BindableProperty.Create(nameof(Placeholder), typeof (string), typeof (string), string.Empty);

    public string Placeholder
    {
        get { return (string) GetValue(PlaceholderProperty); }
        set { SetValue(PlaceholderProperty, value); }
    }
}

渲染之一

public class BorderedEditorRenderer : EditorRenderer
{
    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e != null)
        {
            var textAttributes = new UIStringAttributes();

            textAttributes.Font = UIFont.FromName("SourceSansPro-Regular", 15);
            textAttributes.ForegroundColor = UIColor.Black;

            var attributedText = new NSAttributedString(Control.Text, textAttributes);
            Control.AttributedText = attributedText;

            if (_placeholder != null)
                _placeholder.Hidden = Control.HasText;
        }
    }

    UILabel _placeholder;

    protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            e.NewElement.SizeChanged += NewElementOnSizeChanged;

            Control.TextContainer.LineFragmentPadding = 16;

            Control.Layer.CornerRadius = 4.0f;
            Control.Layer.MasksToBounds = true;
            Control.Layer.BorderColor = UIColor.FromRGB(232, 232, 232).CGColor;
            Control.Layer.BorderWidth = 2.0f;
        }
    }

    private void NewElementOnSizeChanged(object sender, EventArgs eventArgs)
    {
        var editorWithPlaceholder = sender as EditorWithPlaceholder;
        if (editorWithPlaceholder != null)
        {
            var placeholderText = (Element as EditorWithPlaceholder).Placeholder;

            _placeholder = new UILabel(new CGRect(16.0, 8.0, Element.Width - 32.0, Element.HeightRequest - 24));
            _placeholder.Lines = 0;
            _placeholder.Text = placeholderText;
            _placeholder.Hidden = Control.HasText;

            var attributes = new UIStringAttributes();
            attributes.Font = UIFont.FromName("SourceSansPro-Regular", 15);
            attributes.ForegroundColor = UIColor.FromRGB(155, 155, 155);

            var attributedPlaceholder = new NSAttributedString(_placeholder.Text, attributes);

            _placeholder.AttributedText = attributedPlaceholder;

            Control.AddSubview(_placeholder);

            _placeholder.SizeToFit();
        }
    }
}

终于找到问题的原因了。原因是在 Grid 之一中添加动态控件。如果我删除ShowHobbies();,它将正常工作。

XAML 在同一页面上:

<Grid ColumnSpacing="0" Margin="17,15,17,0" x:Name="HobbiesGrid">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="auto" />
  </Grid.ColumnDefinitions>
</Grid>

XAML.CS 文件

protected override void OnAppearing()
{
    base.OnAppearing();
    ShowHobbies();
}

private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(_editProfileViewModel.HobbiesSuggestions) &&
        _editProfileViewModel.HobbiesSuggestions != null)
    {
      ShowHobbies();
    }
}

private void ShowHobbies()
{
    if (_editProfileViewModel.HobbiesSuggestions != null)
    {
        for (var i = 0; i < _editProfileViewModel.HobbiesSuggestions.Count(); i++)
        {
            var isEven = i % 2 == 0;
            if (isEven && HobbiesGrid.RowDefinitions.Count() < i / 2)
            {
                HobbiesGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            }
            var layout = new StackLayout();
            layout.Orientation = StackOrientation.Horizontal;
            var btn = new RoundRadioButton();
            btn.WidthRequest = 28;
            btn.HeightRequest = 28;
            btn.SetBinding(RoundRadioButton.IsPressedProperty,
                new Binding($"HobbiesSuggestions[{i}].Selected", BindingMode.TwoWay));
            layout.Children.Add(btn);
            var lbl = new Label();
            lbl.Text = _editProfileViewModel.HobbiesSuggestions[i].Name;
            lbl.Style = ResourceHelper<Style>.GetResource("CheckmarkLabel");
            layout.Children.Add(lbl);
            var localI = i;
            Device.BeginInvokeOnMainThread(
                () => { HobbiesGrid.Children.Add(layout, isEven ? 0 : 1, localI / 2); });
        }
    }
}

【问题讨论】:

  • 如果你调试代码,它会命中if (_placeholder != null)_placeholder.Hidden = Control.HasText;吗?
  • @Gusman 我刚刚检查过。它打了4次。前 3 次,_placeholder 为空。最后一次,它有一些价值。请提出建议。
  • @Developer 我在我这边测试你的代码,它工作正常。在这种情况下 placeHolder 将重叠。此外,当您创建 BindableProperty 时,将其修改为:BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(EditorWithPlaceholder), string.Empty);
  • @Gusman,我发现了问题,但不知道如何解决。我在最后添加了代码。如果我删除 ShowHobbies(); 方法,它将正常工作。我认为问题在于ShowHobbies(); 函数。请指导我。
  • @LandLu-MSFT 我发现了问题,但不知道如何解决。我在最后添加了代码。如果我删除 ShowHobbies(); 方法,它将正常工作。 ShowHobbies(); 方法动态添加爱好。请指导我。

标签: c# xamarin.forms xamarin.ios


【解决方案1】:

要在选择/单击控件时隐藏占位符文本,请使用本机控件UITextView Started eventhandler:

UILabel _placeholderLabel;

protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
  base.OnElementChanged(e);

  if (Control == null)
  {
    // Instantiate the native control and assign it to the Control property with
    // the SetNativeControl method
  }
  else
  {
    if (e.OldElement != null)
    {
      // Unsubscribe from event handlers and cleanup any resources
      Control.Started -= OnStarted;
    }

    if (e.NewElement != null)
    {
      // Configure the control and subscribe to event handlers
      _placeholderLabel = CreateLabel(); //not shown here
      Control.Started += OnStarted;
    }
  }
...
void OnStarted(object sender, EventArgs e)
{
  _placeholderLabel.Hidden = true;
}

另一个选项可能是在使用 Changed 事件处理程序输入文本时隐藏占位符文本:

      Control.Changed += OnChanged;
...
void OnChanged(object sender, EventArgs e)
{
  _placeholderLabel.Hidden = Control.HasText;
}

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 2020-11-03
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    • 2017-05-04
    • 2016-09-18
    相关资源
    最近更新 更多