diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Platform.Android/Cells | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Platform.Android/Cells')
11 files changed, 1062 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs b/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs new file mode 100644 index 00000000..7855b01e --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs @@ -0,0 +1,208 @@ +using System.IO; +using System.Threading.Tasks; +using Android.Content; +using Android.Graphics; +using Android.Text; +using Android.Views; +using Android.Widget; +using AView = Android.Views.View; +using AColor = Android.Graphics.Color; +using AColorDraw = Android.Graphics.Drawables.ColorDrawable; + +namespace Xamarin.Forms.Platform.Android +{ + public class BaseCellView : LinearLayout, INativeElementView + { + public const double DefaultMinHeight = 44; + + readonly Color _androidDefaultTextColor; + readonly Cell _cell; + readonly TextView _detailText; + readonly ImageView _imageView; + readonly TextView _mainText; + Color _defaultDetailColor; + Color _defaultMainTextColor; + Color _detailTextColor; + string _detailTextText; + ImageSource _imageSource; + Color _mainTextColor; + string _mainTextText; + + public BaseCellView(Context context, Cell cell) : base(context) + { + _cell = cell; + SetMinimumWidth((int)context.ToPixels(25)); + SetMinimumHeight((int)context.ToPixels(25)); + Orientation = Orientation.Horizontal; + + var padding = (int)context.FromPixels(8); + SetPadding(padding, padding, padding, padding); + + _imageView = new ImageView(context); + var imageParams = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.FillParent) + { + Width = (int)context.ToPixels(60), + Height = (int)context.ToPixels(60), + RightMargin = 0, + Gravity = GravityFlags.Center + }; + using(imageParams) + AddView(_imageView, imageParams); + + var textLayout = new LinearLayout(context) { Orientation = Orientation.Vertical }; + + _mainText = new TextView(context); + _mainText.SetSingleLine(true); + _mainText.Ellipsize = TextUtils.TruncateAt.End; + _mainText.SetPadding((int)context.ToPixels(15), padding, padding, padding); + _mainText.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItem); + using(var lp = new LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent)) + textLayout.AddView(_mainText, lp); + + _detailText = new TextView(context); + _detailText.SetSingleLine(true); + _detailText.Ellipsize = TextUtils.TruncateAt.End; + _detailText.SetPadding((int)context.ToPixels(15), padding, padding, padding); + _detailText.Visibility = ViewStates.Gone; + _detailText.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItemSmall); + using(var lp = new LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent)) + textLayout.AddView(_detailText, lp); + + var layoutParams = new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent) { Width = 0, Weight = 1, Gravity = GravityFlags.Center }; + + using(layoutParams) + AddView(textLayout, layoutParams); + + SetMinimumHeight((int)context.ToPixels(DefaultMinHeight)); + _androidDefaultTextColor = Color.FromUint((uint)_mainText.CurrentTextColor); + } + + public AView AccessoryView { get; private set; } + + public string DetailText + { + get { return _detailTextText; } + set + { + if (_detailTextText == value) + return; + + _detailTextText = value; + _detailText.Text = value; + _detailText.Visibility = string.IsNullOrEmpty(value) ? ViewStates.Gone : ViewStates.Visible; + } + } + + public string MainText + { + get { return _mainTextText; } + set + { + if (_mainTextText == value) + return; + + _mainTextText = value; + _mainText.Text = value; + } + } + + Element INativeElementView.Element + { + get { return _cell; } + } + + public void SetAccessoryView(AView view) + { + if (AccessoryView != null) + RemoveView(AccessoryView); + + if (view != null) + { + using(var layout = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.FillParent)) + AddView(view, layout); + + AccessoryView = view; + } + } + + public void SetDefaultMainTextColor(Color defaultColor) + { + _defaultMainTextColor = defaultColor; + if (_mainTextColor == Color.Default) + _mainText.SetTextColor(defaultColor.ToAndroid()); + } + + public void SetDetailTextColor(Color color) + { + if (_detailTextColor == color) + return; + + if (_defaultDetailColor == Color.Default) + _defaultDetailColor = Color.FromUint((uint)_detailText.CurrentTextColor); + + _detailTextColor = color; + _detailText.SetTextColor(color.ToAndroid(_defaultDetailColor)); + } + + public void SetImageSource(ImageSource source) + { + UpdateBitmap(source, _imageSource); + _imageSource = source; + } + + public void SetImageVisible(bool visible) + { + _imageView.Visibility = visible ? ViewStates.Visible : ViewStates.Gone; + } + + public void SetIsEnabled(bool isEnable) + { + _mainText.Enabled = isEnable; + _detailText.Enabled = isEnable; + } + + public void SetMainTextColor(Color color) + { + Color defaultColorToSet = _defaultMainTextColor == Color.Default ? _androidDefaultTextColor : _defaultMainTextColor; + + _mainTextColor = color; + _mainText.SetTextColor(color.ToAndroid(defaultColorToSet)); + } + + public void SetRenderHeight(double height) + { + height = Context.ToPixels(height); + LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.MatchParent, (int)(height == -1 ? ViewGroup.LayoutParams.WrapContent : height)); + } + + async void UpdateBitmap(ImageSource source, ImageSource previousSource = null) + { + if (Equals(source, previousSource)) + return; + + _imageView.SetImageResource(global::Android.Resource.Color.Transparent); + + Bitmap bitmap = null; + + IImageSourceHandler handler; + + if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null) + { + try + { + bitmap = await handler.LoadImageAsync(source, Context); + } + catch (TaskCanceledException) + { + } + catch (IOException e) + { + } + } + + _imageView.SetImageBitmap(bitmap); + if (bitmap != null) + bitmap.Dispose(); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs b/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs new file mode 100644 index 00000000..589236c3 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs @@ -0,0 +1,41 @@ +using Android.Content; +using Android.Views; +using AView = Android.Views.View; +using AListView = Android.Widget.ListView; + +namespace Xamarin.Forms.Platform.Android +{ + public static class CellFactory + { + public static AView GetCell(Cell item, AView convertView, ViewGroup parent, Context context, View view) + { + CellRenderer renderer = CellRenderer.GetRenderer(item); + if (renderer == null) + { + renderer = Registrar.Registered.GetHandler<CellRenderer>(item.GetType()); + renderer.ParentView = view; + } + + AView result = renderer.GetCell(item, convertView, parent, context); + + if (view is TableView) + UpdateMinimumHeightFromParent(context, result, (TableView)view); + else if (view is ListView) + UpdateMinimumHeightFromParent(context, result, (ListView)view); + + return result; + } + + static void UpdateMinimumHeightFromParent(Context context, AView view, TableView table) + { + if (!table.HasUnevenRows && table.RowHeight > 0) + view.SetMinimumHeight((int)context.ToPixels(table.RowHeight)); + } + + static void UpdateMinimumHeightFromParent(Context context, AView view, ListView listView) + { + if (!listView.HasUnevenRows && listView.RowHeight > 0) + view.SetMinimumHeight((int)context.ToPixels(listView.RowHeight)); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs new file mode 100644 index 00000000..d9d4eee5 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs @@ -0,0 +1,131 @@ +using System; +using System.ComponentModel; +using Android.Content; +using Android.Views; +using Android.Widget; +using AView = Android.Views.View; +using Object = Java.Lang.Object; + +namespace Xamarin.Forms.Platform.Android +{ + public class CellRenderer : IRegisterable + { + static readonly PropertyChangedEventHandler PropertyChangedHandler = OnGlobalCellPropertyChanged; + + static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(CellRenderer), typeof(Cell), null); + + EventHandler _onForceUpdateSizeRequested; + + public View ParentView { get; set; } + + protected Cell Cell { get; set; } + + public AView GetCell(Cell item, AView convertView, ViewGroup parent, Context context) + { + Performance.Start(); + + Cell = item; + Cell.PropertyChanged -= PropertyChangedHandler; + + SetRenderer(Cell, this); + + if (convertView != null) + { + Object tag = convertView.Tag; + var renderHolder = tag as RendererHolder; + if (renderHolder != null) + { + Cell oldCell = renderHolder.Renderer.Cell; + oldCell.SendDisappearing(); + + if (Cell != oldCell) + SetRenderer(oldCell, null); + } + } + + AView view = GetCellCore(item, convertView, parent, context); + + WireUpForceUpdateSizeRequested(item, view); + + var holder = view.Tag as RendererHolder; + if (holder == null) + view.Tag = new RendererHolder { Renderer = this }; + else + holder.Renderer = this; + + Cell.PropertyChanged += PropertyChangedHandler; + Cell.SendAppearing(); + + Performance.Stop(); + + return view; + } + + protected virtual AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context) + { + Performance.Start(); + + LayoutInflater inflater = LayoutInflater.FromContext(context); + const int type = global::Android.Resource.Layout.SimpleListItem1; + AView view = inflater.Inflate(type, null); + + var textView = view.FindViewById<TextView>(global::Android.Resource.Id.Text1); + textView.Text = item.ToString(); + textView.SetBackgroundColor(global::Android.Graphics.Color.Transparent); + view.SetBackgroundColor(global::Android.Graphics.Color.Black); + + Performance.Stop(); + + return view; + } + + protected virtual void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + } + + protected void WireUpForceUpdateSizeRequested(Cell cell, AView nativeCell) + { + cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested; + + _onForceUpdateSizeRequested = delegate + { + // RenderHeight may not be changed, but that's okay, since we + // don't actually use the height argument in the OnMeasure override. + nativeCell.Measure(nativeCell.Width, (int)cell.RenderHeight); + nativeCell.SetMinimumHeight(nativeCell.MeasuredHeight); + nativeCell.SetMinimumWidth(nativeCell.MeasuredWidth); + }; + + cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested; + } + + internal static CellRenderer GetRenderer(BindableObject cell) + { + return (CellRenderer)cell.GetValue(RendererProperty); + } + + internal static void SetRenderer(BindableObject cell, CellRenderer renderer) + { + cell.SetValue(RendererProperty, renderer); + } + + static void OnGlobalCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var cell = (Cell)sender; + CellRenderer renderer = GetRenderer(cell); + if (renderer == null) + { + cell.PropertyChanged -= PropertyChangedHandler; + return; + } + + renderer.OnCellPropertyChanged(sender, e); + ; + } + + class RendererHolder : Object + { + public CellRenderer Renderer; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs new file mode 100644 index 00000000..287804ba --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs @@ -0,0 +1,45 @@ +using System; +using Android.App; +using Android.Content; +using Android.Graphics; +using Android.Views; +using Android.Widget; + +namespace Xamarin.Forms.Platform.Android +{ + public sealed class EntryCellEditText : EditText + { + SoftInput _startingMode; + + public EntryCellEditText(Context context) : base(context) + { + } + + public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e) + { + if (keyCode == Keycode.Back && e.Action == KeyEventActions.Down) + { + EventHandler handler = BackButtonPressed; + if (handler != null) + handler(this, EventArgs.Empty); + } + return base.OnKeyPreIme(keyCode, e); + } + + protected override void OnFocusChanged(bool gainFocus, FocusSearchDirection direction, Rect previouslyFocusedRect) + { + Window window = ((Activity)Context).Window; + if (gainFocus) + { + _startingMode = window.Attributes.SoftInputMode; + window.SetSoftInputMode(SoftInput.AdjustPan); + } + else + window.SetSoftInputMode(_startingMode); + + base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect); + } + + internal event EventHandler BackButtonPressed; + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs new file mode 100644 index 00000000..00330928 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs @@ -0,0 +1,119 @@ +using System.ComponentModel; +using Android.Content; +using Android.Views; + +namespace Xamarin.Forms.Platform.Android +{ + public class EntryCellRenderer : CellRenderer + { + EntryCellView _view; + + protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context) + { + if ((_view = convertView as EntryCellView) == null) + _view = new EntryCellView(context, item); + else + { + _view.TextChanged = null; + _view.FocusChanged = null; + _view.EditingCompleted = null; + } + + UpdateLabel(); + UpdateLabelColor(); + UpdatePlaceholder(); + UpdateKeyboard(); + UpdateHorizontalTextAlignment(); + UpdateText(); + UpdateIsEnabled(); + UpdateHeight(); + + _view.TextChanged = OnTextChanged; + _view.EditingCompleted = OnEditingCompleted; + + return _view; + } + + protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnCellPropertyChanged(sender, e); + + if (e.PropertyName == EntryCell.LabelProperty.PropertyName) + UpdateLabel(); + else if (e.PropertyName == EntryCell.TextProperty.PropertyName) + UpdateText(); + else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName) + UpdatePlaceholder(); + else if (e.PropertyName == EntryCell.KeyboardProperty.PropertyName) + UpdateKeyboard(); + else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName) + UpdateLabelColor(); + else if (e.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName) + UpdateHorizontalTextAlignment(); + else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(); + else if (e.PropertyName == "RenderHeight") + UpdateHeight(); + } + + void OnEditingCompleted() + { + var entryCell = (EntryCell)Cell; + entryCell.SendCompleted(); + } + + void OnTextChanged(string text) + { + var entryCell = (EntryCell)Cell; + entryCell.Text = text; + } + + void UpdateHeight() + { + _view.SetRenderHeight(Cell.RenderHeight); + } + + void UpdateHorizontalTextAlignment() + { + var entryCell = (EntryCell)Cell; + _view.EditText.Gravity = entryCell.HorizontalTextAlignment.ToHorizontalGravityFlags(); + } + + void UpdateIsEnabled() + { + var entryCell = (EntryCell)Cell; + _view.EditText.Enabled = entryCell.IsEnabled; + } + + void UpdateKeyboard() + { + var entryCell = (EntryCell)Cell; + _view.EditText.InputType = entryCell.Keyboard.ToInputType(); + } + + void UpdateLabel() + { + _view.LabelText = ((EntryCell)Cell).Label; + } + + void UpdateLabelColor() + { + _view.SetLabelTextColor(((EntryCell)Cell).LabelColor, global::Android.Resource.Color.PrimaryTextDark); + } + + void UpdatePlaceholder() + { + var entryCell = (EntryCell)Cell; + _view.EditText.Hint = entryCell.Placeholder; + } + + void UpdateText() + { + var entryCell = (EntryCell)Cell; + if (_view.EditText.Text == entryCell.Text) + return; + + _view.EditText.Text = entryCell.Text; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs new file mode 100644 index 00000000..c0206f1e --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs @@ -0,0 +1,145 @@ +using System; +using Android.Content; +using Android.Text; +using Android.Views; +using Android.Views.InputMethods; +using Android.Widget; +using Java.Lang; + +namespace Xamarin.Forms.Platform.Android +{ + public sealed class EntryCellView : LinearLayout, ITextWatcher, global::Android.Views.View.IOnFocusChangeListener, TextView.IOnEditorActionListener, INativeElementView + { + public const double DefaultMinHeight = 55; + + readonly Cell _cell; + readonly TextView _label; + + Color _labelTextColor; + string _labelTextText; + + public EntryCellView(Context context, Cell cell) : base(context) + { + _cell = cell; + SetMinimumWidth((int)context.ToPixels(50)); + SetMinimumHeight((int)context.ToPixels(85)); + Orientation = Orientation.Horizontal; + + var padding = (int)context.ToPixels(8); + SetPadding((int)context.ToPixels(15), padding, padding, padding); + + _label = new TextView(context); + _label.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItem); + + var layoutParams = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = GravityFlags.CenterVertical }; + using(layoutParams) + AddView(_label, layoutParams); + + EditText = new EntryCellEditText(context); + EditText.AddTextChangedListener(this); + EditText.OnFocusChangeListener = this; + EditText.SetOnEditorActionListener(this); + EditText.ImeOptions = ImeAction.Done; + EditText.BackButtonPressed += OnBackButtonPressed; + //editText.SetBackgroundDrawable (null); + layoutParams = new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent) { Width = 0, Weight = 1, Gravity = GravityFlags.FillHorizontal | GravityFlags.Center }; + using(layoutParams) + AddView(EditText, layoutParams); + } + + public Action EditingCompleted { get; set; } + + public EntryCellEditText EditText { get; } + + public Action<bool> FocusChanged { get; set; } + + public string LabelText + { + get { return _labelTextText; } + set + { + if (_labelTextText == value) + return; + + _labelTextText = value; + _label.Text = value; + } + } + + public Action<string> TextChanged { get; set; } + + public Element Element + { + get { return _cell; } + } + + bool TextView.IOnEditorActionListener.OnEditorAction(TextView v, ImeAction actionId, KeyEvent e) + { + if (actionId == ImeAction.Done) + { + OnKeyboardDoneButtonPressed(EditText, EventArgs.Empty); + EditText.ClearFocus(); + v.HideKeyboard(); + } + + // Fire Completed and dismiss keyboard for hardware / physical keyboards + if (actionId == ImeAction.ImeNull && e.KeyCode == Keycode.Enter) + { + OnKeyboardDoneButtonPressed(EditText, EventArgs.Empty); + EditText.ClearFocus(); + v.HideKeyboard(); + } + + return true; + } + + void IOnFocusChangeListener.OnFocusChange(global::Android.Views.View view, bool hasFocus) + { + Action<bool> focusChanged = FocusChanged; + if (focusChanged != null) + focusChanged(hasFocus); + } + + void ITextWatcher.AfterTextChanged(IEditable s) + { + } + + void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after) + { + } + + void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count) + { + Action<string> changed = TextChanged; + if (changed != null) + changed(s != null ? s.ToString() : null); + } + + public void SetLabelTextColor(Color color, int defaultColorResourceId) + { + if (_labelTextColor == color) + return; + + _labelTextColor = color; + _label.SetTextColor(color.ToAndroid(defaultColorResourceId)); + } + + public void SetRenderHeight(double height) + { + SetMinimumHeight((int)Context.ToPixels(height == -1 ? DefaultMinHeight : height)); + } + + void OnBackButtonPressed(object sender, EventArgs e) + { + // TODO Clear focus + } + + void OnKeyboardDoneButtonPressed(object sender, EventArgs e) + { + // TODO Clear focus + Action editingCompleted = EditingCompleted; + if (editingCompleted != null) + editingCompleted(); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs new file mode 100644 index 00000000..62815ed6 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs @@ -0,0 +1,37 @@ +using System.ComponentModel; +using Android.Content; +using Android.Views; + +namespace Xamarin.Forms.Platform.Android +{ + public class ImageCellRenderer : TextCellRenderer + { + protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context) + { + var result = (BaseCellView)base.GetCellCore(item, convertView, parent, context); + + UpdateImage(); + + return result; + } + + protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args) + { + base.OnCellPropertyChanged(sender, args); + if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName) + UpdateImage(); + } + + void UpdateImage() + { + var cell = (ImageCell)Cell; + if (cell.ImageSource != null) + { + View.SetImageVisible(true); + View.SetImageSource(cell.ImageSource); + } + else + View.SetImageVisible(false); + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs new file mode 100644 index 00000000..bba9d260 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs @@ -0,0 +1,55 @@ +using System.ComponentModel; +using Android.Content; +using Android.Views; +using AView = Android.Views.View; +using ASwitch = Android.Widget.Switch; + +namespace Xamarin.Forms.Platform.Android +{ + public class SwitchCellRenderer : CellRenderer + { + const double DefaultHeight = 30; + SwitchCellView _view; + + protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context) + { + var cell = (SwitchCell)Cell; + + if ((_view = convertView as SwitchCellView) == null) + _view = new SwitchCellView(context, item); + + _view.Cell = cell; + + UpdateText(); + UpdateChecked(); + UpdateHeight(); + + return _view; + } + + protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args) + { + if (args.PropertyName == SwitchCell.TextProperty.PropertyName) + UpdateText(); + else if (args.PropertyName == SwitchCell.OnProperty.PropertyName) + UpdateChecked(); + else if (args.PropertyName == "RenderHeight") + UpdateHeight(); + } + + void UpdateChecked() + { + ((ASwitch)_view.AccessoryView).Checked = ((SwitchCell)Cell).On; + } + + void UpdateHeight() + { + _view.SetRenderHeight(Cell.RenderHeight); + } + + void UpdateText() + { + _view.MainText = ((SwitchCell)Cell).Text; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs b/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs new file mode 100644 index 00000000..f15c41b0 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs @@ -0,0 +1,25 @@ +using Android.Content; +using Android.Widget; + +namespace Xamarin.Forms.Platform.Android +{ + public class SwitchCellView : BaseCellView, CompoundButton.IOnCheckedChangeListener + { + public SwitchCellView(Context context, Cell cell) : base(context, cell) + { + var sw = new global::Android.Widget.Switch(context); + sw.SetOnCheckedChangeListener(this); + + SetAccessoryView(sw); + + SetImageVisible(false); + } + + public SwitchCell Cell { get; set; } + + public void OnCheckedChanged(CompoundButton buttonView, bool isChecked) + { + Cell.On = isChecked; + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs new file mode 100644 index 00000000..cbaaa2b7 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs @@ -0,0 +1,78 @@ +using System.ComponentModel; +using Android.Content; +using Android.Views; +using AView = Android.Views.View; +using AColor = Android.Graphics.Color; + +namespace Xamarin.Forms.Platform.Android +{ + public class TextCellRenderer : CellRenderer + { + internal TextCellView View { get; private set; } + + protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context) + { + if ((View = convertView as TextCellView) == null) + View = new TextCellView(context, item); + + UpdateMainText(); + UpdateDetailText(); + UpdateHeight(); + UpdateIsEnabled(); + View.SetImageVisible(false); + + return View; + } + + protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args) + { + if (args.PropertyName == TextCell.TextProperty.PropertyName || args.PropertyName == TextCell.TextColorProperty.PropertyName) + UpdateMainText(); + else if (args.PropertyName == TextCell.DetailProperty.PropertyName || args.PropertyName == TextCell.DetailColorProperty.PropertyName) + UpdateDetailText(); + else if (args.PropertyName == Cell.IsEnabledProperty.PropertyName) + UpdateIsEnabled(); + else if (args.PropertyName == "RenderHeight") + UpdateHeight(); + } + + void UpdateDetailText() + { + var cell = (TextCell)Cell; + View.DetailText = cell.Detail; + View.SetDetailTextColor(cell.DetailColor); + } + + void UpdateHeight() + { + View.SetRenderHeight(Cell.RenderHeight); + } + + void UpdateIsEnabled() + { + var cell = (TextCell)Cell; + View.SetIsEnabled(cell.IsEnabled); + } + + void UpdateMainText() + { + var cell = (TextCell)Cell; + View.MainText = cell.Text; + + if (!TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell)) + View.SetDefaultMainTextColor(Color.Accent); + else + View.SetDefaultMainTextColor(Color.Default); + + View.SetMainTextColor(cell.TextColor); + } + + // ensure we don't get other people's BaseCellView's + internal class TextCellView : BaseCellView + { + public TextCellView(Context context, Cell cell) : base(context, cell) + { + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs new file mode 100644 index 00000000..4bf83395 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs @@ -0,0 +1,178 @@ +using Android.Content; +using Android.Views; +using AView = Android.Views.View; + +namespace Xamarin.Forms.Platform.Android +{ + public class ViewCellRenderer : CellRenderer + { + protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context) + { + Performance.Start(); + var cell = (ViewCell)item; + + var container = convertView as ViewCellContainer; + if (container != null) + { + container.Update(cell); + Performance.Stop(); + return container; + } + + BindableProperty unevenRows = null, rowHeight = null; + if (ParentView is TableView) + { + unevenRows = TableView.HasUnevenRowsProperty; + rowHeight = TableView.RowHeightProperty; + } + else if (ParentView is ListView) + { + unevenRows = ListView.HasUnevenRowsProperty; + rowHeight = ListView.RowHeightProperty; + } + + IVisualElementRenderer view = Platform.CreateRenderer(cell.View); + Platform.SetRenderer(cell.View, view); + cell.View.IsPlatformEnabled = true; + var c = new ViewCellContainer(context, view, cell, ParentView, unevenRows, rowHeight); + + Performance.Stop(); + + return c; + } + + internal class ViewCellContainer : ViewGroup, INativeElementView + { + readonly View _parent; + readonly BindableProperty _rowHeight; + readonly BindableProperty _unevenRows; + IVisualElementRenderer _view; + ViewCell _viewCell; + + public ViewCellContainer(Context context, IVisualElementRenderer view, ViewCell viewCell, View parent, BindableProperty unevenRows, BindableProperty rowHeight) : base(context) + { + _view = view; + _parent = parent; + _unevenRows = unevenRows; + _rowHeight = rowHeight; + _viewCell = viewCell; + AddView(view.ViewGroup); + UpdateIsEnabled(); + } + + protected bool ParentHasUnevenRows + { + get { return (bool)_parent.GetValue(_unevenRows); } + } + + protected int ParentRowHeight + { + get { return (int)_parent.GetValue(_rowHeight); } + } + + public Element Element + { + get { return _viewCell; } + } + + public override bool OnInterceptTouchEvent(MotionEvent ev) + { + if (!Enabled) + return true; + return base.OnInterceptTouchEvent(ev); + } + + public void Update(ViewCell cell) + { + Performance.Start(); + + var renderer = GetChildAt(0) as IVisualElementRenderer; + var viewHandlerType = Registrar.Registered.GetHandlerType(cell.View.GetType()) ?? typeof(Platform.DefaultRenderer); + if (renderer != null && renderer.GetType() == viewHandlerType) + { + Performance.Start("Reuse"); + _viewCell = cell; + + cell.View.DisableLayout = true; + foreach (VisualElement c in cell.View.Descendants()) + c.DisableLayout = true; + + Performance.Start("Reuse.SetElement"); + renderer.SetElement(cell.View); + Performance.Stop("Reuse.SetElement"); + + Platform.SetRenderer(cell.View, _view); + + cell.View.DisableLayout = false; + foreach (VisualElement c in cell.View.Descendants()) + c.DisableLayout = false; + + var viewAsLayout = cell.View as Layout; + if (viewAsLayout != null) + viewAsLayout.ForceLayout(); + + Invalidate(); + + Performance.Stop("Reuse"); + Performance.Stop(); + return; + } + + RemoveView(_view.ViewGroup); + Platform.SetRenderer(_viewCell.View, null); + _viewCell.View.IsPlatformEnabled = false; + _view.ViewGroup.Dispose(); + + _viewCell = cell; + _view = Platform.CreateRenderer(_viewCell.View); + + Platform.SetRenderer(_viewCell.View, _view); + AddView(_view.ViewGroup); + + UpdateIsEnabled(); + + Performance.Stop(); + } + + public void UpdateIsEnabled() + { + Enabled = _viewCell.IsEnabled; + } + + protected override void OnLayout(bool changed, int l, int t, int r, int b) + { + Performance.Start(); + + double width = Context.FromPixels(r - l); + double height = Context.FromPixels(b - t); + + Performance.Start("Element.Layout"); + Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(_view.Element, new Rectangle(0, 0, width, height)); + Performance.Stop("Element.Layout"); + + _view.UpdateLayout(); + Performance.Stop(); + } + + protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + Performance.Start(); + + int width = MeasureSpec.GetSize(widthMeasureSpec); + int height; + + if (ParentHasUnevenRows) + { + SizeRequest measure = _view.Element.Measure(Context.FromPixels(width), double.PositiveInfinity, MeasureFlags.IncludeMargins); + height = (int)Context.ToPixels(_viewCell.Height > 0 ? _viewCell.Height : measure.Request.Height); + } + else + height = (int)Context.ToPixels(ParentRowHeight == -1 ? BaseCellView.DefaultMinHeight : ParentRowHeight); + + SetMeasuredDimension(width, height); + + Performance.Stop(); + } + } + } +}
\ No newline at end of file |