Merge pull request #59 from jsuarezruiz/master
ListViewRenderer, CellRenderers and ListView Samples
This commit is contained in:
commit
0ab74138b5
|
@ -0,0 +1,71 @@
|
|||
using Ooui.Forms.Extensions;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class CellRenderer : IRegisterable
|
||||
{
|
||||
private EventHandler _onForceUpdateSizeRequested;
|
||||
|
||||
static readonly BindableProperty RealCellProperty =
|
||||
BindableProperty.CreateAttached("RealCell", typeof(Div),
|
||||
typeof(Cell), null);
|
||||
|
||||
public virtual CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
var nativeCell = reusableView as CellView ?? GetCellInstance(item);
|
||||
|
||||
nativeCell.Cell = item;
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, nativeCell);
|
||||
UpdateBackground(nativeCell, item);
|
||||
|
||||
return nativeCell;
|
||||
}
|
||||
|
||||
internal static CellView GetRealCell(BindableObject cell)
|
||||
{
|
||||
return (CellView)cell.GetValue(RealCellProperty);
|
||||
}
|
||||
|
||||
internal static void SetRealCell(BindableObject cell, CellView renderer)
|
||||
{
|
||||
cell.SetValue(RealCellProperty, renderer);
|
||||
}
|
||||
|
||||
protected virtual CellView GetCellInstance(Cell item)
|
||||
{
|
||||
return new CellView();
|
||||
}
|
||||
|
||||
protected virtual void OnForceUpdateSizeRequest(Cell cell, CellView nativeCell)
|
||||
{
|
||||
nativeCell.Style.Height = (int)cell.RenderHeight;
|
||||
}
|
||||
|
||||
protected void UpdateBackground(CellView tableViewCell, Cell cell)
|
||||
{
|
||||
var defaultColor = Xamarin.Forms.Color.White.ToOouiColor();
|
||||
Color backgroundColor = defaultColor;
|
||||
|
||||
if (cell.RealParent is VisualElement element)
|
||||
backgroundColor = element.BackgroundColor ==
|
||||
Xamarin.Forms.Color.Default ? backgroundColor : element.BackgroundColor.ToOouiColor();
|
||||
|
||||
tableViewCell.Style.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
protected void WireUpForceUpdateSizeRequested(Cell cell, CellView nativeCell)
|
||||
{
|
||||
cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested;
|
||||
|
||||
_onForceUpdateSizeRequested = (sender, e) =>
|
||||
{
|
||||
OnForceUpdateSizeRequest(cell, nativeCell);
|
||||
};
|
||||
|
||||
cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class CellView : Div, INativeElementView
|
||||
{
|
||||
private Cell _cell;
|
||||
|
||||
public Action<object, PropertyChangedEventArgs> PropertyChanged;
|
||||
|
||||
public CellView()
|
||||
{
|
||||
CreateUI();
|
||||
}
|
||||
|
||||
public Cell Cell
|
||||
{
|
||||
get { return _cell; }
|
||||
set
|
||||
{
|
||||
if (_cell == value)
|
||||
return;
|
||||
|
||||
if (_cell != null)
|
||||
Device.BeginInvokeOnMainThread(_cell.SendDisappearing);
|
||||
|
||||
_cell = value;
|
||||
|
||||
if (_cell != null)
|
||||
Device.BeginInvokeOnMainThread(_cell.SendAppearing);
|
||||
}
|
||||
}
|
||||
|
||||
public Div FirstCol { get; private set; }
|
||||
|
||||
public Div SecondCol { get; private set; }
|
||||
|
||||
public Div ThirdCol { get; private set; }
|
||||
|
||||
public Label TextLabel { get; private set; }
|
||||
|
||||
public Label DetailTextLabel { get; private set; }
|
||||
|
||||
public Image ImageView { get; private set; }
|
||||
|
||||
public Div CustomView { get; private set; }
|
||||
|
||||
public virtual Xamarin.Forms.Element Element => Cell;
|
||||
|
||||
public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void CreateUI()
|
||||
{
|
||||
Style.Width = "100%";
|
||||
Style.Display = "flex";
|
||||
|
||||
FirstCol = new Div();
|
||||
AppendChild(FirstCol);
|
||||
|
||||
SecondCol = new Div();
|
||||
AppendChild(SecondCol);
|
||||
|
||||
ThirdCol = new Div();
|
||||
AppendChild(ThirdCol);
|
||||
|
||||
ImageView = new Image();
|
||||
FirstCol.AppendChild(ImageView);
|
||||
|
||||
TextLabel = new Label();
|
||||
SecondCol.AppendChild(TextLabel);
|
||||
|
||||
DetailTextLabel = new Label();
|
||||
SecondCol.AppendChild(DetailTextLabel);
|
||||
|
||||
CustomView = new Div();
|
||||
ThirdCol.AppendChild(CustomView);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
using Ooui.Forms.Extensions;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class EntryCellRenderer : CellRenderer
|
||||
{
|
||||
private static Cell _cell;
|
||||
|
||||
public override CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
TextInput nativeEntry = null;
|
||||
|
||||
var nativeEntryCell = base.GetCell(item, reusableView, listView);
|
||||
|
||||
if (nativeEntryCell == null)
|
||||
nativeEntryCell = new CellView();
|
||||
else
|
||||
{
|
||||
nativeEntryCell.Cell.PropertyChanged -= OnCellPropertyChanged;
|
||||
|
||||
nativeEntry = nativeEntryCell.CustomView.FirstChild as TextInput;
|
||||
if (nativeEntry != null)
|
||||
{
|
||||
nativeEntryCell.CustomView.RemoveChild(nativeEntry);
|
||||
nativeEntry.Change -= OnTextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
SetRealCell(item, nativeEntryCell);
|
||||
|
||||
if (nativeEntry == null)
|
||||
nativeEntryCell.CustomView.AppendChild(nativeEntry = new TextInput());
|
||||
|
||||
var entryCell = (EntryCell)item;
|
||||
|
||||
nativeEntryCell.Cell = item;
|
||||
nativeEntryCell.SecondCol.Style.Width = "25%";
|
||||
_cell = nativeEntryCell.Cell;
|
||||
|
||||
nativeEntryCell.Cell.PropertyChanged += OnCellPropertyChanged;
|
||||
nativeEntry.Change += OnTextChanged;
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, nativeEntryCell);
|
||||
|
||||
UpdateBackground(nativeEntryCell, entryCell);
|
||||
UpdateLabel(nativeEntryCell, entryCell);
|
||||
UpdateText(nativeEntryCell, entryCell);
|
||||
UpdatePlaceholder(nativeEntryCell, entryCell);
|
||||
UpdateLabelColor(nativeEntryCell, entryCell);
|
||||
|
||||
return nativeEntryCell;
|
||||
}
|
||||
|
||||
private static void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var entryCell = (EntryCell)sender;
|
||||
var realCell = (CellView)GetRealCell(entryCell);
|
||||
|
||||
if (e.PropertyName == EntryCell.LabelProperty.PropertyName)
|
||||
UpdateLabel(realCell, entryCell);
|
||||
else if (e.PropertyName == EntryCell.TextProperty.PropertyName)
|
||||
UpdateText(realCell, entryCell);
|
||||
else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName)
|
||||
UpdatePlaceholder(realCell, entryCell);
|
||||
else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName)
|
||||
UpdateLabelColor(realCell, entryCell);
|
||||
}
|
||||
|
||||
private static void UpdateLabel(CellView cell, EntryCell entryCell)
|
||||
{
|
||||
cell.TextLabel.Text = entryCell.Label ?? string.Empty;
|
||||
}
|
||||
|
||||
private static void UpdateLabelColor(CellView cell, EntryCell entryCell)
|
||||
{
|
||||
cell.TextLabel.Style.Color = entryCell.LabelColor.ToOouiColor();
|
||||
}
|
||||
|
||||
private static void UpdatePlaceholder(CellView cell, EntryCell entryCell)
|
||||
{
|
||||
if (cell.CustomView.FirstChild is TextInput textInput)
|
||||
textInput.Placeholder = entryCell.Placeholder ?? string.Empty;
|
||||
}
|
||||
|
||||
private static void UpdateText(CellView cell, EntryCell entryCell)
|
||||
{
|
||||
if (cell.CustomView.FirstChild is TextInput textInput)
|
||||
textInput.Text = entryCell.Text ?? string.Empty;
|
||||
}
|
||||
|
||||
private static void OnTextChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
var textInput = (TextInput)sender;
|
||||
|
||||
CellView realCell = GetRealCell(_cell);
|
||||
|
||||
if (realCell != null)
|
||||
((EntryCell)realCell.Cell).Text = textInput.Text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
using Ooui.Forms.Renderers;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class ImageCellRenderer : TextCellRenderer
|
||||
{
|
||||
public override CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
var nativeImageCell = reusableView as CellView ?? new CellView();
|
||||
|
||||
var result = (CellView)base.GetCell(item, nativeImageCell, listView);
|
||||
|
||||
var imageCell = (ImageCell)item;
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, result);
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
SetImage(imageCell, result);
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override async void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
|
||||
{
|
||||
var tvc = (CellView)sender;
|
||||
var imageCell = (ImageCell)tvc.Cell;
|
||||
|
||||
base.HandlePropertyChanged(sender, args);
|
||||
|
||||
if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName)
|
||||
await SetImage(imageCell, tvc);
|
||||
}
|
||||
|
||||
static async Task SetImage(ImageCell cell, CellView target)
|
||||
{
|
||||
var source = cell.ImageSource;
|
||||
|
||||
target.ImageView.Source = null;
|
||||
|
||||
IImageSourceHandler handler;
|
||||
|
||||
if (source != null && (handler =
|
||||
Registrar.Registered.GetHandler<Renderers.IImageSourceHandler>(source.GetType())) != null)
|
||||
{
|
||||
string image;
|
||||
try
|
||||
{
|
||||
image = await handler.LoadImageAsync(source).ConfigureAwait(false);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
image = null;
|
||||
}
|
||||
|
||||
target.ImageView.Source = image;
|
||||
}
|
||||
else
|
||||
target.ImageView.Source = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class SwitchCellRenderer : CellRenderer
|
||||
{
|
||||
private static Cell _cell;
|
||||
|
||||
public override CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
var nativeSwitchCell = reusableView as CellView;
|
||||
Input oouiSwitch = null;
|
||||
|
||||
if (nativeSwitchCell == null)
|
||||
nativeSwitchCell = new CellView();
|
||||
else
|
||||
{
|
||||
oouiSwitch = nativeSwitchCell.CustomView.FirstChild as Input;
|
||||
|
||||
if (oouiSwitch != null)
|
||||
{
|
||||
nativeSwitchCell.CustomView.RemoveChild(oouiSwitch);
|
||||
oouiSwitch.Click -= OnSwitchClick;
|
||||
}
|
||||
nativeSwitchCell.Cell.PropertyChanged -= OnCellPropertyChanged;
|
||||
}
|
||||
|
||||
SetRealCell(item, nativeSwitchCell);
|
||||
|
||||
if (oouiSwitch == null)
|
||||
{
|
||||
oouiSwitch = new Input(InputType.Checkbox);
|
||||
oouiSwitch.SetAttribute("data-toggle", "toggle");
|
||||
}
|
||||
|
||||
var switchCell = (SwitchCell)item;
|
||||
|
||||
nativeSwitchCell.Cell = item;
|
||||
nativeSwitchCell.SecondCol.Style.Width = "25%";
|
||||
_cell = nativeSwitchCell.Cell;
|
||||
|
||||
nativeSwitchCell.Cell.PropertyChanged += OnCellPropertyChanged;
|
||||
nativeSwitchCell.CustomView.AppendChild(oouiSwitch);
|
||||
nativeSwitchCell.TextLabel.Text = switchCell.Text ?? string.Empty;
|
||||
|
||||
oouiSwitch.IsChecked = switchCell.On;
|
||||
oouiSwitch.Click += OnSwitchClick;
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, nativeSwitchCell);
|
||||
|
||||
UpdateBackground(nativeSwitchCell, item);
|
||||
|
||||
return nativeSwitchCell;
|
||||
}
|
||||
|
||||
private void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
var switchCell = (SwitchCell)sender;
|
||||
var nativeSwitchCell = (CellView)GetRealCell(switchCell);
|
||||
|
||||
if (e.PropertyName == SwitchCell.OnProperty.PropertyName)
|
||||
((Input)nativeSwitchCell.CustomView.FirstChild).IsChecked = switchCell.On;
|
||||
else if (e.PropertyName == SwitchCell.TextProperty.PropertyName)
|
||||
nativeSwitchCell.TextLabel.Text = switchCell.Text ?? string.Empty;
|
||||
}
|
||||
|
||||
private void OnSwitchClick(object sender, EventArgs eventArgs)
|
||||
{
|
||||
var switchInput = (Input)sender;
|
||||
|
||||
CellView realCell = GetRealCell(_cell);
|
||||
|
||||
if (realCell != null)
|
||||
((SwitchCell)realCell.Cell).On = switchInput.IsChecked;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using Ooui.Forms.Extensions;
|
||||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class TextCellRenderer : CellRenderer
|
||||
{
|
||||
public override CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
var nativeTextCell = base.GetCell(item, reusableView, listView);
|
||||
var textCell = (TextCell)item;
|
||||
|
||||
if (nativeTextCell.Cell != null)
|
||||
nativeTextCell.Cell.PropertyChanged -= nativeTextCell.HandlePropertyChanged;
|
||||
|
||||
nativeTextCell.Cell = textCell;
|
||||
textCell.PropertyChanged += nativeTextCell.HandlePropertyChanged;
|
||||
nativeTextCell.PropertyChanged = HandlePropertyChanged;
|
||||
|
||||
nativeTextCell.TextLabel.Text = textCell.Text ?? string.Empty;
|
||||
nativeTextCell.DetailTextLabel.Text = textCell.Detail ?? string.Empty;
|
||||
nativeTextCell.TextLabel.Style.Color = textCell.TextColor.ToOouiColor();
|
||||
nativeTextCell.DetailTextLabel.Style.Color = textCell.DetailColor.ToOouiColor();
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, nativeTextCell);
|
||||
|
||||
UpdateBackground(nativeTextCell, item);
|
||||
|
||||
return nativeTextCell;
|
||||
}
|
||||
|
||||
protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
|
||||
{
|
||||
var tvc = (CellView)sender;
|
||||
var textCell = (TextCell)tvc.Cell;
|
||||
|
||||
if (args.PropertyName == TextCell.TextProperty.PropertyName)
|
||||
tvc.TextLabel.Text = textCell.Text ?? string.Empty;
|
||||
else if (args.PropertyName == TextCell.DetailProperty.PropertyName)
|
||||
tvc.DetailTextLabel.Text = textCell.Detail ?? string.Empty;
|
||||
else if (args.PropertyName == TextCell.TextColorProperty.PropertyName)
|
||||
tvc.TextLabel.Style.Color = textCell.TextColor.ToOouiColor();
|
||||
else if (args.PropertyName == TextCell.DetailColorProperty.PropertyName)
|
||||
tvc.DetailTextLabel.Style.Color = textCell.DetailColor.ToOouiColor();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class ViewCellRenderer : CellRenderer
|
||||
{
|
||||
public override CellView GetCell(Cell item, CellView reusableView, List listView)
|
||||
{
|
||||
var viewCell = (ViewCell)item;
|
||||
|
||||
var nativeViewCell = reusableView as ViewCellView;
|
||||
|
||||
if (nativeViewCell == null)
|
||||
nativeViewCell = new ViewCellView();
|
||||
|
||||
nativeViewCell.ViewCell = viewCell;
|
||||
|
||||
SetRealCell(item, nativeViewCell);
|
||||
|
||||
WireUpForceUpdateSizeRequested(item, nativeViewCell);
|
||||
|
||||
return nativeViewCell;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
using Ooui.Forms.Renderers;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Ooui.Forms.Cells
|
||||
{
|
||||
public class ViewCellView : CellView
|
||||
{
|
||||
private WeakReference<IVisualElementRenderer> _rendererRef;
|
||||
private ViewCell _viewCell;
|
||||
|
||||
public ViewCell ViewCell
|
||||
{
|
||||
get { return _viewCell; }
|
||||
set
|
||||
{
|
||||
if (_viewCell == value)
|
||||
return;
|
||||
UpdateCell(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCell(ViewCell cell)
|
||||
{
|
||||
if (_viewCell != null)
|
||||
Device.BeginInvokeOnMainThread(_viewCell.SendDisappearing);
|
||||
|
||||
_viewCell = cell;
|
||||
|
||||
Device.BeginInvokeOnMainThread(_viewCell.SendAppearing);
|
||||
|
||||
IVisualElementRenderer renderer;
|
||||
if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer))
|
||||
renderer = GetNewRenderer();
|
||||
else
|
||||
{
|
||||
if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element))
|
||||
renderer.Element.ClearValue(Platform.RendererProperty);
|
||||
|
||||
var type = Xamarin.Forms.Internals.Registrar.Registered.GetHandlerType(_viewCell.View.GetType());
|
||||
var reflectableType = renderer as System.Reflection.IReflectableType;
|
||||
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : renderer.GetType();
|
||||
if (rendererType == type || (renderer is DefaultRenderer && type == null))
|
||||
renderer.SetElement(_viewCell.View);
|
||||
else
|
||||
{
|
||||
renderer = GetNewRenderer();
|
||||
}
|
||||
}
|
||||
|
||||
Platform.SetRenderer(_viewCell.View, renderer);
|
||||
}
|
||||
|
||||
private IVisualElementRenderer GetNewRenderer()
|
||||
{
|
||||
var newRenderer = Platform.CreateRenderer(_viewCell.View);
|
||||
_rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer);
|
||||
AppendChild(newRenderer.NativeView);
|
||||
|
||||
return newRenderer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using Ooui.Forms;
|
||||
using Ooui.Forms.Cells;
|
||||
using Ooui.Forms.Renderers;
|
||||
using Xamarin.Forms;
|
||||
|
||||
|
@ -15,6 +16,7 @@ using Xamarin.Forms;
|
|||
[assembly: ExportRenderer (typeof (Label), typeof (LabelRenderer))]
|
||||
[assembly: ExportRenderer (typeof (LinkLabel), typeof (LinkLabelRenderer))]
|
||||
[assembly: ExportRenderer (typeof (LinkView), typeof (LinkViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
|
||||
[assembly: ExportRenderer (typeof (ProgressBar), typeof (ProgressBarRenderer))]
|
||||
[assembly: ExportRenderer (typeof (SearchBar), typeof (SearchBarRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
|
||||
|
@ -23,7 +25,12 @@ using Xamarin.Forms;
|
|||
[assembly: ExportImageSourceHandler (typeof (FileImageSource), typeof (FileImageSourceHandler))]
|
||||
[assembly: ExportImageSourceHandler (typeof (StreamImageSource), typeof (StreamImagesourceHandler))]
|
||||
[assembly: ExportImageSourceHandler (typeof (UriImageSource), typeof (ImageLoaderSourceHandler))]
|
||||
|
||||
[assembly: ExportCell(typeof(Cell), typeof(CellRenderer))]
|
||||
[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
|
||||
[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
|
||||
[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
|
||||
[assembly: ExportCell(typeof(TextCell), typeof(TextCellRenderer))]
|
||||
[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
|
||||
namespace Ooui.Forms
|
||||
{
|
||||
[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
|
@ -35,6 +42,14 @@ namespace Ooui.Forms
|
|||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class ExportCellAttribute : HandlerAttribute
|
||||
{
|
||||
public ExportCellAttribute(Type handler, Type target) : base(handler, target)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Xamarin.Forms
|
|||
|
||||
Registrar.RegisterAll (new[] {
|
||||
typeof(ExportRendererAttribute),
|
||||
//typeof(ExportCellAttribute),
|
||||
typeof(ExportCellAttribute),
|
||||
typeof(ExportImageSourceHandlerAttribute),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
using Ooui.Forms.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
||||
namespace Ooui.Forms.Renderers
|
||||
{
|
||||
public class ListViewRenderer : ViewRenderer<ListView, List>
|
||||
{
|
||||
private bool _disposed;
|
||||
private List _listView;
|
||||
private List<ListItem> _cells;
|
||||
|
||||
public ListViewRenderer()
|
||||
{
|
||||
_cells = new List<ListItem>();
|
||||
}
|
||||
|
||||
ITemplatedItemsView<Cell> TemplatedItemsView => Element;
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
|
||||
{
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
if (Control == null)
|
||||
{
|
||||
_listView = new List();
|
||||
|
||||
SetNativeControl(_listView);
|
||||
}
|
||||
|
||||
UpdateItems();
|
||||
UpdateBackgroundColor();
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
if (e.PropertyName == ListView.ItemsSourceProperty.PropertyName)
|
||||
UpdateItems();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing && !_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateItems()
|
||||
{
|
||||
_cells.Clear();
|
||||
|
||||
var items = TemplatedItemsView.TemplatedItems;
|
||||
|
||||
if (!items.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool grouping = Element.IsGroupingEnabled;
|
||||
|
||||
if (grouping)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var cell = GetCell(item);
|
||||
|
||||
var listItem = new ListItem();
|
||||
listItem.Style["list-style-type"] = "none";
|
||||
|
||||
listItem.AppendChild(cell);
|
||||
|
||||
_cells.Add(listItem);
|
||||
}
|
||||
|
||||
foreach (var cell in _cells)
|
||||
{
|
||||
_listView.AppendChild(cell);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBackgroundColor()
|
||||
{
|
||||
var backgroundColor = Element.BackgroundColor.ToOouiColor();
|
||||
|
||||
_listView.Style.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
private Div GetCell(Cell cell)
|
||||
{
|
||||
var renderer =
|
||||
(Cells.CellRenderer)Registrar.Registered.GetHandler<IRegisterable>(cell.GetType());
|
||||
|
||||
var realCell = renderer.GetCell(cell, null, _listView);
|
||||
|
||||
return realCell;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
using Ooui;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Samples
|
||||
{
|
||||
public class Light : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private string _name;
|
||||
private string _comment;
|
||||
private Xamarin.Forms.Color _color;
|
||||
private bool _isOn;
|
||||
|
||||
public string Name { get { return _name; } set { OnPropertyChanged(); _name = value; } }
|
||||
public string Comment { get { return _comment; } set { OnPropertyChanged(); _comment = value; } }
|
||||
public Xamarin.Forms.Color Color { get { return _color; } set { OnPropertyChanged(); _color = value; } }
|
||||
public bool IsOn { get { return _isOn; } set { OnPropertyChanged(); OnPropertyChanged("isNotOn"); _isOn = value; } }
|
||||
public bool IsNotOn { get { return !_isOn; } }
|
||||
|
||||
public Light()
|
||||
{
|
||||
this.IsOn = false;
|
||||
this.Name = "My first light!";
|
||||
this.Color = Xamarin.Forms.Color.Blue;
|
||||
this.Comment = "Bedroom";
|
||||
}
|
||||
public Light(bool isOn, string name, Xamarin.Forms.Color color, string comment)
|
||||
{
|
||||
this.IsOn = isOn;
|
||||
this.Name = name;
|
||||
this.Color = color;
|
||||
this.Comment = comment;
|
||||
}
|
||||
void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public static class DataSource
|
||||
{
|
||||
public static ObservableCollection<Light> GetLights()
|
||||
{
|
||||
ObservableCollection<Light> lights = new ObservableCollection<Light>()
|
||||
{
|
||||
new Light(false, "Bedside", Xamarin.Forms.Color.Blue, "Mel's Bedroom"),
|
||||
new Light(false, "Desk", Xamarin.Forms.Color.Red, "Mel's Bedroom"),
|
||||
new Light(true, "Flood Lamp", Xamarin.Forms.Color.Olive, "Outside"),
|
||||
new Light(false, "hallway1", Xamarin.Forms.Color.Teal, "Entry Hallway"),
|
||||
new Light(false, "hallway2", Xamarin.Forms.Color.Purple, "Entry Hallway")
|
||||
};
|
||||
|
||||
return lights;
|
||||
}
|
||||
}
|
||||
|
||||
class EntryListViewSample : ISample
|
||||
{
|
||||
public string Title => "Xamarin.Forms Basic Entry ListView Sample";
|
||||
|
||||
public Ooui.Element CreateElement()
|
||||
{
|
||||
var panel = new StackLayout();
|
||||
|
||||
var titleLabel = new Xamarin.Forms.Label
|
||||
{
|
||||
Text = "ListView",
|
||||
FontSize = 24,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
};
|
||||
|
||||
panel.Children.Add(titleLabel);
|
||||
|
||||
ListView listView = new ListView() { ItemsSource = DataSource.GetLights() };
|
||||
|
||||
listView.ItemTemplate = new DataTemplate(typeof(EntryCell));
|
||||
listView.ItemTemplate.SetBinding(EntryCell.LabelProperty, "Comment");
|
||||
listView.ItemTemplate.SetBinding(EntryCell.TextProperty, "Name");
|
||||
|
||||
panel.Children.Add(listView);
|
||||
|
||||
var page = new ContentPage
|
||||
{
|
||||
Content = panel
|
||||
};
|
||||
|
||||
return page.GetOouiElement();
|
||||
}
|
||||
|
||||
public void Publish()
|
||||
{
|
||||
UI.Publish("/entry-listview", CreateElement);
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchListViewSample : ISample
|
||||
{
|
||||
public string Title => "Xamarin.Forms Basic Switch ListView Sample";
|
||||
|
||||
public Ooui.Element CreateElement()
|
||||
{
|
||||
var panel = new StackLayout();
|
||||
|
||||
var titleLabel = new Xamarin.Forms.Label
|
||||
{
|
||||
Text = "ListView",
|
||||
FontSize = 24,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
};
|
||||
|
||||
panel.Children.Add(titleLabel);
|
||||
|
||||
ListView listView = new ListView() { ItemsSource = DataSource.GetLights() };
|
||||
|
||||
listView.ItemTemplate = new DataTemplate(typeof(SwitchCell));
|
||||
listView.ItemTemplate.SetBinding(SwitchCell.TextProperty, "Name");
|
||||
listView.ItemTemplate.SetBinding(SwitchCell.OnProperty, "IsOn");
|
||||
|
||||
panel.Children.Add(listView);
|
||||
|
||||
var page = new ContentPage
|
||||
{
|
||||
Content = panel
|
||||
};
|
||||
|
||||
return page.GetOouiElement();
|
||||
}
|
||||
|
||||
public void Publish()
|
||||
{
|
||||
UI.Publish("/switch-listview", CreateElement);
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
|
@ -0,0 +1,13 @@
|
|||
using Xamarin.Forms;
|
||||
|
||||
namespace Monkeys.Models
|
||||
{
|
||||
public class Monkey
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Location { get; set; }
|
||||
public string Details { get; set; }
|
||||
public ImageSource Image { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using Monkeys.Models;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Monkeys.Helpers
|
||||
{
|
||||
public static class MonkeyHelper
|
||||
{
|
||||
public static ObservableCollection<Monkey> Monkeys { get; set; }
|
||||
|
||||
static MonkeyHelper()
|
||||
{
|
||||
Monkeys = new ObservableCollection<Monkey>
|
||||
{
|
||||
new Monkey
|
||||
{
|
||||
Name = "Baboon",
|
||||
Location = "Africa & Asia",
|
||||
Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae.",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.Baboon.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
},
|
||||
new Monkey
|
||||
{
|
||||
Name = "Capuchin Monkey",
|
||||
Location = "Central & South America",
|
||||
Details = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus.",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.Capuchin.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
},
|
||||
new Monkey
|
||||
{
|
||||
Name = "Blue Monkey",
|
||||
Location = "Central and East Africa",
|
||||
Details = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.BlueMonkey.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
},
|
||||
new Monkey
|
||||
{
|
||||
Name = "Squirrel Monkey",
|
||||
Location = "Central & South America",
|
||||
Details = "The squirrel monkeys are the New World monkeys of the genus Saimiri. They are the only genus in the subfamily Saimirinae. The name of the genus Saimiri is of Tupi origin, and was also used as an English name by early researchers.",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.Squirrel.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
},
|
||||
new Monkey
|
||||
{
|
||||
Name = "Golden Lion Tamarin",
|
||||
Location = "Brazil",
|
||||
Details = "The golden lion tamarin also known as the golden marmoset, is a small New World monkey of the family Callitrichidae.",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.GoldenLionTamarin.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
},
|
||||
new Monkey
|
||||
{
|
||||
Name = "Howler Monkey",
|
||||
Location = "South America",
|
||||
Details = "Howler monkeys are among the largest of the New World monkeys. Fifteen species are currently recognised. Previously classified in the family Cebidae, they are now placed in the family Atelidae.",
|
||||
Image = ImageSource.FromResource("Samples.Monkeys.Images.Howler.jpg", System.Reflection.Assembly.GetCallingAssembly())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentPage
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Monkeys.Views.MonkeysView"
|
||||
Title="Monkeys">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<Label
|
||||
Text="ListView"
|
||||
FontSize="32"
|
||||
Margin="12, 0"/>
|
||||
<ListView
|
||||
ItemsSource="{Binding Monkeys}"
|
||||
HasUnevenRows="true">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<Grid
|
||||
Padding="10"
|
||||
RowSpacing="10"
|
||||
ColumnSpacing="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
HeightRequest="66"
|
||||
Aspect="AspectFill"
|
||||
WidthRequest="66"
|
||||
Grid.RowSpan="2"
|
||||
Source="{Binding Image}"/>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
Text="{Binding Name}"
|
||||
FontSize="24"
|
||||
VerticalOptions="End"/>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
VerticalOptions="Start"
|
||||
Text="{Binding Location}"/>
|
||||
</Grid>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
|
@ -0,0 +1,15 @@
|
|||
using Monkeys.ViewModels;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Monkeys.Views
|
||||
{
|
||||
public partial class MonkeysView : ContentPage
|
||||
{
|
||||
public MonkeysView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BindingContext = new MonkeysViewModel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using Monkeys.Helpers;
|
||||
using Monkeys.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Monkeys.ViewModels
|
||||
{
|
||||
public class MonkeysViewModel
|
||||
{
|
||||
public ObservableCollection<Monkey> Monkeys { get; set; }
|
||||
|
||||
public MonkeysViewModel()
|
||||
{
|
||||
Monkeys = MonkeyHelper.Monkeys;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using Ooui;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Samples
|
||||
{
|
||||
public class MonkeysSample : ISample
|
||||
{
|
||||
public string Title => "Xamarin.Forms Monkeys";
|
||||
|
||||
public Ooui.Element CreateElement()
|
||||
{
|
||||
var page = new Monkeys.Views.MonkeysView();
|
||||
return page.GetOouiElement();
|
||||
}
|
||||
|
||||
public void Publish()
|
||||
{
|
||||
UI.Publish("/monkeys", CreateElement);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ namespace Samples
|
|||
}
|
||||
}
|
||||
|
||||
new EntryListViewSample().Publish();
|
||||
new ButtonSample ().Publish ();
|
||||
new TodoSample ().Publish ();
|
||||
new DrawSample ().Publish ();
|
||||
|
@ -32,8 +33,10 @@ namespace Samples
|
|||
new DisplayAlertSample ().Publish ();
|
||||
new DotMatrixClockSample().Publish();
|
||||
new EditorSample().Publish();
|
||||
new MonkeysSample().Publish();
|
||||
new SearchBarSample().Publish();
|
||||
new SliderSample().Publish();
|
||||
new SwitchListViewSample().Publish();
|
||||
new TimePickerSample().Publish();
|
||||
new TipCalcSample().Publish();
|
||||
new WeatherAppSample().Publish();
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
<EmbeddedResource Include="**/*.xaml" />
|
||||
<EmbeddedResource Include="BugSweeper\Images\RedBug.png" />
|
||||
<EmbeddedResource Include="BugSweeper\Images\Xamarin120.png" />
|
||||
<EmbeddedResource Include="Monkeys\Images\Baboon.jpg" />
|
||||
<EmbeddedResource Include="Monkeys\Images\BlueMonkey.jpg" />
|
||||
<EmbeddedResource Include="Monkeys\Images\Capuchin.jpg" />
|
||||
<EmbeddedResource Include="Monkeys\Images\GoldenLionTamarin.jpg" />
|
||||
<EmbeddedResource Include="Monkeys\Images\Howler.jpg" />
|
||||
<EmbeddedResource Include="Monkeys\Images\Squirrel.jpg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -41,6 +47,9 @@
|
|||
<EmbeddedResource Update="DotMatrixClock\DotMatrixClockPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Monkeys\MonkeysView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="TipCalc\TipCalcPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
|
@ -56,6 +65,13 @@
|
|||
<None Remove="BugSweeper\Images\RedBug.png" />
|
||||
<None Remove="BugSweeper\Images\Xamarin120.png" />
|
||||
<None Remove="DotMatrixClock\DotMatrixClockPage.xaml" />
|
||||
<None Remove="Monkeys\Images\Baboon.jpg" />
|
||||
<None Remove="Monkeys\Images\BlueMonkey.jpg" />
|
||||
<None Remove="Monkeys\Images\Capuchin.jpg" />
|
||||
<None Remove="Monkeys\Images\GoldenLionTamarin.jpg" />
|
||||
<None Remove="Monkeys\Images\Howler.jpg" />
|
||||
<None Remove="Monkeys\Images\Squirrel.jpg" />
|
||||
<None Remove="Monkeys\MonkeysView.xaml" />
|
||||
<None Remove="TipCalc\TipCalcPage.xaml" />
|
||||
<None Remove="WeatherApp\WeatherPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue