[Tizen] Changed CarouselView scroll logic according to the Core change. (#10235)

* [Tizen] Invoke ItemsView Scrolled event

* [Tizen] Changed CarouselView scroll logic

* [Tizen] Add IndicatorView
This commit is contained in:
sung-su.kim 2020-04-08 01:53:28 +09:00 коммит произвёл GitHub
Родитель c8b99fb391
Коммит ed2ad60b25
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 287 добавлений и 32 удалений

Просмотреть файл

@ -124,9 +124,7 @@ namespace Xamarin.Forms.Platform
internal class _CheckBoxRenderer { }
#endif
#if !TIZEN4_0
[RenderWith(typeof(IndicatorViewRenderer))]
#endif
internal class _IndicatorViewRenderer { }
#if __IOS__

Просмотреть файл

@ -22,7 +22,7 @@ namespace Xamarin.Forms.ControlGallery.Tizen
{
var app = new MainApplication();
FormsMaps.Init("HERE", "write-your-API-key-here");
Forms.SetFlags("CollectionView_Experimental", "Shell_Experimental", "MediaElement_Experimental");
Forms.SetFlags("CollectionView_Experimental", "Shell_Experimental", "MediaElement_Experimental", "IndicatorView_Experimental");
Forms.Init(app);
FormsMaterial.Init();
app.Run(args);

Просмотреть файл

@ -27,6 +27,8 @@ namespace Xamarin.Forms.Platform.Tizen.Native
SnapPointsType _snapPoints;
ESize _itemSize = new ESize(-1, -1);
public event EventHandler<ItemsViewScrolledEventArgs> Scrolled;
public CollectionView(EvasObject parent) : base(parent)
{
SetLayoutCallback(OnLayout);
@ -522,9 +524,24 @@ namespace Xamarin.Forms.Platform.Tizen.Native
_innerLayout.MinimumHeight = size.Height;
}
int _previousHorizontalOffset = 0;
int _previousVerticalOffset = 0;
void OnScrolled(object sender, EventArgs e)
{
_layoutManager.LayoutItems(Scroller.CurrentRegion);
_layoutManager.LayoutItems(ViewPort);
var args = new ItemsViewScrolledEventArgs();
args.FirstVisibleItemIndex = _layoutManager.GetVisibleItemIndex(ViewPort.X, ViewPort.Y);
args.CenterItemIndex = _layoutManager.GetVisibleItemIndex(ViewPort.X + (ViewPort.Width / 2), ViewPort.Y + (ViewPort.Height / 2));
args.LastVisibleItemIndex = _layoutManager.GetVisibleItemIndex(ViewPort.X + ViewPort.Width, ViewPort.Y + ViewPort.Height);
args.HorizontalOffset = ViewPort.X;
args.HorizontalDelta = ViewPort.X - _previousHorizontalOffset;
args.VerticalOffset = ViewPort.Y;
args.VerticalDelta = ViewPort.Y - _previousVerticalOffset;
Scrolled?.Invoke(this, args);
_previousHorizontalOffset = ViewPort.X;
_previousVerticalOffset = ViewPort.Y;
}
void UpdateSnapPointsType(SnapPointsType snapPoints)

Просмотреть файл

@ -338,6 +338,29 @@ namespace Xamarin.Forms.Platform.Tizen.Native
}
}
public int GetVisibleItemIndex(int x, int y)
{
int index = 0;
if (x < 0 || y < 0)
return index;
if (_scrollCanvasSize.Width < x || _scrollCanvasSize.Height < y)
return CollectionView.Count - 1;
int first = (IsHorizontal ? x : y) / BaseItemSize;
if (_hasUnevenRows)
first = _accumulatedItemSizes.FindIndex(current => (IsHorizontal ? x : y) <= current);
int second = (IsHorizontal ? y : x) / ColumnSize;
if (second == Span)
second -= 1;
index = (first * Span) + second;
if (index < CollectionView.Count)
return index;
return CollectionView.Count - 1;
}
void InitializeMeasureCache()
{
_baseItemSize = 0;

Просмотреть файл

@ -28,5 +28,7 @@ namespace Xamarin.Forms.Platform.Tizen.Native
void Reset();
void ItemMeasureInvalidated(int index);
int GetVisibleItemIndex(int x, int y);
}
}

Просмотреть файл

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using ElmSharp;
namespace Xamarin.Forms.Platform.Tizen.Native
{
public class IndicatorView : Index
{
List<IndexItem> _list = new List<IndexItem>();
public IndicatorView(EvasObject parent) : base(parent)
{
AutoHide = false;
IsHorizontal = true;
Style = "pagecontrol";
if (Device.Idiom == TargetIdiom.Watch)
Style = "circle";
}
public event EventHandler<SelectedPositionChangedEventArgs> SelectedPosition;
public void UpdateSelectedIndex(int index)
{
if (index > -1 && index < _list.Count)
{
_list[index].Select(true);
}
}
public void AppendIndex(int count = 1)
{
for (int i = 0; i < count; i++)
{
var item = Append(null);
item.Selected += OnSelected;
_list.Add(item);
}
if (Device.Idiom == TargetIdiom.Watch)
ApplyStyle();
}
public void ClearIndex()
{
foreach (var item in _list)
{
item.Selected -= OnSelected;
}
_list.Clear();
Clear();
}
void ApplyStyle()
{
foreach (var item in _list)
{
int center = 10;
int start = center - (_list.Count / 2);
int index = _list.IndexOf(item);
int position = start + index;
if (_list.Count % 2 == 0)
{
string itemStyle = "item/even_" + position;
item.Style = itemStyle;
}
else
{
string itemStyle = "item/odd_" + position;
item.Style = itemStyle;
}
}
}
void OnSelected(object sender, EventArgs e)
{
var index = _list.IndexOf((IndexItem)sender);
SelectedPosition?.Invoke(this, new SelectedPositionChangedEventArgs(index));
UpdateSelectedIndex(index);
}
}
}

Просмотреть файл

@ -296,6 +296,22 @@ namespace Xamarin.Forms.Platform.Tizen.Native
}
}
public int GetVisibleItemIndex(int x, int y)
{
int coordinate = IsHorizontal ? x : y;
int canvasSize = IsHorizontal ? _scrollCanvasSize.Width : _scrollCanvasSize.Height;
if (coordinate < 0)
return 0;
if (canvasSize < coordinate)
return CollectionView.Count - 1;
if (!_hasUnevenRows)
return coordinate / BaseItemSize;
else
return _accumulatedItemSizes.FindIndex(current => coordinate <= current);
}
void InitializeMeasureCache()
{
_baseItemSize = 0;

Просмотреть файл

@ -30,6 +30,7 @@ using Xamarin.Forms.Platform.Tizen;
[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
[assembly: ExportRenderer(typeof(IndicatorView), typeof(IndicatorViewRenderer))]
[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
@ -42,6 +43,7 @@ using Xamarin.Forms.Platform.Tizen;
[assembly: ExportRenderer(typeof(SwipeView), typeof(SwipeViewRenderer))]
[assembly: ExportRenderer(typeof(RefreshView), typeof(RefreshViewRenderer))]
[assembly: ExportRenderer(typeof(MediaElement), typeof(MediaElementRenderer))]
[assembly: ExportRenderer(typeof(IndicatorView), typeof(IndicatorViewRenderer))]
[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImageSourceHandler))]

Просмотреть файл

@ -1,4 +1,6 @@
namespace Xamarin.Forms.Platform.Tizen
using System;
namespace Xamarin.Forms.Platform.Tizen
{
public class CarouselViewRenderer : ItemsViewRenderer<CarouselView, Native.CarouselView>
{
@ -7,7 +9,8 @@
RegisterPropertyHandler(CarouselView.ItemsLayoutProperty, UpdateItemsLayout);
RegisterPropertyHandler(CarouselView.IsBounceEnabledProperty, UpdateIsBounceEnabled);
RegisterPropertyHandler(CarouselView.IsSwipeEnabledProperty, UpdateIsSwipeEnabled);
RegisterPropertyHandler(CarouselView.PositionProperty, UpdatePosition);
RegisterPropertyHandler(CarouselView.PositionProperty, UpdatePositionFromElement);
RegisterPropertyHandler(CarouselView.CurrentItemProperty, UpdateCurrentItemFromElement);
}
protected override Native.CarouselView CreateNativeControl(ElmSharp.EvasObject parent)
@ -20,17 +23,23 @@
return Element.ItemsLayout;
}
ElmSharp.SmartEvent _animationStart;
ElmSharp.SmartEvent _animationStop;
protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
{
base.OnElementChanged(e);
Control.Scroll.Scrolled += OnScrollStart;
Control.Scroll.PageScrolled += OnScrollStop;
}
protected override void OnItemSelectedFromUI(object sender, SelectedItemChangedEventArgs e)
{
Element.Position = e.SelectedItemIndex;
Element.CurrentItem = e.SelectedItem;
if (e.NewElement != null)
{
Control.Scrolled += OnScrolled;
Control.Scroll.DragStart += OnDragStart;
Control.Scroll.DragStop += OnDragStop;
_animationStart = new ElmSharp.SmartEvent(Control.Scroll, Control.Scroll.RealHandle, "scroll,anim,start");
_animationStart.On += OnScrollStart;
_animationStop = new ElmSharp.SmartEvent(Control.Scroll, Control.Scroll.RealHandle, "scroll,anim,stop");
_animationStop.On += OnScrollStop;
}
UpdatePositionFromElement(false);
UpdateCurrentItemFromElement(false);
}
protected override void Dispose(bool disposing)
@ -39,39 +48,79 @@
{
if (Element != null)
{
Control.Scroll.Scrolled -= OnScrollStart;
Control.Scroll.PageScrolled -= OnScrollStop;
Control.Scrolled -= OnScrolled;
Control.Scroll.DragStart -= OnDragStart;
Control.Scroll.DragStop -= OnDragStop;
_animationStart.On -= OnScrollStart;
_animationStop.On -= OnScrollStop;
}
}
base.Dispose(disposing);
}
void OnDragStart(object sender, System.EventArgs e)
{
Element.SetIsDragging(true);
Element.IsScrolling = true;
}
void OnDragStop(object sender, System.EventArgs e)
{
Element.SetIsDragging(false);
Element.IsScrolling = false;
}
void OnScrollStart(object sender, System.EventArgs e)
{
if (!Element.IsDragging)
{
Element.SetIsDragging(true);
}
Element.IsScrolling = true;
}
void OnScrollStop(object sender, System.EventArgs e)
{
if (Element.IsDragging)
{
Element.SetIsDragging(false);
}
var scrollerIndex = Control.LayoutManager.IsHorizontal ? Control.Scroll.HorizontalPageIndex : Control.Scroll.VerticalPageIndex;
Element.SetValueFromRenderer(CarouselView.PositionProperty, scrollerIndex);
Element.SetValueFromRenderer(CarouselView.CurrentItemProperty, Control.Adaptor[scrollerIndex]);
Control.Adaptor.RequestItemSelected(Control.Adaptor[scrollerIndex]);
Element.IsScrolling = false;
}
void UpdatePosition(bool initialize)
void OnScrolled(object sender, ItemsViewScrolledEventArgs e)
{
if (initialize)
{
if (!Element.IsScrolling)
Element.IsScrolling = true;
if (Element.IsDragging)
if (Element.Position != e.CenterItemIndex)
Element.SetValueFromRenderer(CarouselView.PositionProperty, e.CenterItemIndex);
}
void UpdateCurrentItemFromElement(bool isInitializing)
{
if (isInitializing)
return;
}
if (Element.Position > -1 && Element.Position < Control.Adaptor.Count)
if (Element.CurrentItem != null)
ScrollTo(Control.Adaptor.GetItemIndex(Element.CurrentItem));
}
void UpdatePositionFromElement(bool isInitializing)
{
if (isInitializing)
return;
ScrollTo(Element.Position);
}
void ScrollTo(int position)
{
if (Element.IsScrolling)
return;
if (position > -1 && position < Control.Adaptor.Count)
{
Control.Adaptor.RequestItemSelected(Element.Position);
Element.CurrentItem = Control.Adaptor[Element.Position];
var scrollerIndex = Control.LayoutManager.IsHorizontal ? Control.Scroll.HorizontalPageIndex : Control.Scroll.VerticalPageIndex;
if (position != scrollerIndex)
Control.ScrollTo(position);
}
}

Просмотреть файл

@ -0,0 +1,59 @@
using System.Collections;
namespace Xamarin.Forms.Platform.Tizen
{
public class IndicatorViewRenderer : ViewRenderer<IndicatorView, Native.IndicatorView>
{
public IndicatorViewRenderer()
{
RegisterPropertyHandler(IndicatorView.CountProperty, UpdateItemsSource);
RegisterPropertyHandler(IndicatorView.PositionProperty, UpdatePosition);
}
protected override void OnElementChanged(ElementChangedEventArgs<IndicatorView> e)
{
if (Control == null)
{
SetNativeControl(new Native.IndicatorView(Forms.NativeParent));
}
if (e.NewElement != null)
{
Control.SelectedPosition += OnSelectedPosition;
}
if (e.OldElement != null)
{
Control.SelectedPosition -= OnSelectedPosition;
}
base.OnElementChanged(e);
}
void OnSelectedPosition(object sender, SelectedPositionChangedEventArgs e)
{
Element.SetValueFromRenderer(IndicatorView.PositionProperty, (int)e.SelectedPosition);
}
void UpdateItemsSource()
{
Control.ClearIndex();
int count = 0;
if (Element.ItemsSource is ICollection collection)
{
count = collection.Count;
}
else
{
var enumerator = Element.ItemsSource.GetEnumerator();
while (enumerator?.MoveNext() ?? false)
{
count++;
}
}
Control.AppendIndex(count);
}
void UpdatePosition()
{
Control.UpdateSelectedIndex(Element.Position);
}
}
}

Просмотреть файл

@ -1,4 +1,5 @@
using System.Collections.Specialized;
using System;
using System.Collections.Specialized;
using System.Linq;
using Xamarin.Forms.Platform.Tizen.Native;
@ -26,6 +27,7 @@ namespace Xamarin.Forms.Platform.Tizen
if (Control == null)
{
SetNativeControl(CreateNativeControl(Forms.NativeParent));
Control.Scrolled += OnScrolled;
}
if (e.NewElement != null)
{
@ -44,6 +46,7 @@ namespace Xamarin.Forms.Platform.Tizen
{
Element.ScrollToRequested -= OnScrollToRequest;
ItemsLayout.PropertyChanged -= OnLayoutPropertyChanged;
Control.Scrolled -= OnScrolled;
}
if (_observableSource != null)
{
@ -93,6 +96,11 @@ namespace Xamarin.Forms.Platform.Tizen
{
}
void OnScrolled(object sender, ItemsViewScrolledEventArgs e)
{
Element.SendScrolled(e);
}
void OnScrollToRequest(object sender, ScrollToRequestEventArgs e)
{
if (e.Mode == ScrollToMode.Position)

Просмотреть файл

@ -104,6 +104,7 @@ namespace Xamarin.Forms.Platform.Tizen
Registered.Register(typeof(SwipeView), () => new SwipeViewRenderer());
Registered.Register(typeof(RefreshView), () => new RefreshViewRenderer());
Registered.Register(typeof(MediaElement), () => new MediaElementRenderer());
Registered.Register(typeof(IndicatorView), () => new IndicatorViewRenderer());
//ImageSourceHandlers
Registered.Register(typeof(FileImageSource), () => new FileImageSourceHandler());