From c17c72d73a789409d3ad2f5447e6420a54d495f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=B9=84=EC=98=A4/Tizen=20Platform=20Lab=28SR=29?= =?UTF-8?q?/Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Tue, 23 Jan 2018 13:49:53 +0900 Subject: [PATCH] Change CirclePage (add feature, change renderer) (#57) Add ActionButtonItem for Visibility, Enable/Disable from MenuItem Change CirclePageRenderer to don't use Layout. it only use one box. --- .../CirclePageRenderer.cs | 439 +++++++++++++++--- .../CirclePageWidget.cs | 293 ------------ Xamarin.Forms.CircularUI/ActionButtonItem.cs | 20 + Xamarin.Forms.CircularUI/CirclePage.cs | 6 +- 4 files changed, 390 insertions(+), 368 deletions(-) delete mode 100755 Xamarin.Forms.CircularUI.Tizen/CirclePageWidget.cs create mode 100644 Xamarin.Forms.CircularUI/ActionButtonItem.cs diff --git a/Xamarin.Forms.CircularUI.Tizen/CirclePageRenderer.cs b/Xamarin.Forms.CircularUI.Tizen/CirclePageRenderer.cs index 79ec47b5..bb8e2a66 100644 --- a/Xamarin.Forms.CircularUI.Tizen/CirclePageRenderer.cs +++ b/Xamarin.Forms.CircularUI.Tizen/CirclePageRenderer.cs @@ -1,12 +1,16 @@ -using ElmSharp.Wearable; +using ElmSharp; +using ElmSharp.Wearable; using System; -using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; using Xamarin.Forms.CircularUI; using Xamarin.Forms.Platform.Tizen; -using System.ComponentModel; +using Xamarin.Forms.Platform.Tizen.Native; [assembly: ExportRenderer(typeof(CirclePage), typeof(Xamarin.Forms.CircularUI.Tizen.CirclePageRenderer))] @@ -14,9 +18,21 @@ namespace Xamarin.Forms.CircularUI.Tizen { public class CirclePageRenderer : VisualElementRenderer { - CirclePageWidget _widget; + NBox _box; + + ElmSharp.Rectangle _bgColorObject; + ElmSharp.EvasImage _bgImageObject; + ElmSharp.Layout _surfaceLayout; + ElmSharp.Button _actionButton; + string _bgImage; + + ElmSharp.Wearable.CircleSurface _surface; IRotaryFocusable _currentRotaryFocusObject; + ElmSharp.Wearable.MoreOption _moreOption; + Dictionary _toolbarItemMap; + Dictionary _circleSurfaceItems; + public CirclePageRenderer() { RegisterPropertyHandler(Page.BackgroundImageProperty, UpdateBackgroundImage); @@ -24,72 +40,287 @@ public CirclePageRenderer() RegisterPropertyHandler(CirclePage.RotaryFocusObjectProperty, UpdateRotaryFocusObject); } - public ElmSharp.Wearable.CircleSurface CircleSurface => _widget.CircleSurface; + public ElmSharp.Wearable.CircleSurface CircleSurface => _surface; - protected override void OnElementChanged(ElementChangedEventArgs args) + protected override void OnElementChanged(ElementChangedEventArgs e) { - if (null == _widget) + if (_box == null) { - _widget = new CirclePageWidget(Xamarin.Forms.Platform.Tizen.Forms.NativeParent, Element); - _widget.LayoutUpdated += OnLayoutUpdated; - _widget.ToolbarOpened += OnToolbarOpened; - _widget.ToolbarClosed += OnToolbarClosed; - SetNativeView(_widget); + OnRealized(); } - if (args.NewElement != null) + if (e.NewElement != null) { - args.NewElement.Appearing += OnCirclePageAppearing; - args.NewElement.Disappearing += OnCirclePageDisappearing; + e.NewElement.Appearing += OnPageAppearing; + e.NewElement.Disappearing += OnPageDisappearing; + var toolbarItems = e.NewElement.ToolbarItems as ObservableCollection; + if (toolbarItems != null) + toolbarItems.CollectionChanged += OnToolbarItemChanged; + var circleSurfaceItems = e.NewElement.CircleSurfaceItems as ObservableCollection; + if (circleSurfaceItems != null) + circleSurfaceItems.CollectionChanged += OnCircleSurfaceItemsChanged; } - if (args.OldElement != null) + if (e.OldElement != null) { - args.OldElement.Appearing -= OnCirclePageAppearing; - args.OldElement.Disappearing -= OnCirclePageDisappearing; + e.OldElement.Appearing -= OnPageAppearing; + e.OldElement.Disappearing -= OnPageDisappearing; + var toolbarItems = e.NewElement.ToolbarItems as ObservableCollection; + if (toolbarItems != null) + toolbarItems.CollectionChanged -= OnToolbarItemChanged; + var circleSurfaceItems = e.NewElement.CircleSurfaceItems as ObservableCollection; + if (circleSurfaceItems != null) + circleSurfaceItems.CollectionChanged -= OnCircleSurfaceItemsChanged; } - base.OnElementChanged(args); + base.OnElementChanged(e); } + protected override void UpdateBackgroundColor(bool initialize) + { + if (initialize && Element.BackgroundColor.IsDefault) return; - protected void OnCirclePageAppearing(object sender, EventArgs e) + if (Element.BackgroundColor.A == 0) + { + _bgColorObject.Color = ElmSharp.Color.Transparent; + } + else + { + _bgColorObject.Color = Element.BackgroundColor.ToNative(); + } + UpdateBackground(); + } + protected void UpdateBackgroundImage(bool initialize) { - ActivateRotaryWidget(); + if (initialize && string.IsNullOrWhiteSpace(Element.BackgroundImage)) + return; + if (string.IsNullOrWhiteSpace(Element.BackgroundImage)) + { + _bgImageObject.File = null; + _bgImage = null; + } + else + { + _bgImageObject.File = ResourcePath.GetPath(Element.BackgroundImage); + _bgImage = Element.BackgroundImage; + } + UpdateBackground(); } + void OnRealized() + { + _box = new NBox(Xamarin.Forms.Platform.Tizen.Forms.NativeParent); + _box.SetLayoutCallback(OnLayout); + var rect = _box.Geometry; + + _bgColorObject = new ElmSharp.Rectangle(_box) + { + Color = ElmSharp.Color.Transparent + //Color = new ElmSharp.Color(0xff, 0, 0, 0xa0) + }; + _bgImageObject = new EvasImage(_box); + _surfaceLayout = new ElmSharp.Layout(_box); + _surface = new ElmSharp.Wearable.CircleSurface(_surfaceLayout); + _actionButton = new ElmSharp.Button(_box) + { + Style = "bottom" + }; + _actionButton.Clicked += OnActionButtonClicked; + + _moreOption = new ElmSharp.Wearable.MoreOption(_box); + _moreOption.Clicked += OnMoreOptionClicked; + _moreOption.Opened += ToolbarOpened; + _moreOption.Closed += ToolbarClosed; + _toolbarItemMap = new Dictionary(); + _circleSurfaceItems = new Dictionary(); - protected void OnCirclePageDisappearing(object sender, EventArgs e) + var btnRect = _actionButton.Geometry; + var btnX = (rect.Width - btnRect.Width) / 2; + var btnY = rect.Height - btnRect.Height; + _actionButton.Move(btnX, btnY); + + _box.PackEnd(_bgColorObject); + _box.PackEnd(_bgImageObject); + _box.PackEnd(_actionButton); + _box.PackEnd(_surfaceLayout); + _box.PackEnd(_moreOption); + + _bgColorObject.Show(); + _bgImageObject.Hide(); + _surfaceLayout.Show(); + _actionButton.Hide(); + _moreOption.Hide(); + + SetNativeView(_box); + } + void OnLayout() { - DeactivateRotaryWidget(); + var rect = _box.Geometry; + Element.Layout(rect.ToDP()); + _bgColorObject.Geometry = rect; + _bgImageObject.Geometry = rect; + + _bgImageObject.StackAbove(_bgColorObject); + EvasObject prev = _bgImageObject; + + IContainable container = _box; + foreach (var obj in container.Children) + { + obj.StackAbove(prev); + prev = obj; + } + + _surfaceLayout.Geometry = rect; + _surfaceLayout.StackAbove(prev); + + _actionButton.StackAbove(_surfaceLayout); + + _moreOption.StackAbove(_actionButton); } - protected override void UpdateBackgroundColor(bool initialize) + void UpdateBackground() { - if (initialize && Element.BackgroundColor.IsDefault) return; - - if (Element.BackgroundColor.A == 0) + if (string.IsNullOrEmpty(_bgImage)) { - _widget.BackgroundColor = ElmSharp.Color.Transparent; + _bgImageObject.Hide(); } else { - _widget.BackgroundColor = Element.BackgroundColor.ToNative(); + _bgImageObject.Show(); } } - IRotaryActionWidget GetRotaryWidget(IRotaryFocusable focusable) + void UpdateActionButton(bool initialize) { - var consumer = focusable as BindableObject; - IRotaryActionWidget rotaryWidget = null; - if (consumer != null) + if (initialize && Element.ActionButton == null) return; + + if (Element.ActionButton != null) { - if (consumer is CircleSliderSurfaceItem) + Element.ActionButton.PropertyChanged += OnActionButtonItemChanged; + _actionButton.Text = Element.ActionButton.Text; + _actionButton.IsEnabled = Element.ActionButton.IsEnable; + if (Element.ActionButton.IsVisible) + _actionButton.Show(); + else + _actionButton.Hide(); + } + } + void OnActionButtonItemChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == MenuItem.TextProperty.PropertyName) + { + _actionButton.Text = Element.ActionButton.Text; + } + else if (e.PropertyName == ActionButtonItem.IsEnableProperty.PropertyName) + { + _actionButton.IsEnabled = Element.ActionButton.IsEnable; + } + else if (e.PropertyName == ActionButtonItem.IsVisibleProperty.PropertyName) + { + if (Element.ActionButton.IsVisible) { - ICircleSurfaceItem item = consumer as ICircleSurfaceItem; - rotaryWidget = _widget.GetCircleWidget(item) as IRotaryActionWidget; + _actionButton.Show(); } else { - var consumerRenderer = Platform.Tizen.Platform.GetRenderer(consumer); - rotaryWidget = consumerRenderer?.NativeView as IRotaryActionWidget; + _actionButton.Hide(); } } - return rotaryWidget; + } + void OnActionButtonClicked(object sender, EventArgs e) + { + if (Element.ActionButton != null) + { + Element.ActionButton.Command.Execute(Element.ActionButton.CommandParameter); + } + } + void OnToolbarItemChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Add || + e.Action == NotifyCollectionChangedAction.Replace) + { + foreach (ToolbarItem item in e.NewItems) AddToolbarItem(item); + } + if (e.Action == NotifyCollectionChangedAction.Remove || + e.Action == NotifyCollectionChangedAction.Replace) + { + foreach (ToolbarItem item in e.OldItems) RemoveToolbarITem(item); + } + if (Element.ToolbarItems.Count > 0) + { + _moreOption.Show(); + } + else + { + _moreOption.Hide(); + } + } + void AddToolbarItem(ToolbarItem item) + { + var moreOptionItem = new ActionMoreOptionItem(); + var icon = item.Icon; + if (!string.IsNullOrEmpty(icon.File)) + { + var img = new ElmSharp.Image(_moreOption); + img.LoadAsync(ResourcePath.GetPath(icon.File)); + moreOptionItem.Icon = img; + } + var text = item.Text; + if (!string.IsNullOrEmpty(text)) + { + moreOptionItem.MainText = text; + } + if (item is CircleToolbarItem) + { + var subText = ((CircleToolbarItem)item).SubText; + if (!string.IsNullOrEmpty(subText)) + { + moreOptionItem.SubText = subText; + } + } + moreOptionItem.Action = () => item.Activate(); + _moreOption.Items.Add(moreOptionItem); + _toolbarItemMap[item] = moreOptionItem; + } + void RemoveToolbarITem(ToolbarItem item) + { + if (_toolbarItemMap.TryGetValue(item, out var moreOptionItem)) + { + _moreOption?.Items.Remove(moreOptionItem); + _toolbarItemMap.Remove(item); + } + } + void OnMoreOptionClicked(object sender, ElmSharp.Wearable.MoreOptionItemEventArgs e) + { + var item = e.Item as ActionMoreOptionItem; + if (item != null) + { + item.Action?.Invoke(); + } + _moreOption.IsOpened = false; + } + void UpdateRotaryFocusObject(bool initialize) + { + if (initialize) + { + _currentRotaryFocusObject = Element.RotaryFocusObject; + } + else + { + DeactivateRotaryWidget(); + _currentRotaryFocusObject = Element.RotaryFocusObject; + ActivateRotaryWidget(); + } + } + void OnPageDisappearing(object sender, EventArgs e) + { + DeactivateRotaryWidget(); + } + void OnPageAppearing(object sender, EventArgs e) + { + ActivateRotaryWidget(); + } + void ToolbarClosed(object sender, EventArgs e) + { + ActivateRotaryWidget(); + } + void ToolbarOpened(object sender, EventArgs e) + { + DeactivateRotaryWidget(); } void ActivateRotaryWidget() @@ -103,7 +334,6 @@ void ActivateRotaryWidget() GetRotaryWidget(_currentRotaryFocusObject)?.Activate(); } } - void DeactivateRotaryWidget() { if (_currentRotaryFocusObject is IRotaryEventReceiver) @@ -115,70 +345,135 @@ void DeactivateRotaryWidget() GetRotaryWidget(_currentRotaryFocusObject)?.Deactivate(); } } - - void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs args) + void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs e) { if (_currentRotaryFocusObject is IRotaryEventReceiver) { var receiver = _currentRotaryFocusObject as IRotaryEventReceiver; - receiver.Rotate(new RotaryEventArgs { IsClockwise = args.IsClockwise }); + receiver.Rotate(new RotaryEventArgs { IsClockwise = e.IsClockwise }); } } - void OnToolbarClosed(object sender, EventArgs e) + void OnCircleSurfaceItemsChanged(object sender, NotifyCollectionChangedEventArgs e) { - ActivateRotaryWidget(); + if (e.Action == NotifyCollectionChangedAction.Add || + e.Action == NotifyCollectionChangedAction.Replace) + { + foreach (ICircleSurfaceItem item in e.NewItems) + AddCircleSurfaceItem(item); + } + if (e.Action == NotifyCollectionChangedAction.Remove || + e.Action == NotifyCollectionChangedAction.Replace) + { + foreach (ICircleSurfaceItem item in e.OldItems) + RemoveCircleSurfaceItem(item); + } } - void OnToolbarOpened(object sender, EventArgs e) + void AddCircleSurfaceItem(ICircleSurfaceItem item) { - DeactivateRotaryWidget(); + if (item is CircleProgressBarSurfaceItem) + { + var widget = new CircleProgressBarSurfaceItemImplements(item as CircleProgressBarSurfaceItem, _surfaceLayout, _surface); + _circleSurfaceItems[item] = widget; + } + else if (item is CircleSliderSurfaceItem) + { + var widget = new CircleSliderSurfaceItemImplements(item as CircleSliderSurfaceItem, _surfaceLayout, _surface); + _circleSurfaceItems[item] = widget; + } } - - void UpdateRotaryFocusObject(bool initialize) + void RemoveCircleSurfaceItem(ICircleSurfaceItem item) { - if (!initialize) + if (_circleSurfaceItems.TryGetValue(item, out var widget)) { - DeactivateRotaryWidget(); + ElmSharp.EvasObject obj = widget as ElmSharp.EvasObject; + obj?.Unrealize(); + _circleSurfaceItems.Remove(item); } - _currentRotaryFocusObject = Element.RotaryFocusObject; - if (!initialize) + } + + IRotaryActionWidget GetRotaryWidget(IRotaryFocusable focusable) + { + var consumer = focusable as BindableObject; + IRotaryActionWidget rotaryWidget = null; + if (consumer != null) { - ActivateRotaryWidget(); + if (consumer is CircleSliderSurfaceItem) + { + ICircleSurfaceItem item = consumer as ICircleSurfaceItem; + rotaryWidget = GetCircleWidget(item) as IRotaryActionWidget; + } + else + { + var consumerRenderer = Platform.Tizen.Platform.GetRenderer(consumer); + rotaryWidget = consumerRenderer?.NativeView as IRotaryActionWidget; + } } + return rotaryWidget; } - void OnLayoutUpdated(object sender, Platform.Tizen.Native.LayoutEventArgs args) + public ICircleWidget GetCircleWidget(ICircleSurfaceItem item) { - DoLayout(args); + ElmSharp.Wearable.ICircleWidget widget; + if (_circleSurfaceItems.TryGetValue(item, out widget)) + { + return widget; + } + return null; } - void UpdateBackgroundImage(bool initialize) + class NBox : ElmSharp.Box, IContainable { - if (initialize && string.IsNullOrWhiteSpace(Element.BackgroundImage)) - return; - if (string.IsNullOrWhiteSpace(Element.BackgroundImage)) + ReObservableCollection _children; + public NBox(EvasObject parent) : base(parent) { - _widget.File = null; + _children = new ReObservableCollection(); + _children.CollectionChanged += OnChildrenChanged; } - else + IList IContainable.Children => _children; + + void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) { - _widget.File = ResourcePath.GetPath(Element.BackgroundImage); + if (e.Action == NotifyCollectionChangedAction.Add) + { + foreach (var child in e.NewItems) + { + if (child is EvasObject) + { + PackEnd(child as EvasObject); + } + } + } + else if (e.Action == NotifyCollectionChangedAction.Remove) + { + foreach (var child in e.OldItems) + { + if (child is EvasObject) + { + UnPack(child as EvasObject); + } + } + } } } - void UpdateActionButton(bool initialize) + class ActionMoreOptionItem : MoreOptionItem { - if (initialize && Element.ActionButton == null) return; + public Action Action { get; set; } + } - if (Element.ActionButton != null) - { - var item = Element.ActionButton; - _widget.ShowActionButton(item.Text, item.Icon, () => item.Activate()); - } - else + class ReObservableCollection : ObservableCollection + { + protected override void ClearItems() { - _widget.HideActionButton(); + var oldItems = Items.ToList(); + Items.Clear(); + using (BlockReentrancy()) + { + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems)); + } + base.ClearItems(); } } } diff --git a/Xamarin.Forms.CircularUI.Tizen/CirclePageWidget.cs b/Xamarin.Forms.CircularUI.Tizen/CirclePageWidget.cs deleted file mode 100755 index 4886a6de..00000000 --- a/Xamarin.Forms.CircularUI.Tizen/CirclePageWidget.cs +++ /dev/null @@ -1,293 +0,0 @@ -using ElmSharp; -using ElmSharp.Wearable; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Text; -using Xamarin.Forms.CircularUI; -using Xamarin.Forms.Platform.Tizen; -using Xamarin.Forms.Platform.Tizen.Native; - -namespace Xamarin.Forms.CircularUI.Tizen -{ - class CirclePageWidget : ElmSharp.Layout, IContainable - { - ElmSharp.Layout _circleOptionLayout; - ElmSharp.Layout _circleLayout; - ElmSharp.Layout _actionButtonLayout; - ElmSharp.Wearable.CircleSurface _surface; - ElmSharp.Wearable.MoreOption _moreOption; - - Xamarin.Forms.Platform.Tizen.Native.Page _content; - - Dictionary _toolbarItemMap; - Dictionary _circleSurfaceItems; - - ElmSharp.Button _actionButton; - - CirclePage _page; - - public CirclePageWidget(EvasObject parent, CirclePage element) : base(parent) - { - SetTheme("layout", "application", "default"); - - _actionButtonLayout = new ElmSharp.Layout(this); - _actionButtonLayout.SetTheme("layout", "bottom_button", "default"); - _actionButtonLayout.Show(); - SetPartContent("elm.swallow.bg", _actionButtonLayout); - - _content = new Xamarin.Forms.Platform.Tizen.Native.Page(_actionButtonLayout); - _actionButtonLayout.SetContent(_content); - _content.Show(); - - _circleOptionLayout = new ElmSharp.Layout(this); - _circleOptionLayout.SetTheme("layout", "application", "default"); - _circleOptionLayout.Show(); - SetPartContent("elm.swallow.content", _circleOptionLayout); - - _circleLayout = new ElmSharp.Layout(_circleOptionLayout); - _circleLayout.Show(); - _circleOptionLayout.SetPartContent("elm.swallow.bg", _circleLayout); - - _surface = new ElmSharp.Wearable.CircleSurface(_circleLayout); - - Console.WriteLine($"Circle Surface hash is {_surface.GetHashCode()}"); - - Console.WriteLine($"element is {element.ToString()}"); - - Console.WriteLine($"element.ToolbarItems is {element.ToolbarItems}"); - - var items = element.ToolbarItems as ObservableCollection; - items.CollectionChanged += OnToolbarItemsChanged; - PrepareToolbarItems(items); - - var surfaceItems = element.CircleSurfaceItems as ObservableCollection; - surfaceItems.CollectionChanged += OnCircleSurfaceItemsChanged; - PrepareCircleSurfaceItems(surfaceItems); - - _page = element; - } - - public event EventHandler LayoutUpdated - { - add => _content.LayoutUpdated += value; - remove => _content.LayoutUpdated -= value; - } - - public event EventHandler ToolbarOpened; - public event EventHandler ToolbarClosed; - - IList IContainable.Children => _content.Children; - - public CircleSurface CircleSurface => _surface; - - public override ElmSharp.Color BackgroundColor - { - get => _content.Color; - set => _content.Color = value; - } - - public string File - { - get => _content.File; - set => _content.File = value; - } - - public void ShowActionButton(string text, string image = null, Action action = null) - { - if (_actionButton != null) - HideActionButton(); - - _actionButton = new ElmSharp.Button(_actionButtonLayout) - { - Text = text, - Style = "bottom" - }; - if (image != null) - { - var path = ResourcePath.GetPath(image); - var buttonImage = new ElmSharp.Image(_actionButton); - buttonImage.LoadAsync(path); - buttonImage.Show(); - _actionButton.SetPartContent("elm.swallow.content", buttonImage); - } - if (action != null) - { - _actionButton.Clicked += (s, e) => action(); - } - _actionButtonLayout.SetPartContent("elm.swallow.button", _actionButton); - - Console.WriteLine($"ShowActionButton"); - } - - public void HideActionButton() - { - if (_actionButton != null) - { - _actionButton.Unrealize(); - _actionButtonLayout.SetPartContent("elm.swallow.button", null); - _actionButton = null; - } - Console.WriteLine($"HideActionButton"); - } - - protected override void OnUnrealize() - { - var toolbarItems = _page.ToolbarItems as ObservableCollection; - if (null != toolbarItems) - { - toolbarItems.CollectionChanged -= OnToolbarItemsChanged; - } - - var circleSurfaceItems = _page.CircleSurfaceItems as ObservableCollection; - if (null != circleSurfaceItems) - { - circleSurfaceItems.CollectionChanged -= OnCircleSurfaceItemsChanged; - } - base.OnUnrealize(); - } - - void PrepareCircleSurfaceItems(IList items) - { - if (null == _circleSurfaceItems) - { - _circleSurfaceItems = new Dictionary(); - } - foreach (ICircleSurfaceItem item in items) - { - if (item is CircleProgressBarSurfaceItem) - { - var widget = new CircleProgressBarSurfaceItemImplements(item as CircleProgressBarSurfaceItem, _circleLayout, _surface); - _circleSurfaceItems[item] = widget; - } - else if (item is CircleSliderSurfaceItem) - { - var widget = new CircleSliderSurfaceItemImplements(item as CircleSliderSurfaceItem, _circleLayout, _surface); - _circleSurfaceItems[item] = widget; - } - } - } - - void OnCircleSurfaceItemsChanged(object sender, NotifyCollectionChangedEventArgs args) - { - if (args.Action == NotifyCollectionChangedAction.Add || - args.Action == NotifyCollectionChangedAction.Replace) - { - PrepareCircleSurfaceItems(args.NewItems); - } - if (args.Action == NotifyCollectionChangedAction.Remove || - args.Action == NotifyCollectionChangedAction.Replace) - { - foreach (ICircleSurfaceItem item in args.OldItems) - { - ElmSharp.Wearable.ICircleWidget widget; - if (_circleSurfaceItems.TryGetValue(item, out widget)) - { - ElmSharp.EvasObject obj = widget as ElmSharp.EvasObject; - obj?.Unrealize(); - _circleSurfaceItems.Remove(item); - } - } - } - } - - public ICircleWidget GetCircleWidget(ICircleSurfaceItem item) - { - ElmSharp.Wearable.ICircleWidget widget; - if (_circleSurfaceItems.TryGetValue(item, out widget)) - { - return widget; - } - return null; - } - - void PrepareToolbarItems(IList items) - { - if (items == null || items.Count <= 0) return; - - if (_moreOption == null) - { - initToolbar(); - } - foreach (ToolbarItem item in items) - { - var moreOptionItem = new ActionMoreOptionItem(); - var icon = item.Icon; - if (!string.IsNullOrEmpty(icon.File)) - { - var img = new ElmSharp.Image(_moreOption); - img.LoadAsync(ResourcePath.GetPath(icon.File)); - moreOptionItem.Icon = img; - } - var text = item.Text; - if (!string.IsNullOrEmpty(text)) - { - moreOptionItem.MainText = text; - } - if (item is CircleToolbarItem) - { - var subText = ((CircleToolbarItem)item).SubText; - if (!string.IsNullOrEmpty(subText)) - { - moreOptionItem.SubText = subText; - } - } - moreOptionItem.Action = () => item.Activate(); - _moreOption.Items.Add(moreOptionItem); - _toolbarItemMap[item] = moreOptionItem; - } - } - - void OnToolbarItemsChanged(object sender, NotifyCollectionChangedEventArgs args) - { - if (args.Action == NotifyCollectionChangedAction.Add || - args.Action == NotifyCollectionChangedAction.Replace) - { - PrepareToolbarItems(args.NewItems); - } - if (args.Action == NotifyCollectionChangedAction.Remove || - args.Action == NotifyCollectionChangedAction.Replace) - { - foreach (ToolbarItem item in args.OldItems) - { - ElmSharp.Wearable.MoreOptionItem moreOptionItem; - if (_toolbarItemMap.TryGetValue(item, out moreOptionItem)) - { - _moreOption?.Items.Remove(moreOptionItem); - _toolbarItemMap.Remove(item); - } - } - } - } - - void initToolbar() - { - _moreOption = new MoreOption(_circleOptionLayout); - _circleOptionLayout.SetPartContent("elm.swallow.content", _moreOption); - _moreOption.Show(); - _toolbarItemMap = new Dictionary(); - _moreOption.Clicked += MoreOptionClicked; - _moreOption.Opened += (s, e) => ToolbarOpened?.Invoke(this, EventArgs.Empty); - _moreOption.Closed += (s, e) => ToolbarClosed?.Invoke(this, EventArgs.Empty); - } - - void MoreOptionClicked(object sender, MoreOptionItemEventArgs e) - { - var item = e.Item as ActionMoreOptionItem; - if (item != null) - { - item.Action?.Invoke(); - } - _moreOption.IsOpened = false; - } - - class ActionMoreOptionItem : MoreOptionItem - { - public Action Action { get; set; } - } - } -} diff --git a/Xamarin.Forms.CircularUI/ActionButtonItem.cs b/Xamarin.Forms.CircularUI/ActionButtonItem.cs new file mode 100644 index 00000000..1d0e0401 --- /dev/null +++ b/Xamarin.Forms.CircularUI/ActionButtonItem.cs @@ -0,0 +1,20 @@ +namespace Xamarin.Forms.CircularUI +{ + public class ActionButtonItem : MenuItem + { + public static BindableProperty IsEnableProperty = BindableProperty.Create(nameof(IsEnable), typeof(bool), typeof(ActionButtonItem), true); + public static BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(ActionButtonItem), false); + + public bool IsEnable + { + get => (bool)GetValue(IsEnableProperty); + set => SetValue(IsEnableProperty, value); + } + + public bool IsVisible + { + get => (bool)GetValue(IsVisibleProperty); + set => SetValue(IsVisibleProperty, value); + } + } +} diff --git a/Xamarin.Forms.CircularUI/CirclePage.cs b/Xamarin.Forms.CircularUI/CirclePage.cs index 1d67ec5e..2bf3abe1 100755 --- a/Xamarin.Forms.CircularUI/CirclePage.cs +++ b/Xamarin.Forms.CircularUI/CirclePage.cs @@ -8,7 +8,7 @@ namespace Xamarin.Forms.CircularUI { public class CirclePage : ContentPage { - public static readonly BindableProperty ActionButtonProperty = BindableProperty.Create(nameof(ActionButton), typeof(MenuItem), typeof(CirclePage), null, + public static readonly BindableProperty ActionButtonProperty = BindableProperty.Create(nameof(ActionButton), typeof(ActionButtonItem), typeof(CirclePage), null, propertyChanged: (b, o, n) => { if (n != null) @@ -43,9 +43,9 @@ public CirclePage() public IList CircleSurfaceItems { get; } - public MenuItem ActionButton + public ActionButtonItem ActionButton { - get => (MenuItem)GetValue(ActionButtonProperty); + get => (ActionButtonItem)GetValue(ActionButtonProperty); set => SetValue(ActionButtonProperty, value); }