2016-07-17 3 views
7

Я новичок в платформе Xamarin.Forms. Надеюсь, ты поможешь мне двигаться вперед. Я хочу иметь контроль как автозаполнение в xamarin.forms как нижеXamarin.Forms Autocomplete CrossPlatform

Autocomplete

Можете ли вы руководство, как это может быть достижимо в Xamarin.Forms? Я хочу, чтобы достичь его с помощью входа управления

ТИА

+1

Пожалуйста, в следующий раз напишите код, который вы пробовали, или даже некоторые идеи, которые у вас есть для того, чего вы хотите достичь. – Imdad

ответ

6

Вы не включили то, что именно вы хотите, просто какой-то автозаполнения.

Я буду буллит ручной способ сделать это в целом для списка элементов:

  1. Используйте TextBox, чтобы позволить пользователю вводить текст.
  2. Используйте Список, чтобы собрать все ваши объекты вместе с их возможностью поиска, например, именем объекта.
  3. Поскольку пользователь вводит что-то в TextBox, приложение должно искать в списке для строки, введенной в TextBox.
  4. Предложения должны отображаться в соответствии с введенным значением String в ListView под TextBox.
  5. Пользователь нажимает на элемент ListView, который является предложением, а затем этот автозаполняется, принимая объект Name из элемента, нажатого на TextBox.

Общий способ выполнения автозаполнения без длительной процедуры, описанной выше, заключается в использовании Android AutoCompleteTextView.

Вы все еще можете использовать основную логику для этого в Xamarin Forms.

Посмотрите here на AutoCompleteTextView для Android. Посмотрите here, here и here за помощью с автозавершением в формах Xamarin.

+0

Я прошел через AutoCompleteTextView, но в Xamarin.iOS нет обеспечения автозаполнения? У вас есть мысли по этому поводу. –

+0

@ManojSethi Это тот же принцип, что и в ручном способе его выполнения. Эти компоненты также доступны в Xamarin.iOS. :) – Imdad

2

Прочтите эти статьи и попробуйте реализовать решение на Xamarin.Forms с помощью Custom Renderers.

Google Place API with Autocomplete in Xamarin Android

Xamarin.iOS Location Autocomplete by using Google Place API

+0

Извините, это не формы Xamarin, на которые был поставлен вопрос. Это все родной андроид. – peterincumbria

+0

Речь идет о Custom Renderers, так что это связано с Xamarin.Forms тоже. –

1

Я реализовал AutocompleteView в моем проекте. Вы можете направить его.

public class AutoCompleteView : ContentView 
{ 
    public static readonly BindableProperty SuggestionsProperty = BindableProperty.Create(nameof(Suggestions), typeof(IEnumerable), typeof(AutoCompleteView), null, BindingMode.OneWay, null, OnSuggestionsChanged); 
    public static readonly BindableProperty SearchTextProperty = BindableProperty.Create(nameof(SearchText), typeof(string), typeof(AutoCompleteView), null, BindingMode.TwoWay, null, OnSearchTextChanged); 
    public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(AutoCompleteView), null, BindingMode.OneWay, null, OnPlaceholderChanged); 
    public static readonly BindableProperty MaximumVisibleSuggestionItemsProperty = BindableProperty.Create(nameof(MaximumVisibleSuggestionItems), typeof(int), typeof(AutoCompleteView), 4); 
    public static readonly BindableProperty SuggestionItemTemplateProperty = BindableProperty.Create(nameof(SuggestionItemTemplate), typeof(DataTemplate), typeof(AutoCompleteView), null, BindingMode.OneWay, null, OnSuggestionItemTemplateChanged); 
    public static readonly BindableProperty DisplayPropertyNameProperty = BindableProperty.Create(nameof(DisplayPropertyName), typeof(string), typeof(AutoCompleteView)); 

    public IEnumerable Suggestions 
    { 
     get { return (IEnumerable)GetValue(SuggestionsProperty); } 
     set { SetValue(SuggestionsProperty, value); } 
    } 

    public string SearchText 
    { 
     get { return (string)GetValue(SearchTextProperty); } 
     set { SetValue(SearchTextProperty, value); } 
    } 

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

    public int MaximumVisibleSuggestionItems 
    { 
     get { return (int)GetValue(MaximumVisibleSuggestionItemsProperty); } 
     set { SetValue(MaximumVisibleSuggestionItemsProperty, value); } 
    } 

    public DataTemplate SuggestionItemTemplate 
    { 
     get { return (DataTemplate)GetValue(SuggestionItemTemplateProperty); } 
     set { SetValue(SuggestionItemTemplateProperty, value); } 
    } 

    public string DisplayPropertyName 
    { 
     get { return (string)GetValue(DisplayPropertyNameProperty); } 
     set { SetValue(DisplayPropertyNameProperty, value); } 
    } 

    public ItemsStack SuggestionsListView { get; private set; } 
    public Entry SearchEntry { get; private set; } 
    public IEnumerable OriginSuggestions { get; private set; } 
    public NestedScrollView SuggestionWrapper { get; private set; } 
    public Grid Container { get; private set; } 

    public bool IsSelected { get; private set; } 
    public int TotalNumberOfTypings { get; private set; } 

    private static void OnSuggestionsChanged(object bindable, object oldValue, object newValue) 
    { 
     var autoCompleteView = bindable as AutoCompleteView; 

     var suggestions = (IEnumerable)newValue; 
     autoCompleteView.OriginSuggestions = suggestions; 

     suggestions = autoCompleteView.FilterSuggestions(suggestions, autoCompleteView.SearchText); 
     autoCompleteView.SuggestionsListView.ItemsSource = suggestions; 
    } 

    private static void OnSearchTextChanged(object bindable, object oldValue, object newValue) 
    { 
     var autoCompleteView = bindable as AutoCompleteView; 

     var suggestions = autoCompleteView.OriginSuggestions; 
     if (newValue != null) 
     { 
      suggestions = autoCompleteView.FilterSuggestions(suggestions, autoCompleteView.SearchText); 
      // assign when initializing with data 
      if (autoCompleteView.SearchEntry.Text != autoCompleteView.SearchText) 
      { 
       autoCompleteView.SearchEntry.Text = autoCompleteView.SearchText; 
      } 
     } 
     autoCompleteView.SuggestionsListView.ItemsSource = suggestions; 

     if (Device.OS == TargetPlatform.Android) 
     { 
      // update the layout -> only do this when user is typing instead of selection an item from suggestions list 
      // -> prevent duplicated update layout 
      if (!autoCompleteView.IsSelected) 
      { 
       autoCompleteView.UpdateLayout(); 
      } 
      else 
      { 
       autoCompleteView.IsSelected = false; 
      } 
     } 
    } 

    private static void OnSuggestionItemTemplateChanged(object bindable, object oldValue, object newValue) 
    { 
     var autoCompleteView = bindable as AutoCompleteView; 

     if (autoCompleteView.SuggestionsListView != null) 
     { 
      autoCompleteView.SuggestionsListView.ItemTemplate = autoCompleteView.SuggestionItemTemplate; 
     } 
    } 

    public IEnumerable FilterSuggestions(IEnumerable suggestions, string keyword) 
    { 
     if (string.IsNullOrEmpty(keyword) || suggestions == null) return suggestions; 

     var searchWords = keyword.ConvertToNonMark().ToLower().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); 
     var result = suggestions.Cast<object>(); 
     foreach (var item in searchWords) 
     { 
      if (!string.IsNullOrEmpty(DisplayPropertyName)) 
      { 
       result = result.Where(x => x.GetType().GetRuntimeProperty(DisplayPropertyName).GetValue(x).ToString().ConvertToNonMark().ToLower().Contains(item)).ToList(); 
      } 
      else 
      { 
       result = result.Where(x => x.ToString().ConvertToNonMark().ToLower().Contains(item)).ToList(); 
      } 
     } 

     return result; 
    } 

    private static void OnPlaceholderChanged(object bindable, object oldValue, object newValue) 
    { 
     var autoCompleteView = bindable as AutoCompleteView; 
     autoCompleteView.SearchEntry.Placeholder = newValue?.ToString(); 
    } 

    public void UpdateLayout() 
    { 
     var expectedHeight = this.getExpectedHeight(); 
     Container.HeightRequest = expectedHeight; 
     Container.ForceLayout(); 
    } 

    private void SearchEntry_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     TotalNumberOfTypings++; 
     Device.StartTimer(TimeSpan.FromMilliseconds(1000),() => { 
      TotalNumberOfTypings--; 
      if (TotalNumberOfTypings == 0) 
      { 
       SearchText = e.NewTextValue; 
      } 
      return false; 
     }); 
    } 

    private void SearchEntry_Focused(object sender, FocusEventArgs e) 
    { 
     UpdateLayout(); 
     IsSelected = false; 
    } 

    private void SearchEntry_Unfocused(object sender, FocusEventArgs e) 
    { 
     Container.HeightRequest = 50; 
     Container.ForceLayout(); 
    } 

    private void SuggestionsListView_ItemSelected(object sender, ItemTappedEventArgs e) 
    { 
     IsSelected = true; 
     SearchEntry.Text = !string.IsNullOrEmpty(DisplayPropertyName) ? e.Item?.GetType()?.GetRuntimeProperty(DisplayPropertyName)?.GetValue(e.Item)?.ToString() : e.Item?.ToString(); 
     Container.HeightRequest = 50; 
     Container.ForceLayout(); 
    } 

    private void OverlapContentView_Tapped(object sender, TappedEventArgs e) 
    { 
     UpdateLayout(); 
     IsSelected = false; 

    } 

    private int getExpectedHeight() 
    { 
     var items = SuggestionsListView.ItemsSource as IList; 
     int wrapperHeightRequest = items != null ? 
      (items.Count >= MaximumVisibleSuggestionItems ? MaximumVisibleSuggestionItems * 40 : items.Count * 40) : 0; 
     if (Device.OS == TargetPlatform.Android) 
     { 
      return wrapperHeightRequest + 50; 
     } 
     return MaximumVisibleSuggestionItems * 40 + 50; 
    } 

    public AutoCompleteView() 
    { 
     Container = new Grid(); 
     SearchEntry = new Entry(); 
     SuggestionsListView = new ItemsStack(); 
     SuggestionWrapper = new NestedScrollView(); 

     // init Grid Layout 
     Container.RowSpacing = 0; 
     Container.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star }); 
     Container.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Star }); 
     Container.RowDefinitions.Add(new RowDefinition() { Height = 50 }); 
     Container.HeightRequest = 50; 

     // init Search Entry 
     SearchEntry.HorizontalOptions = LayoutOptions.Fill; 
     SearchEntry.VerticalOptions = LayoutOptions.Fill; 
     SearchEntry.TextChanged += SearchEntry_TextChanged; 
     SearchEntry.Unfocused += SearchEntry_Unfocused; 
     SearchEntry.Focused += SearchEntry_Focused; 

     // init Suggestions ListView 
     SuggestionsListView.BackgroundColor = Color.White; 
     SuggestionsListView.ItemTapped += SuggestionsListView_ItemSelected; 
     SuggestionsListView.VerticalOptions = LayoutOptions.End; 
     SuggestionsListView.Spacing = 1; 

     // suggestions Listview's wrapper 
     SuggestionWrapper.VerticalOptions = LayoutOptions.Fill; 
     SuggestionWrapper.Orientation = ScrollOrientation.Vertical; 
     SuggestionWrapper.BackgroundColor = Color.White; 
     SuggestionWrapper.Content = SuggestionsListView; 

     Container.Children.Add(SuggestionWrapper); 
     Container.Children.Add(SearchEntry, 0, 1); 

     this.Content = Container; 
    } 
} 

Пример использования:

<customControls:AutoCompleteView SearchText="{Binding User.UniversitySchool}" Suggestions="{Binding Schools}" DisplayPropertyName="Name" Placeholder="Please choose your school"> 
        <customControls:AutoCompleteView.SuggestionItemTemplate> 
         <DataTemplate> 
          <ContentView Padding="10"> 
           <Label Text="{Binding Name}" HeightRequest="20" LineBreakMode="HeadTruncation" Style="{StaticResource MainContentLabel}" /> 
          </ContentView> 
         </DataTemplate> 
        </customControls:AutoCompleteView.SuggestionItemTemplate> 
       </customControls:AutoCompleteView> 

С этой точки зрения, я использовал контроль ItemStack. Вы можете сослаться на это: https://gist.github.com/NVentimiglia/2723411428cdbb72fac6

+0

Где находится NestedScrollView? Это только для Android или PCL? –

+0

Ah ... Вы должны создать пользовательский вид NestedScrollView и рендеринга для него (только для Android). Затем вы устанавливаете собственный атрибут NestedScrollingEnabled = true (см. Https://developer.xamarin.com/api/property/Android.Views.View.NestedScrollingEnabled/). Если у вас нет этого класса, список вариантов автозаполнения нельзя прокручивать. –

+0

@ Quý Nguyễn Nam, у вас есть код для NestedScrollView – Wes

Смежные вопросы