-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,180 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
using System.ComponentModel; | ||
using Android.Content; | ||
using Android.Content.Res; | ||
using Android.Support.Design.Widget; | ||
using Android.Support.V4.View; | ||
using Android.Support.V7.Widget; | ||
using Android.Text; | ||
using Android.Text.Method; | ||
using Android.Util; | ||
using Android.Views; | ||
using Android.Views.InputMethods; | ||
using Android.Widget; | ||
using Java.Lang; | ||
using Xamarin.Forms; | ||
using Xamarin.Forms.Platform.Android; | ||
using Application = Android.App.Application; | ||
using Color = Xamarin.Forms.Color; | ||
using AColor = Android.Graphics.Color; | ||
using FormsAppCompat = Xamarin.Forms.Platform.Android.AppCompat; | ||
using Plugin.InputKit.Shared.Controls; | ||
using Plugin.InputKit.Platforms.Droid; | ||
using System.Collections.Specialized; | ||
using System.Collections.Generic; | ||
using System; | ||
using System.Linq; | ||
using System.Collections; | ||
using Android.Graphics.Drawables; | ||
|
||
[assembly: ExportRenderer(typeof(AutoCompleteView), typeof(AutoCompleteViewRenderer))] | ||
namespace Plugin.InputKit.Platforms.Droid | ||
{ | ||
public class AutoCompleteViewRenderer : FormsAppCompat.ViewRenderer<AutoCompleteView, TextInputLayout> | ||
{ | ||
public AutoCompleteViewRenderer(Context context) : base(context) | ||
{ | ||
} | ||
|
||
private AppCompatAutoCompleteTextView AutoComplete => Control?.EditText as AppCompatAutoCompleteTextView; | ||
|
||
protected override TextInputLayout CreateNativeControl() | ||
{ | ||
var textInputLayout = new TextInputLayout(Context); | ||
var autoComplete = new AppCompatAutoCompleteTextView(Context) | ||
{ | ||
BackgroundTintList = ColorStateList.ValueOf(GetPlaceholderColor()) | ||
}; | ||
|
||
GradientDrawable gd = new GradientDrawable(); | ||
gd.SetColor(global::Android.Graphics.Color.Transparent); | ||
autoComplete.SetBackground(gd); | ||
|
||
textInputLayout.AddView(autoComplete); | ||
return textInputLayout; | ||
} | ||
|
||
protected override void OnElementChanged(ElementChangedEventArgs<AutoCompleteView> e) | ||
{ | ||
base.OnElementChanged(e); | ||
if (e.OldElement != null) | ||
{ | ||
// unsubscribe | ||
AutoComplete.ItemClick -= AutoCompleteOnItemSelected; | ||
var elm = e.OldElement; | ||
elm.CollectionChanged -= ItemsSourceCollectionChanged; | ||
} | ||
|
||
if (e.NewElement != null) | ||
{ | ||
SetNativeControl(CreateNativeControl()); | ||
// subscribe | ||
SetItemsSource(); | ||
SetThreshold(); | ||
KillPassword(); | ||
AutoComplete.ItemClick += AutoCompleteOnItemSelected; | ||
var elm = e.NewElement; | ||
elm.CollectionChanged += ItemsSourceCollectionChanged; | ||
} | ||
} | ||
|
||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) | ||
{ | ||
base.OnElementPropertyChanged(sender, e); | ||
|
||
if (e.PropertyName == Entry.IsPasswordProperty.PropertyName) | ||
KillPassword(); | ||
if (e.PropertyName == AutoCompleteView.ItemsSourceProperty.PropertyName) | ||
SetItemsSource(); | ||
else if (e.PropertyName == AutoCompleteView.ThresholdProperty.PropertyName) | ||
SetThreshold(); | ||
} | ||
|
||
private void AutoCompleteOnItemSelected(object sender, AdapterView.ItemClickEventArgs args) | ||
{ | ||
var view = (AutoCompleteTextView)sender; | ||
var selectedItemArgs = new SelectedItemChangedEventArgs(view.Text); | ||
var element = (AutoCompleteView)Element; | ||
element.OnItemSelectedInternal(Element, selectedItemArgs); | ||
} | ||
|
||
private void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) | ||
{ | ||
var element = (AutoCompleteView)Element; | ||
ResetAdapter(element); | ||
} | ||
|
||
private void KillPassword() | ||
{ | ||
if (Element.IsPassword) | ||
throw new NotImplementedException("Cannot set IsPassword on a AutoComplete"); | ||
} | ||
|
||
private void ResetAdapter(AutoCompleteView element) | ||
{ | ||
var adapter = new BoxArrayAdapter(Context, | ||
Android.Resource.Layout.SimpleDropDownItem1Line, | ||
element.ItemsSource.ToList(), | ||
element.SortingAlgorithm); | ||
AutoComplete.Adapter = adapter; | ||
adapter.NotifyDataSetChanged(); | ||
} | ||
|
||
private void SetItemsSource() | ||
{ | ||
var element = (AutoCompleteView)Element; | ||
if (element.ItemsSource == null) return; | ||
|
||
ResetAdapter(element); | ||
} | ||
|
||
private void SetThreshold() | ||
{ | ||
var element = (AutoCompleteView)Element; | ||
AutoComplete.Threshold = element.Threshold; | ||
} | ||
|
||
#region Section 2 | ||
protected AColor GetPlaceholderColor() => Element.PlaceholderColor.ToAndroid(Color.FromHex("#80000000")); | ||
#endregion | ||
} | ||
|
||
internal class BoxArrayAdapter : ArrayAdapter | ||
{ | ||
private readonly IList<string> _objects; | ||
private readonly Func<string, ICollection<string>, ICollection<string>> _sortingAlgorithm; | ||
|
||
public BoxArrayAdapter( | ||
Context context, | ||
int textViewResourceId, | ||
List<string> objects, | ||
Func<string, ICollection<string>, ICollection<string>> sortingAlgorithm) : base(context, textViewResourceId, objects) | ||
{ | ||
_objects = objects; | ||
_sortingAlgorithm = sortingAlgorithm; | ||
} | ||
|
||
public override Filter Filter | ||
{ | ||
get | ||
{ | ||
return new CustomFilter(_sortingAlgorithm) { Adapter = this, Originals = _objects }; | ||
} | ||
} | ||
} | ||
|
||
internal class CustomFilter : Filter | ||
{ | ||
private readonly Func<string, ICollection<string>, ICollection<string>> _sortingAlgorithm; | ||
|
||
public CustomFilter(Func<string, ICollection<string>, ICollection<string>> sortingAlgorithm) | ||
{ | ||
_sortingAlgorithm = sortingAlgorithm; | ||
} | ||
|
||
public BoxArrayAdapter Adapter { private get; set; } | ||
public IList<string> Originals { get; set; } | ||
|
||
protected override FilterResults PerformFiltering(ICharSequence constraint) | ||
{ | ||
var results = new FilterResults(); | ||
if (constraint == null || constraint.Length() == 0) | ||
{ | ||
results.Values = new Java.Util.ArrayList(Originals.ToList()); | ||
results.Count = Originals.Count; | ||
} | ||
else | ||
{ | ||
var values = new Java.Util.ArrayList(); | ||
var sorted = _sortingAlgorithm(constraint.ToString(), Originals).ToList(); | ||
|
||
for (var index = 0; index < sorted.Count; index++) | ||
{ | ||
var item = sorted[index]; | ||
values.Add(item); | ||
} | ||
|
||
results.Values = values; | ||
results.Count = sorted.Count; | ||
} | ||
|
||
return results; | ||
} | ||
|
||
protected override void PublishResults(ICharSequence constraint, FilterResults results) | ||
{ | ||
if (results.Count == 0) | ||
Adapter.NotifyDataSetInvalidated(); | ||
else | ||
{ | ||
Adapter.Clear(); | ||
var vals = (Java.Util.ArrayList)results.Values; | ||
foreach (var val in vals.ToArray()) | ||
{ | ||
Adapter.Add(val); | ||
} | ||
Adapter.NotifyDataSetChanged(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
using CoreGraphics; | ||
using Plugin.InputKit.Platforms.iOS; | ||
using Plugin.InputKit.Platforms.iOS.Controls; | ||
using Plugin.InputKit.Platforms.iOS.Helpers; | ||
using Plugin.InputKit.Shared.Controls; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Specialized; | ||
using System.ComponentModel; | ||
using System.Drawing; | ||
using System.Linq; | ||
using System.Text; | ||
using UIKit; | ||
using Xamarin.Forms; | ||
using Xamarin.Forms.Platform.iOS; | ||
|
||
[assembly: ExportRenderer(typeof(AutoCompleteView), typeof(AutoCompleteViewRenderer))] | ||
namespace Plugin.InputKit.Platforms.iOS | ||
{ | ||
public class AutoCompleteViewRenderer : ViewRenderer<AutoCompleteView, UITextField> | ||
{ | ||
private MbAutoCompleteTextField NativeControl => (MbAutoCompleteTextField)Control; | ||
private AutoCompleteView AutoCompleteEntry => (AutoCompleteView)Element; | ||
|
||
public AutoCompleteViewRenderer() | ||
{ | ||
// ReSharper disable once VirtualMemberCallInContructor | ||
Frame = new RectangleF(0, 20, 320, 40); | ||
} | ||
|
||
protected override UITextField CreateNativeControl() | ||
{ | ||
var element = (AutoCompleteView)Element; | ||
var view = new MbAutoCompleteTextField | ||
{ | ||
AutoCompleteViewSource = new MbAutoCompleteDefaultDataSource(), | ||
SortingAlgorithm = element.SortingAlgorithm | ||
}; | ||
view.AutoCompleteViewSource.Selected += AutoCompleteViewSourceOnSelected; | ||
return view; | ||
} | ||
public override void Draw(CGRect rect) | ||
{ | ||
base.Draw(rect); | ||
var scrollView = GetParentScrollView(Control); | ||
var ctrl = UIApplication.SharedApplication.GetTopViewController(); | ||
NativeControl.Draw(ctrl, Layer, scrollView); | ||
} | ||
|
||
protected override void OnElementChanged(ElementChangedEventArgs<AutoCompleteView> e) | ||
{ | ||
base.OnElementChanged(e); | ||
if (e.OldElement != null) | ||
{ | ||
// unsubscribe | ||
NativeControl.AutoCompleteViewSource.Selected -= AutoCompleteViewSourceOnSelected; | ||
var elm = (AutoCompleteView)e.OldElement; | ||
elm.CollectionChanged -= ItemsSourceCollectionChanged; | ||
} | ||
|
||
if (e.NewElement != null) | ||
{ | ||
SetNativeControl(CreateNativeControl()); | ||
SetItemsSource(); | ||
SetThreshold(); | ||
KillPassword(); | ||
|
||
var elm = (AutoCompleteView)e.NewElement; | ||
elm.CollectionChanged += ItemsSourceCollectionChanged; | ||
} | ||
} | ||
|
||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) | ||
{ | ||
base.OnElementPropertyChanged(sender, e); | ||
|
||
if (e.PropertyName == Entry.IsPasswordProperty.PropertyName) | ||
KillPassword(); | ||
if (e.PropertyName == AutoCompleteView.ItemsSourceProperty.PropertyName) | ||
SetItemsSource(); | ||
else if (e.PropertyName == AutoCompleteView.ThresholdProperty.PropertyName) | ||
SetThreshold(); | ||
} | ||
|
||
private void SetThreshold() | ||
{ | ||
NativeControl.Threshold = AutoCompleteEntry.Threshold; | ||
} | ||
|
||
private void SetItemsSource() | ||
{ | ||
if (AutoCompleteEntry.ItemsSource != null) | ||
{ | ||
var items = AutoCompleteEntry.ItemsSource.ToList(); | ||
NativeControl.UpdateItems(items); | ||
} | ||
} | ||
|
||
private void KillPassword() | ||
{ | ||
if (Element.IsPassword) | ||
throw new NotImplementedException("Cannot set IsPassword on a AutoCompleteEntry"); | ||
} | ||
|
||
private void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) | ||
{ | ||
SetItemsSource(); | ||
} | ||
|
||
private static UIScrollView GetParentScrollView(UIView element) | ||
{ | ||
if (element.Superview == null) return null; | ||
var scrollView = element.Superview as UIScrollView; | ||
return scrollView ?? GetParentScrollView(element.Superview); | ||
} | ||
|
||
private void AutoCompleteViewSourceOnSelected(object sender, SelectedItemChangedEventArgs args) | ||
{ | ||
AutoCompleteEntry.OnItemSelectedInternal(Element, args); | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
InputKit/Platforms/iOS/Controls/MbAutoCompleteTableView.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using UIKit; | ||
|
||
namespace Plugin.InputKit.Platforms.iOS.Controls | ||
{ | ||
internal class MbAutoCompleteTableView : UITableView | ||
{ | ||
private readonly UIScrollView _parentScrollView; | ||
|
||
public MbAutoCompleteTableView(UIScrollView parentScrollView) | ||
{ | ||
_parentScrollView = parentScrollView; | ||
} | ||
|
||
public override bool Hidden | ||
{ | ||
get { return base.Hidden; } | ||
set | ||
{ | ||
base.Hidden = value; | ||
if (_parentScrollView == null) return; | ||
_parentScrollView.DelaysContentTouches = !value; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.