如何在Xamarin.Form中使用Editor控件创建占位符?

时间:2018-03-09 12:40:31

标签: c# xamarin.forms xamarin.ios

我遇到自定义控件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();
        }
    }
}

enter image description here

最后我找到了问题的原因。原因是在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); });
        }
    }
}

1 个答案:

答案 0 :(得分:1)

要在选择/单击控件时隐藏占位符文本,请使用本机Control 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;
}