public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;
+ public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create("BorderWidth", typeof(double), typeof(Button), -1d);
+
+ public static readonly BindableProperty BorderColorProperty = BorderElement.BorderColorProperty;
+
+ [Obsolete("BorderRadiusProperty is obsolete as of 2.5.0. Please use CornerRadius instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty BorderRadiusProperty = BindableProperty.Create("BorderRadius", typeof(int), typeof(Button), defaultValue: DefaultBorderRadius,
+ propertyChanged: BorderRadiusPropertyChanged);
+
+ public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create("CornerRadius", typeof(int), typeof(Button), defaultValue: BorderElement.DefaultCornerRadius,
+ propertyChanged: CornerRadiusPropertyChanged);
+
public static readonly BindableProperty ImageSourceProperty = ImageElement.ImageProperty;
[Obsolete("ImageProperty is obsolete as of 4.0.0. Please use ImageSourceProperty instead.")]
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
}
+
+ internal static readonly BindablePropertyKey IsPressedPropertyKey = BindableProperty.CreateReadOnly(nameof(IsPressed), typeof(bool), typeof(Button), default(bool));
+ public static readonly BindableProperty IsPressedProperty = IsPressedPropertyKey.BindableProperty;
+
+
readonly Lazy<PlatformConfigurationRegistry<Button>> _platformConfigurationRegistry;
- public Color BorderColor { get; set; }
+ public Color BorderColor
+ {
+ get { return (Color)GetValue(BorderElement.BorderColorProperty); }
+ set { SetValue(BorderElement.BorderColorProperty, value); }
+ }
+
+ [Obsolete("BorderRadius is obsolete as of 2.5.0. Please use CornerRadius instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public int BorderRadius
+ {
+ get { return (int)GetValue(BorderRadiusProperty); }
+ set { SetValue(BorderRadiusProperty, value); }
+ }
- public int CornerRadius { get; set; }
+ public int CornerRadius
+ {
+ get { return (int)GetValue(CornerRadiusProperty); }
+ set { SetValue(CornerRadiusProperty, value); }
+ }
- public double BorderWidth { get; set; }
+ public double BorderWidth
+ {
+ get { return (double)GetValue(BorderWidthProperty); }
+ set { SetValue(BorderWidthProperty, value); }
+ }
public ButtonContentLayout ContentLayout
{
[EditorBrowsable(EditorBrowsableState.Never)]
public void SendClicked() => ButtonElement.ElementClicked(this, this);
- public bool IsPressed => false;
+ public bool IsPressed => (bool)GetValue(IsPressedProperty);
[EditorBrowsable(EditorBrowsableState.Never)]
- void IButtonElement.SetIsPressed(bool isPressed) { }
+ void IButtonElement.SetIsPressed(bool isPressed) => SetValue(IsPressedPropertyKey, isPressed);
[EditorBrowsable(EditorBrowsableState.Never)]
public void SendPressed() => ButtonElement.ElementPressed(this, this);
ImageSource IImageElement.Source => ImageSource;
bool IImageElement.IsOpaque => false;
+
void IImageElement.RaiseImageSourcePropertyChanged() => OnPropertyChanged(ImageSourceProperty.PropertyName);
- int IBorderElement.CornerRadiusDefaultValue => (int)BorderElement.DefaultCornerRadius;
+ int IBorderElement.CornerRadiusDefaultValue => (int)CornerRadiusProperty.DefaultValue;
+
+ Color IBorderElement.BorderColorDefaultValue => (Color)BorderColorProperty.DefaultValue;
+
+ double IBorderElement.BorderWidthDefaultValue => (double)BorderWidthProperty.DefaultValue;
+
+
+ /// <summary>
+ /// Flag to prevent overwriting the value of CornerRadius
+ /// </summary>
+ bool cornerOrBorderRadiusSetting = false;
+
+ static void BorderRadiusPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ if (newvalue == oldvalue)
+ return;
+
+ var button = (Button)bindable;
+ var val = (int)newvalue;
+ if (val == DefaultBorderRadius && !button.cornerOrBorderRadiusSetting)
+ val = BorderElement.DefaultCornerRadius;
- Color IBorderElement.BorderColorDefaultValue => (Color)BorderElement.BorderColorProperty.DefaultValue;
+ var oldVal = (int)bindable.GetValue(Button.CornerRadiusProperty);
- double IBorderElement.BorderWidthDefaultValue => (double)-1d;
+ if (oldVal == val)
+ return;
+
+ if (button.cornerOrBorderRadiusSetting) // retain until BorderRadiusProperty removed
+ return;
+
+ button.cornerOrBorderRadiusSetting = true;
+ bindable.SetValue(Button.CornerRadiusProperty, val);
+ button.cornerOrBorderRadiusSetting = false;
+ }
+
+ static void CornerRadiusPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ if (newvalue == oldvalue)
+ return;
+
+ var button = (Button)bindable;
+ var val = (int)newvalue;
+ if (val == BorderElement.DefaultCornerRadius && !button.cornerOrBorderRadiusSetting)
+ val = DefaultBorderRadius;
+
+#pragma warning disable 0618 // retain until BorderRadiusProperty removed
+ var oldVal = (int)bindable.GetValue(Button.BorderRadiusProperty);
+#pragma warning restore
+
+ if (oldVal == val)
+ return;
+
+#pragma warning disable 0618 // retain until BorderRadiusProperty removed
+ button.cornerOrBorderRadiusSetting = true;
+ bindable.SetValue(Button.BorderRadiusProperty, val);
+ button.cornerOrBorderRadiusSetting = false;
+#pragma warning restore
+ }
void ITextElement.OnTextColorPropertyChanged(Color oldValue, Color newValue)
{
void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
{
+ InvalidateMeasure();
}
+
void IBorderElement.OnBorderColorPropertyChanged(Color oldValue, Color newValue)
{
}
+
bool IImageController.GetLoadAsAnimation() => false;
bool IImageElement.IsLoading => false;
{
}
- bool IBorderElement.IsCornerRadiusSet() => false;
- bool IBorderElement.IsBackgroundColorSet() => false;
- bool IBorderElement.IsBorderColorSet() => false;
- bool IBorderElement.IsBorderWidthSet() => false;
+ bool IBorderElement.IsCornerRadiusSet() => IsSet(CornerRadiusProperty);
+ bool IBorderElement.IsBackgroundColorSet() => IsSet(BackgroundColorProperty);
+ bool IBorderElement.IsBorderColorSet() => IsSet(BorderColorProperty);
+ bool IBorderElement.IsBorderWidthSet() => IsSet(BorderWidthProperty);
[DebuggerDisplay("Image Position = {Position}, Spacing = {Spacing}")]
--- /dev/null
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_CheckBoxRenderer))]
+ public class CheckBox : View, IElementConfiguration<CheckBox>, IBorderElement, IColorElement
+ {
+ readonly Lazy<PlatformConfigurationRegistry<CheckBox>> _platformConfigurationRegistry;
+ public const string IsCheckedVisualState = "IsChecked";
+
+ public static readonly BindableProperty IsCheckedProperty =
+ BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(CheckBox), false,
+ propertyChanged: (bindable, oldValue, newValue) => {
+ ((CheckBox)bindable).CheckedChanged?.Invoke(bindable, new CheckedChangedEventArgs((bool)newValue));
+ ((CheckBox)bindable).ChangeVisualState();
+ }, defaultBindingMode: BindingMode.TwoWay);
+
+ public static readonly BindableProperty ColorProperty = ColorElement.ColorProperty;
+
+ public Color Color
+ {
+ get => (Color)GetValue(ColorProperty);
+ set => SetValue(ColorProperty, value);
+ }
+
+
+ public CheckBox() => _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<CheckBox>>(() => new PlatformConfigurationRegistry<CheckBox>(this));
+
+ public bool IsChecked
+ {
+ get => (bool)GetValue(IsCheckedProperty);
+ set => SetValue(IsCheckedProperty, value);
+ }
+
+ protected internal override void ChangeVisualState()
+ {
+ if (IsEnabled && IsChecked)
+ VisualStateManager.GoToState(this, IsCheckedVisualState);
+ else
+ base.ChangeVisualState();
+ }
+
+ public event EventHandler<CheckedChangedEventArgs> CheckedChanged;
+
+ public IPlatformElementConfiguration<T, CheckBox> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+
+ void IBorderElement.OnBorderColorPropertyChanged(Color oldValue, Color newValue)
+ {
+ }
+
+ Color IBorderElement.BorderColor => Color.Transparent;
+ int IBorderElement.CornerRadius => 0;
+ double IBorderElement.BorderWidth => 0;
+ int IBorderElement.CornerRadiusDefaultValue => 0;
+ Color IBorderElement.BorderColorDefaultValue => Color.Transparent;
+ double IBorderElement.BorderWidthDefaultValue => 0;
+ bool IBorderElement.IsCornerRadiusSet() => false;
+ bool IBorderElement.IsBackgroundColorSet() => IsSet(BackgroundColorProperty);
+ bool IBorderElement.IsBorderColorSet() => false;
+ bool IBorderElement.IsBorderWidthSet() => false;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_DatePickerRenderer))]
+ public class DatePicker : View, IFontElement, ITextElement, IElementConfiguration<DatePicker>
+ {
+ public static readonly BindableProperty FormatProperty = BindableProperty.Create(nameof(Format), typeof(string), typeof(DatePicker), "d");
+
+ public static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(DatePicker), default(DateTime), BindingMode.TwoWay,
+ coerceValue: CoerceDate,
+ propertyChanged: DatePropertyChanged,
+ defaultValueCreator: (bindable) => DateTime.Today);
+
+ public static readonly BindableProperty MinimumDateProperty = BindableProperty.Create(nameof(MinimumDate), typeof(DateTime), typeof(DatePicker), new DateTime(1900, 1, 1),
+ validateValue: ValidateMinimumDate, coerceValue: CoerceMinimumDate);
+
+ public static readonly BindableProperty MaximumDateProperty = BindableProperty.Create(nameof(MaximumDate), typeof(DateTime), typeof(DatePicker), new DateTime(2100, 12, 31),
+ validateValue: ValidateMaximumDate, coerceValue: CoerceMaximumDate);
+
+ public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;
+
+ public static readonly BindableProperty CharacterSpacingProperty = TextElement.CharacterSpacingProperty;
+
+ public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty;
+
+ public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;
+
+ public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;
+
+ readonly Lazy<PlatformConfigurationRegistry<DatePicker>> _platformConfigurationRegistry;
+
+ public DatePicker()
+ {
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<DatePicker>>(() => new PlatformConfigurationRegistry<DatePicker>(this));
+ }
+
+ public DateTime Date
+ {
+ get { return (DateTime)GetValue(DateProperty); }
+ set { SetValue(DateProperty, value); }
+ }
+
+ public string Format
+ {
+ get { return (string)GetValue(FormatProperty); }
+ set { SetValue(FormatProperty, value); }
+ }
+
+ public DateTime MaximumDate
+ {
+ get { return (DateTime)GetValue(MaximumDateProperty); }
+ set { SetValue(MaximumDateProperty, value); }
+ }
+
+ public DateTime MinimumDate
+ {
+ get { return (DateTime)GetValue(MinimumDateProperty); }
+ set { SetValue(MinimumDateProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextElement.TextColorProperty); }
+ set { SetValue(TextElement.TextColorProperty, value); }
+ }
+
+ public double CharacterSpacing
+ {
+ get { return (double)GetValue(TextElement.CharacterSpacingProperty); }
+ set { SetValue(TextElement.CharacterSpacingProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontSizeChanged(double oldValue, double newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontChanged(Font oldValue, Font newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ double IFontElement.FontSizeDefaultValueCreator() =>
+ Device.GetNamedSize(NamedSize.Default, (DatePicker)this);
+
+ void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ public event EventHandler<DateChangedEventArgs> DateSelected;
+
+ static object CoerceDate(BindableObject bindable, object value)
+ {
+ var picker = (DatePicker)bindable;
+ DateTime dateValue = ((DateTime)value).Date;
+
+ if (dateValue > picker.MaximumDate)
+ dateValue = picker.MaximumDate;
+
+ if (dateValue < picker.MinimumDate)
+ dateValue = picker.MinimumDate;
+
+ return dateValue;
+ }
+
+ static object CoerceMaximumDate(BindableObject bindable, object value)
+ {
+ DateTime dateValue = ((DateTime)value).Date;
+ var picker = (DatePicker)bindable;
+ if (picker.Date > dateValue)
+ picker.Date = dateValue;
+
+ return dateValue;
+ }
+
+ static object CoerceMinimumDate(BindableObject bindable, object value)
+ {
+ DateTime dateValue = ((DateTime)value).Date;
+ var picker = (DatePicker)bindable;
+ if (picker.Date < dateValue)
+ picker.Date = dateValue;
+
+ return dateValue;
+ }
+
+ static void DatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var datePicker = (DatePicker)bindable;
+ EventHandler<DateChangedEventArgs> selected = datePicker.DateSelected;
+
+ if (selected != null)
+ selected(datePicker, new DateChangedEventArgs((DateTime)oldValue, (DateTime)newValue));
+ }
+
+ static bool ValidateMaximumDate(BindableObject bindable, object value)
+ {
+ return ((DateTime)value).Date >= ((DatePicker)bindable).MinimumDate.Date;
+ }
+
+ static bool ValidateMinimumDate(BindableObject bindable, object value)
+ {
+ return ((DateTime)value).Date <= ((DatePicker)bindable).MaximumDate.Date;
+ }
+
+ public IPlatformElementConfiguration<T, DatePicker> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+
+ void ITextElement.OnTextColorPropertyChanged(Color oldValue, Color newValue)
+ {
+ }
+
+ void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
+ {
+ InvalidateMeasure();
+ }
+
+ }
+}
\ No newline at end of file
public new static readonly BindableProperty TextColorProperty = InputView.TextColorProperty;
+ public new static readonly BindableProperty CharacterSpacingProperty = InputView.CharacterSpacingProperty;
+
public new static readonly BindableProperty PlaceholderProperty = InputView.PlaceholderProperty;
public new static readonly BindableProperty PlaceholderColorProperty = InputView.PlaceholderColorProperty;
+ public static readonly BindableProperty IsTextPredictionEnabledProperty = BindableProperty.Create(nameof(IsTextPredictionEnabled), typeof(bool), typeof(Editor), true, BindingMode.Default);
+
public static readonly BindableProperty AutoSizeProperty = BindableProperty.Create(nameof(AutoSize), typeof(EditorAutoSizeOption), typeof(Editor), defaultValue: EditorAutoSizeOption.Disabled, propertyChanged: (bindable, oldValue, newValue)
=> ((Editor)bindable)?.InvalidateMeasure());
set { SetValue(FontAttributesProperty, value); }
}
- public bool IsTextPredictionEnabled { get; set; }
+ public bool IsTextPredictionEnabled
+ {
+ get { return (bool)GetValue(IsTextPredictionEnabledProperty); }
+ set { SetValue(IsTextPredictionEnabledProperty, value); }
+ }
public string FontFamily
{
public new static readonly BindableProperty TextColorProperty = InputView.TextColorProperty;
+ public new static readonly BindableProperty CharacterSpacingProperty = InputView.CharacterSpacingProperty;
+
public static readonly BindableProperty HorizontalTextAlignmentProperty = TextAlignmentElement.HorizontalTextAlignmentProperty;
public static readonly BindableProperty VerticalTextAlignmentProperty = TextAlignmentElement.VerticalTextAlignmentProperty;
[RenderWith(typeof(_FrameRenderer))]
public class Frame : ContentView, IElementConfiguration<Frame>, IPaddingElement, IBorderElement
{
+ [Obsolete("OutlineColorProperty is obsolete as of version 3.0.0. Please use BorderColorProperty instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty OutlineColorProperty = BorderElement.BorderColorProperty;
+
public static readonly BindableProperty BorderColorProperty = BorderElement.BorderColorProperty;
public static readonly BindableProperty HasShadowProperty = BindableProperty.Create("HasShadow", typeof(bool), typeof(Frame), true);
set { SetValue(HasShadowProperty, value); }
}
+ [Obsolete("OutlineColor is obsolete as of version 3.0.0. Please use BorderColor instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Color OutlineColor
+ {
+ get { return (Color)GetValue(OutlineColorProperty); }
+ set { SetValue(OutlineColorProperty, value); }
+ }
+
public Color BorderColor
{
get { return (Color)GetValue(BorderElement.BorderColorProperty); }
void IBorderElement.OnBorderColorPropertyChanged(Color oldValue, Color newValue)
{
+#pragma warning disable 0618 // retain until OutlineColor removed
+ OnPropertyChanged(nameof(OutlineColor));
+#pragma warning restore
}
bool IBorderElement.IsCornerRadiusSet() => IsSet(CornerRadiusProperty);
--- /dev/null
+using System;
+
+namespace Xamarin.Forms
+{
+ public interface IMasterDetailPageController
+ {
+ bool CanChangeIsPresented { get; set; }
+
+ Rectangle DetailBounds { get; set; }
+
+ Rectangle MasterBounds { get; set; }
+
+ bool ShouldShowSplitMode { get; }
+
+ void UpdateMasterBehavior();
+
+ event EventHandler<BackButtonPressedEventArgs> BackButtonPressed;
+ }
+}
\ No newline at end of file
--- /dev/null
+namespace Xamarin.Forms
+{
+ public interface ISearchBarController
+ {
+ void OnSearchButtonPressed();
+ }
+}
\ No newline at end of file
public static readonly BindableProperty IsLoadingProperty = IsLoadingPropertyKey.BindableProperty;
+ internal static readonly BindablePropertyKey IsPressedPropertyKey = BindableProperty.CreateReadOnly(nameof(IsPressed), typeof(bool), typeof(ImageButton), default(bool));
+
+ public static readonly BindableProperty IsPressedProperty = IsPressedPropertyKey.BindableProperty;
+
public static readonly BindableProperty PaddingProperty = PaddingElement.PaddingProperty;
public event EventHandler Clicked;
public bool IsLoading => (bool)GetValue(IsLoadingProperty);
- public bool IsPressed => false;
+ public bool IsPressed => (bool)GetValue(IsPressedProperty);
public bool IsOpaque
{
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetIsLoading(bool isLoading) => SetValue(IsLoadingPropertyKey, isLoading);
- public void SetIsPressed(bool isPressed) { }
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetIsPressed(bool isPressed) =>
+ SetValue(IsPressedPropertyKey, isPressed);
[EditorBrowsable(EditorBrowsableState.Never)]
public void SendClicked() =>
void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
{
+ InvalidateMeasure();
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public class ToolbarTracker
{
+ int _masterDetails;
Page _target;
public IEnumerable<Page> AdditionalTargets { get; set; }
+ public bool HaveMasterDetail
+ {
+ get { return _masterDetails > 0; }
+ }
+
+ public bool SeparateMasterDetail { get; set; }
+
public Page Target
{
get { return _target; }
var result = new List<ToolbarItem>();
result.AddRange(page.ToolbarItems);
- if (page is IPageContainer<Page>)
+ if (page is MasterDetailPage)
+ {
+ var masterDetail = (MasterDetailPage)page;
+ if (SeparateMasterDetail)
+ {
+ if (masterDetail.IsPresented)
+ {
+ if (masterDetail.Master != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Master));
+ }
+ else
+ {
+ if (masterDetail.Detail != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Detail));
+ }
+ }
+ else
+ {
+ if (masterDetail.Master != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Master));
+ if (masterDetail.Detail != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Detail));
+ }
+ }
+ else if (page is IPageContainer<Page>)
{
var container = (IPageContainer<Page>)page;
if (container.CurrentPage != null)
void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
- if (propertyChangedEventArgs.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
+ if (propertyChangedEventArgs.PropertyName == NavigationPage.CurrentPageProperty.PropertyName || propertyChangedEventArgs.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName ||
+ propertyChangedEventArgs.PropertyName == "Detail" || propertyChangedEventArgs.PropertyName == "Master")
{
EmitCollectionChanged();
}
void RegisterChildPage(Page page)
{
+ if (page is MasterDetailPage)
+ _masterDetails++;
+
((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged += OnCollectionChanged;
page.PropertyChanged += OnPropertyChanged;
}
if (page == null)
return;
+ if (page is MasterDetailPage)
+ _masterDetails++;
+
((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged += OnCollectionChanged;
page.Descendants().OfType<Page>().ForEach(RegisterChildPage);
void UnregisterChildPage(Page page)
{
+ if (page is MasterDetailPage)
+ _masterDetails--;
+
((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged -= OnCollectionChanged;
page.PropertyChanged -= OnPropertyChanged;
}
if (page == null)
return;
+ if (page is MasterDetailPage)
+ _masterDetails--;
+
((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged -= OnCollectionChanged;
page.Descendants().OfType<Page>().ForEach(UnregisterChildPage);
{
public static readonly BindableProperty HorizontalTextAlignmentProperty = TextAlignmentElement.HorizontalTextAlignmentProperty;
+ [Obsolete("XAlignProperty is obsolete as of version 2.0.0. Please use HorizontalTextAlignmentProperty instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty XAlignProperty = HorizontalTextAlignmentProperty;
+
public static readonly BindableProperty VerticalTextAlignmentProperty = BindableProperty.Create("VerticalTextAlignment", typeof(TextAlignment), typeof(Label), TextAlignment.Start,
propertyChanged: OnVerticalTextAlignmentPropertyChanged);
+ [Obsolete("YAlignProperty is obsolete as of version 2.0.0. Please use VerticalTextAlignmentProperty instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty YAlignProperty = VerticalTextAlignmentProperty;
+
public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;
public static readonly BindableProperty CharacterSpacingProperty = TextElement.CharacterSpacingProperty;
public static readonly BindableProperty LineHeightProperty = LineHeightElement.LineHeightProperty;
+ public static readonly BindableProperty MaxLinesProperty = BindableProperty.Create(nameof(MaxLines), typeof(int), typeof(Label), -1, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ if (bindable != null)
+ {
+ ((Label)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+ }
+ });
+
public static readonly BindableProperty PaddingProperty = PaddingElement.PaddingProperty;
public static readonly BindableProperty TextTypeProperty = BindableProperty.Create(nameof(TextType), typeof(TextType), typeof(Label), TextType.Text,
set { SetValue(VerticalTextAlignmentProperty, value); }
}
+ [Obsolete("XAlign is obsolete as of version 2.0.0. Please use HorizontalTextAlignment instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TextAlignment XAlign
+ {
+ get { return (TextAlignment)GetValue(XAlignProperty); }
+ set { SetValue(XAlignProperty, value); }
+ }
+
+ [Obsolete("YAlign is obsolete as of version 2.0.0. Please use VerticalTextAlignment instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TextAlignment YAlign
+ {
+ get { return (TextAlignment)GetValue(YAlignProperty); }
+ set { SetValue(YAlignProperty, value); }
+ }
+
public FontAttributes FontAttributes
{
get { return (FontAttributes)GetValue(FontAttributesProperty); }
set { SetValue(LineHeightProperty, value); }
}
+ public int MaxLines
+ {
+ get => (int)GetValue(MaxLinesProperty);
+ set => SetValue(MaxLinesProperty, value);
+ }
+
public Thickness Padding
{
get { return (Thickness)GetValue(PaddingProperty); }
void ITextAlignmentElement.OnHorizontalTextAlignmentPropertyChanged(TextAlignment oldValue, TextAlignment newValue)
{
+#pragma warning disable 0618 // retain until XAlign removed
+ OnPropertyChanged(nameof(XAlign));
+#pragma warning restore
}
static void OnTextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
static void OnVerticalTextAlignmentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
+ var label = (Label)bindable;
+#pragma warning disable 0618 // retain until YAlign removed
+ label.OnPropertyChanged(nameof(YAlign));
+#pragma warning restore 0618
}
public IPlatformElementConfiguration<T, Label> On<T>() where T : IConfigPlatform
void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
{
+ InvalidateMeasure();
}
+
public override IList<GestureElement> GetChildElements(Point point)
{
if (FormattedText?.Spans == null || FormattedText?.Spans.Count == 0)
public abstract class Layout : View, ILayout, ILayoutController, IPaddingElement
{
+ public static readonly BindableProperty IsClippedToBoundsProperty = BindableProperty.Create("IsClippedToBounds", typeof(bool), typeof(Layout), false);
+
public static readonly BindableProperty CascadeInputTransparentProperty = BindableProperty.Create(
nameof(CascadeInputTransparent), typeof(bool), typeof(Layout), true);
InternalChildren.CollectionChanged += InternalChildrenOnCollectionChanged;
}
+ public bool IsClippedToBounds
+ {
+ get { return (bool)GetValue(IsClippedToBoundsProperty); }
+ set { SetValue(IsClippedToBoundsProperty, value); }
+ }
+
public Thickness Padding
{
get { return (Thickness)GetValue(PaddingElement.PaddingProperty); }
[RenderWith(typeof(_ListViewRenderer))]
public class ListView : ItemsView<Cell>, IListViewController, IElementConfiguration<ListView>
{
+ public static readonly BindableProperty IsPullToRefreshEnabledProperty = BindableProperty.Create("IsPullToRefreshEnabled", typeof(bool), typeof(ListView), false);
+
+ public static readonly BindableProperty IsRefreshingProperty = BindableProperty.Create("IsRefreshing", typeof(bool), typeof(ListView), false, BindingMode.TwoWay);
+
public static readonly BindableProperty RefreshCommandProperty = BindableProperty.Create("RefreshCommand", typeof(ICommand), typeof(ListView), null, propertyChanged: OnRefreshCommandChanged);
public static readonly BindableProperty HeaderProperty = BindableProperty.Create("Header", typeof(object), typeof(ListView), null, propertyChanged: OnHeaderChanged);
public static readonly BindableProperty SeparatorVisibilityProperty = BindableProperty.Create("SeparatorVisibility", typeof(SeparatorVisibility), typeof(ListView), SeparatorVisibility.Default);
+ public static readonly BindableProperty SeparatorColorProperty = BindableProperty.Create("SeparatorColor", typeof(Color), typeof(ListView), Color.Default);
+
+ public static readonly BindableProperty RefreshControlColorProperty = BindableProperty.Create(nameof(RefreshControlColor), typeof(Color), typeof(ListView), Color.Default);
+
+ public static readonly BindableProperty HorizontalScrollBarVisibilityProperty = BindableProperty.Create(nameof(HorizontalScrollBarVisibility), typeof(ScrollBarVisibility), typeof(ListView), ScrollBarVisibility.Default);
+
+ public static readonly BindableProperty VerticalScrollBarVisibilityProperty = BindableProperty.Create(nameof(VerticalScrollBarVisibility), typeof(ScrollBarVisibility), typeof(ListView), ScrollBarVisibility.Default);
+
static readonly ToStringValueConverter _toStringValueConverter = new ToStringValueConverter();
readonly Lazy<PlatformConfigurationRegistry<ListView>> _platformConfigurationRegistry;
set { SetValue(IsGroupingEnabledProperty, value); }
}
+ public bool IsPullToRefreshEnabled
+ {
+ get { return (bool)GetValue(IsPullToRefreshEnabledProperty); }
+ set { SetValue(IsPullToRefreshEnabledProperty, value); }
+ }
+
+ public bool IsRefreshing
+ {
+ get { return (bool)GetValue(IsRefreshingProperty); }
+ set { SetValue(IsRefreshingProperty, value); }
+ }
+
public ICommand RefreshCommand
{
get { return (ICommand)GetValue(RefreshCommandProperty); }
set { SetValue(SelectionModeProperty, value); }
}
+ public Color SeparatorColor
+ {
+ get { return (Color)GetValue(SeparatorColorProperty); }
+ set { SetValue(SeparatorColorProperty, value); }
+ }
+
+ public Color RefreshControlColor
+ {
+ get { return (Color)GetValue(RefreshControlColorProperty); }
+ set { SetValue(RefreshControlColorProperty, value); }
+ }
+
public SeparatorVisibility SeparatorVisibility
{
get { return (SeparatorVisibility)GetValue(SeparatorVisibilityProperty); }
set { SetValue(SeparatorVisibilityProperty, value); }
}
+ public ScrollBarVisibility HorizontalScrollBarVisibility
+ {
+ get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); }
+ set { SetValue(HorizontalScrollBarVisibilityProperty, value); }
+ }
+ public ScrollBarVisibility VerticalScrollBarVisibility
+ {
+ get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); }
+ set { SetValue(VerticalScrollBarVisibilityProperty, value); }
+ }
+
public ListViewCachingStrategy CachingStrategy { get; private set; }
[EditorBrowsable(EditorBrowsableState.Never)]
if (!RefreshAllowed)
return;
+ SetValueCore(IsRefreshingProperty, true);
OnRefreshing(EventArgs.Empty);
ICommand command = RefreshCommand;
public void EndRefresh()
{
+ SetValueCore(IsRefreshingProperty, false);
}
public event EventHandler<ItemVisibilityEventArgs> ItemAppearing;
--- /dev/null
+namespace Xamarin.Forms
+{
+ public enum MasterBehavior
+ {
+ Default = 0,
+ SplitOnLandscape = 1,
+ Split = 2,
+ Popover = 3,
+ SplitOnPortrait = 4
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_MasterDetailPageRenderer))]
+ public class MasterDetailPage : Page, IMasterDetailPageController, IElementConfiguration<MasterDetailPage>
+ {
+ public static readonly BindableProperty IsGestureEnabledProperty = BindableProperty.Create("IsGestureEnabled", typeof(bool), typeof(MasterDetailPage), true);
+
+ public static readonly BindableProperty IsPresentedProperty = BindableProperty.Create("IsPresented", typeof(bool), typeof(MasterDetailPage),default(bool),
+ propertyChanged: OnIsPresentedPropertyChanged, propertyChanging: OnIsPresentedPropertyChanging, defaultValueCreator : GetDefaultValue);
+
+ public static readonly BindableProperty MasterBehaviorProperty = BindableProperty.Create("MasterBehavior", typeof(MasterBehavior), typeof(MasterDetailPage), default(MasterBehavior),
+ propertyChanged: OnMasterBehaviorPropertyChanged);
+
+ Page _detail;
+
+ Rectangle _detailBounds;
+
+ Page _master;
+
+ Rectangle _masterBounds;
+
+ public Page Detail
+ {
+ get { return _detail; }
+ set
+ {
+ if (_detail != null && value == null)
+ throw new ArgumentNullException("value", "Detail cannot be set to null once a value is set.");
+
+ if (_detail == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Detail must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_detail != null)
+ InternalChildren.Remove(_detail);
+ _detail = value;
+ InternalChildren.Add(_detail);
+ OnPropertyChanged();
+ }
+ }
+
+ public bool IsGestureEnabled
+ {
+ get { return (bool)GetValue(IsGestureEnabledProperty); }
+ set { SetValue(IsGestureEnabledProperty, value); }
+ }
+
+ public bool IsPresented
+ {
+ get { return (bool)GetValue(IsPresentedProperty); }
+ set { SetValue(IsPresentedProperty, value); }
+ }
+
+ public Page Master
+ {
+ get { return _master; }
+ set
+ {
+ if (_master != null && value == null)
+ throw new ArgumentNullException("value", "Master cannot be set to null once a value is set");
+
+ if (string.IsNullOrEmpty(value.Title))
+ throw new InvalidOperationException("Title property must be set on Master page");
+
+ if (_master == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Master must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_master != null)
+ InternalChildren.Remove(_master);
+ _master = value;
+ InternalChildren.Add(_master);
+ OnPropertyChanged();
+ }
+ }
+
+ public MasterBehavior MasterBehavior
+ {
+ get { return (MasterBehavior)GetValue(MasterBehaviorProperty); }
+ set { SetValue(MasterBehaviorProperty, value); }
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool CanChangeIsPresented { get; set; } = true;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Rectangle DetailBounds
+ {
+ get { return _detailBounds; }
+ set
+ {
+ _detailBounds = value;
+ if (_detail == null)
+ throw new InvalidOperationException("Detail must be set before using a MasterDetailPage");
+ _detail.Layout(value);
+ }
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Rectangle MasterBounds
+ {
+ get { return _masterBounds; }
+ set
+ {
+ _masterBounds = value;
+ if (_master == null)
+ throw new InvalidOperationException("Master must be set before using a MasterDetailPage");
+ _master.Layout(value);
+ }
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool ShouldShowSplitMode
+ {
+ get
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return false;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior == MasterBehavior.Split || isSplitOnLandscape || isSplitOnPortrait;
+ }
+ }
+
+ public event EventHandler IsPresentedChanged;
+
+ public virtual bool ShouldShowToolbarButton()
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return true;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior != MasterBehavior.Split && !isSplitOnLandscape && !isSplitOnPortrait;
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (Master == null || Detail == null)
+ throw new InvalidOperationException("Master and Detail must be set before using a MasterDetailPage");
+ _master.Layout(_masterBounds);
+ _detail.Layout(_detailBounds);
+ }
+
+ protected override void OnAppearing()
+ {
+ CanChangeIsPresented = true;
+ UpdateMasterBehavior(this);
+ base.OnAppearing();
+ }
+
+ protected override bool OnBackButtonPressed()
+ {
+ if (IsPresented)
+ {
+ if (Master.SendBackButtonPressed())
+ return true;
+ }
+
+ EventHandler<BackButtonPressedEventArgs> handler = BackButtonPressed;
+ if (handler != null)
+ {
+ var args = new BackButtonPressedEventArgs();
+ handler(this, args);
+ if (args.Handled)
+ return true;
+ }
+
+ if (Detail.SendBackButtonPressed())
+ {
+ return true;
+ }
+
+ return base.OnBackButtonPressed();
+ }
+
+ protected override void OnParentSet()
+ {
+ if (RealParent != null && (Master == null || Detail == null))
+ throw new InvalidOperationException("Master and Detail must be set before adding MasterDetailPage to a container");
+ base.OnParentSet();
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public event EventHandler<BackButtonPressedEventArgs> BackButtonPressed;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void UpdateMasterBehavior()
+ {
+ UpdateMasterBehavior(this);
+ }
+
+ internal static void UpdateMasterBehavior(MasterDetailPage page)
+ {
+ if (page.ShouldShowSplitMode)
+ {
+ page.SetValueCore(IsPresentedProperty, true);
+ if (page.MasterBehavior != MasterBehavior.Default)
+ page.CanChangeIsPresented = false;
+ }
+ }
+
+ static void OnIsPresentedPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ => ((MasterDetailPage)sender).IsPresentedChanged?.Invoke(sender, EventArgs.Empty);
+
+ static void OnIsPresentedPropertyChanging(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ if (!page.CanChangeIsPresented)
+ throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", page.MasterBehavior));
+ }
+
+ static void OnMasterBehaviorPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ UpdateMasterBehavior(page);
+ }
+
+ static object GetDefaultValue(BindableObject bindable)
+ {
+ return Device.RuntimePlatform == Device.macOS;
+ }
+
+ public MasterDetailPage()
+ {
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<MasterDetailPage>>(() => new PlatformConfigurationRegistry<MasterDetailPage>(this));
+ }
+
+ readonly Lazy<PlatformConfigurationRegistry<MasterDetailPage>> _platformConfigurationRegistry;
+
+ public new IPlatformElementConfiguration<T, MasterDetailPage> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+ }
+}
\ No newline at end of file
[RenderWith(typeof(_NavigationPageRenderer))]
public class NavigationPage : Page, IPageContainer<Page>, IBarElement, INavigationPageController, IElementConfiguration<NavigationPage>
{
+ public static readonly BindableProperty BackButtonTitleProperty = BindableProperty.CreateAttached("BackButtonTitle", typeof(string), typeof(Page), null);
+
public static readonly BindableProperty HasNavigationBarProperty = BindableProperty.CreateAttached("HasNavigationBar", typeof(bool), typeof(Page), true);
+ public static readonly BindableProperty HasBackButtonProperty = BindableProperty.CreateAttached("HasBackButton", typeof(bool), typeof(NavigationPage), true);
+
+ [Obsolete("TintProperty is obsolete as of version 1.2.0. Please use BarBackgroundColorProperty and BarTextColorProperty to change NavigationPage bar color properties.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty TintProperty = BindableProperty.Create("Tint", typeof(Color), typeof(NavigationPage), Color.Default);
+
public static readonly BindableProperty BarBackgroundColorProperty = BarElement.BarBackgroundColorProperty;
public static readonly BindableProperty BarTextColorProperty = BarElement.BarTextColorProperty;
+ public static readonly BindableProperty TitleIconImageSourceProperty = BindableProperty.CreateAttached("TitleIconImageSource", typeof(ImageSource), typeof(NavigationPage), default(ImageSource));
+
+ [Obsolete("TitleIconProperty is obsolete as of 4.0.0. Please use TitleIconImageSourceProperty instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty TitleIconProperty = TitleIconImageSourceProperty;
+
public static readonly BindableProperty TitleViewProperty = BindableProperty.CreateAttached("TitleView", typeof(View), typeof(NavigationPage), null, propertyChanging: TitleViewPropertyChanging);
static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null);
set => SetValue(BarElement.BarTextColorProperty, value);
}
+ [Obsolete("Tint is obsolete as of version 1.2.0. Please use BarBackgroundColor and BarTextColor to change NavigationPage bar color properties.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Color Tint
+ {
+ get { return (Color)GetValue(TintProperty); }
+ set { SetValue(TintProperty, value); }
+ }
+
internal Task CurrentNavigationTask { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
}
}
+ public static string GetBackButtonTitle(BindableObject page)
+ {
+ return (string)page.GetValue(BackButtonTitleProperty);
+ }
+
+ public static bool GetHasBackButton(Page page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+ return (bool)page.GetValue(HasBackButtonProperty);
+ }
+
public static bool GetHasNavigationBar(BindableObject page)
{
return (bool)page.GetValue(HasNavigationBarProperty);
}
+ [Obsolete("GetTitleIcon is obsolete as of 4.0.0. Please use GetTitleIconImageSource instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static FileImageSource GetTitleIcon(BindableObject bindable)
+ {
+ return bindable.GetValue(TitleIconImageSourceProperty) as FileImageSource;
+ }
+
+ public static ImageSource GetTitleIconImageSource(BindableObject bindable)
+ {
+ return (ImageSource)bindable.GetValue(TitleIconImageSourceProperty);
+ }
+
public static View GetTitleView(BindableObject bindable)
{
return (View)bindable.GetValue(TitleViewProperty);
public event EventHandler<NavigationEventArgs> Pushed;
+ public static void SetBackButtonTitle(BindableObject page, string value)
+ {
+ page.SetValue(BackButtonTitleProperty, value);
+ }
+
+ public static void SetHasBackButton(Page page, bool value)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+ page.SetValue(HasBackButtonProperty, value);
+ }
+
public static void SetHasNavigationBar(BindableObject page, bool value)
{
page.SetValue(HasNavigationBarProperty, value);
}
+ [Obsolete("SetTitleIcon is obsolete as of 4.0.0. Please use SetTitleIconImageSource instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void SetTitleIcon(BindableObject bindable, FileImageSource value)
+ {
+ bindable.SetValue(TitleIconImageSourceProperty, value);
+ }
+
+ public static void SetTitleIconImageSource(BindableObject bindable, ImageSource value)
+ {
+ bindable.SetValue(TitleIconImageSourceProperty, value);
+ }
+
public static void SetTitleView(BindableObject bindable, View value)
{
bindable.SetValue(TitleViewProperty, value);
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_PickerRenderer))]
+ public class Picker : View, IFontElement, ITextElement, IElementConfiguration<Picker>
+ {
+ public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;
+
+ public static readonly BindableProperty CharacterSpacingProperty = TextElement.CharacterSpacingProperty;
+
+ public static readonly BindableProperty TitleProperty =
+ BindableProperty.Create(nameof(Title), typeof(string), typeof(Picker), default(string));
+
+ public static readonly BindableProperty TitleColorProperty =
+ BindableProperty.Create(nameof(TitleColor), typeof(Color), typeof(Picker), default(Color));
+
+ public static readonly BindableProperty SelectedIndexProperty =
+ BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(Picker), -1, BindingMode.TwoWay,
+ propertyChanged: OnSelectedIndexChanged, coerceValue: CoerceSelectedIndex);
+
+ public static readonly BindableProperty ItemsSourceProperty =
+ BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(Picker), default(IList),
+ propertyChanged: OnItemsSourceChanged);
+
+ public static readonly BindableProperty SelectedItemProperty =
+ BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(Picker), null, BindingMode.TwoWay,
+ propertyChanged: OnSelectedItemChanged);
+
+ public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty;
+
+ public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;
+
+ public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;
+
+ readonly Lazy<PlatformConfigurationRegistry<Picker>> _platformConfigurationRegistry;
+
+ public Picker()
+ {
+ ((INotifyCollectionChanged)Items).CollectionChanged += OnItemsCollectionChanged;
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Picker>>(() => new PlatformConfigurationRegistry<Picker>(this));
+ }
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontSizeChanged(double oldValue, double newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontChanged(Font oldValue, Font newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ double IFontElement.FontSizeDefaultValueCreator() =>
+ Device.GetNamedSize(NamedSize.Default, (Picker)this);
+
+ void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ public IList<string> Items { get; } = new LockableObservableListWrapper();
+
+ public IList ItemsSource
+ {
+ get { return (IList)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public int SelectedIndex
+ {
+ get { return (int)GetValue(SelectedIndexProperty); }
+ set { SetValue(SelectedIndexProperty, value); }
+ }
+
+ public object SelectedItem
+ {
+ get { return GetValue(SelectedItemProperty); }
+ set { SetValue(SelectedItemProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextElement.TextColorProperty); }
+ set { SetValue(TextElement.TextColorProperty, value); }
+ }
+
+ public double CharacterSpacing
+ {
+ get { return (double)GetValue(TextElement.CharacterSpacingProperty); }
+ set { SetValue(TextElement.CharacterSpacingProperty, value); }
+ }
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ public Color TitleColor
+ {
+ get { return (Color)GetValue(TitleColorProperty); }
+ set { SetValue(TitleColorProperty, value); }
+ }
+
+ BindingBase _itemDisplayBinding;
+ public BindingBase ItemDisplayBinding {
+ get { return _itemDisplayBinding; }
+ set {
+ if (_itemDisplayBinding == value)
+ return;
+
+ OnPropertyChanging();
+ var oldValue = value;
+ _itemDisplayBinding = value;
+ OnItemDisplayBindingChanged(oldValue, _itemDisplayBinding);
+ OnPropertyChanged();
+ }
+ }
+
+ public event EventHandler SelectedIndexChanged;
+
+ static readonly BindableProperty s_displayProperty =
+ BindableProperty.Create("Display", typeof(string), typeof(Picker), default(string));
+
+ string GetDisplayMember(object item)
+ {
+ if (ItemDisplayBinding == null)
+ return item.ToString();
+
+ ItemDisplayBinding.Apply(item, this, s_displayProperty);
+ ItemDisplayBinding.Unapply();
+ return (string)GetValue(s_displayProperty);
+ }
+
+ static object CoerceSelectedIndex(BindableObject bindable, object value)
+ {
+ var picker = (Picker)bindable;
+ return picker.Items == null ? -1 : ((int)value).Clamp(-1, picker.Items.Count - 1);
+ }
+
+ void OnItemDisplayBindingChanged(BindingBase oldValue, BindingBase newValue)
+ {
+ ResetItems();
+ }
+
+ void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ var oldIndex = SelectedIndex;
+ var newIndex = SelectedIndex = SelectedIndex.Clamp(-1, Items.Count - 1);
+ // If the index has not changed, still need to change the selected item
+ if (newIndex == oldIndex)
+ UpdateSelectedItem(newIndex);
+ }
+
+ static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ ((Picker)bindable).OnItemsSourceChanged((IList)oldValue, (IList)newValue);
+ }
+
+ void OnItemsSourceChanged(IList oldValue, IList newValue)
+ {
+ var oldObservable = oldValue as INotifyCollectionChanged;
+ if (oldObservable != null)
+ oldObservable.CollectionChanged -= CollectionChanged;
+
+ var newObservable = newValue as INotifyCollectionChanged;
+ if (newObservable != null) {
+ newObservable.CollectionChanged += CollectionChanged;
+ }
+
+ if (newValue != null) {
+ ((LockableObservableListWrapper)Items).IsLocked = true;
+ ResetItems();
+ } else {
+ ((LockableObservableListWrapper)Items).InternalClear();
+ ((LockableObservableListWrapper)Items).IsLocked = false;
+ }
+ }
+
+ void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action) {
+ case NotifyCollectionChangedAction.Add:
+ AddItems(e);
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ RemoveItems(e);
+ break;
+ default: //Move, Replace, Reset
+ ResetItems();
+ break;
+ }
+ }
+ void AddItems(NotifyCollectionChangedEventArgs e)
+ {
+ int index = e.NewStartingIndex < 0 ? Items.Count : e.NewStartingIndex;
+ foreach (object newItem in e.NewItems)
+ ((LockableObservableListWrapper)Items).InternalInsert(index++, GetDisplayMember(newItem));
+ }
+
+ void RemoveItems(NotifyCollectionChangedEventArgs e)
+ {
+ int index = e.OldStartingIndex < Items.Count ? e.OldStartingIndex : Items.Count;
+ foreach (object _ in e.OldItems)
+ ((LockableObservableListWrapper)Items).InternalRemoveAt(index--);
+ }
+
+ void ResetItems()
+ {
+ if (ItemsSource == null)
+ return;
+ ((LockableObservableListWrapper)Items).InternalClear();
+ foreach (object item in ItemsSource)
+ ((LockableObservableListWrapper)Items).InternalAdd(GetDisplayMember(item));
+ UpdateSelectedItem(SelectedIndex);
+ }
+
+ static void OnSelectedIndexChanged(object bindable, object oldValue, object newValue)
+ {
+ var picker = (Picker)bindable;
+ picker.UpdateSelectedItem(picker.SelectedIndex);
+ picker.SelectedIndexChanged?.Invoke(bindable, EventArgs.Empty);
+ }
+
+ static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var picker = (Picker)bindable;
+ picker.UpdateSelectedIndex(newValue);
+ }
+
+ void UpdateSelectedIndex(object selectedItem)
+ {
+ if (ItemsSource != null) {
+ SelectedIndex = ItemsSource.IndexOf(selectedItem);
+ return;
+ }
+ SelectedIndex = Items.IndexOf(selectedItem);
+ }
+
+ void UpdateSelectedItem(int index)
+ {
+ if (index == -1) {
+ SelectedItem = null;
+ return;
+ }
+
+ if (ItemsSource != null) {
+ SelectedItem = ItemsSource [index];
+ return;
+ }
+
+ SelectedItem = Items [index];
+ }
+
+ public IPlatformElementConfiguration<T, Picker> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+
+ void ITextElement.OnTextColorPropertyChanged(Color oldValue, Color newValue)
+ {
+ }
+
+ void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
+ {
+ InvalidateMeasure();
+ }
+
+ }
+}
\ No newline at end of file
--- /dev/null
+namespace Xamarin.Forms.PlatformConfiguration.TizenSpecific
+{
+ using FormsElement = Forms.NavigationPage;
+
+ public static class NavigationPage
+ {
+ #region HasBreadCrumbsBar
+ public static readonly BindableProperty HasBreadCrumbsBarProperty
+ = BindableProperty.CreateAttached("HasBreadCrumbsBar", typeof(bool), typeof(FormsElement), false);
+
+ public static bool GetHasBreadCrumbsBar(BindableObject element)
+ {
+ return (bool)element.GetValue(HasBreadCrumbsBarProperty);
+ }
+
+ public static void SetHasBreadCrumbsBar(BindableObject element, bool value)
+ {
+ element.SetValue(HasBreadCrumbsBarProperty, value);
+ }
+
+ public static bool HasBreadCrumbsBar(this IPlatformElementConfiguration<Tizen, FormsElement> config)
+ {
+ return GetHasBreadCrumbsBar(config.Element);
+ }
+
+ public static IPlatformElementConfiguration<Tizen, FormsElement> SetHasBreadCrumbsBar(this IPlatformElementConfiguration<Tizen, FormsElement> config, bool value)
+ {
+ SetHasBreadCrumbsBar(config.Element, value);
+ return config;
+ }
+ #endregion
+ }
+}
public const string Default = "default";
public const string Pending = "pending";
}
+
+ public static class TabbedPageStyle
+ {
+ public const string Default = "default";
+ public const string Tabbar = "tabbar";
+ public const string TabbarWithTitle = "tabbar_with_title";
+ }
}
[assembly: StyleProperty("background-image", typeof(Page), nameof(Page.BackgroundImageSourceProperty))]
[assembly: StyleProperty("border-color", typeof(IBorderElement), nameof(BorderElement.BorderColorProperty))]
[assembly: StyleProperty("border-radius", typeof(ICornerElement), nameof(CornerElement.CornerRadiusProperty))]
+[assembly: StyleProperty("border-radius", typeof(Button), nameof(Button.CornerRadiusProperty))]
[assembly: StyleProperty("border-radius", typeof(Frame), nameof(Frame.CornerRadiusProperty))]
[assembly: StyleProperty("border-radius", typeof(ImageButton), nameof(BorderElement.CornerRadiusProperty))]
[assembly: StyleProperty("border-width", typeof(IBorderElement), nameof(BorderElement.BorderWidthProperty))]
[assembly: StyleProperty("margin-top", typeof(View), nameof(View.MarginTopProperty))]
[assembly: StyleProperty("margin-right", typeof(View), nameof(View.MarginRightProperty))]
[assembly: StyleProperty("margin-bottom", typeof(View), nameof(View.MarginBottomProperty))]
+[assembly: StyleProperty("max-lines", typeof(Label), nameof(Label.MaxLinesProperty))]
[assembly: StyleProperty("min-height", typeof(VisualElement), nameof(VisualElement.MinimumHeightRequestProperty))]
[assembly: StyleProperty("min-width", typeof(VisualElement), nameof(VisualElement.MinimumWidthRequestProperty))]
[assembly: StyleProperty("opacity", typeof(VisualElement), nameof(VisualElement.OpacityProperty))]
[assembly: StyleProperty("-xf-orientation", typeof(StackLayout), nameof(StackLayout.OrientationProperty))]
[assembly: StyleProperty("-xf-visual", typeof(VisualElement), nameof(VisualElement.VisualProperty))]
[assembly: StyleProperty("-xf-vertical-text-alignment", typeof(Label), nameof(TextAlignmentElement.VerticalTextAlignmentProperty))]
+[assembly: StyleProperty("-xf-thumb-color", typeof(Switch), nameof(Switch.ThumbColorProperty))]
//shell
[assembly: StyleProperty("-xf-flyout-background", typeof(Shell), nameof(Shell.FlyoutBackgroundColorProperty))]
public RefreshView()
{
+ IsClippedToBounds = true;
VerticalOptions = LayoutOptions.FillAndExpand;
HorizontalOptions = LayoutOptions.FillAndExpand;
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.Windows.Input;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_SearchBarRenderer))]
+ public class SearchBar : InputView, IFontElement, ITextAlignmentElement, ISearchBarController, IElementConfiguration<SearchBar>
+ {
+ public static readonly BindableProperty SearchCommandProperty = BindableProperty.Create("SearchCommand", typeof(ICommand), typeof(SearchBar), null, propertyChanged: OnCommandChanged);
+
+ public static readonly BindableProperty SearchCommandParameterProperty = BindableProperty.Create("SearchCommandParameter", typeof(object), typeof(SearchBar), null);
+
+ public new static readonly BindableProperty TextProperty = InputView.TextProperty;
+
+ public static readonly BindableProperty CancelButtonColorProperty = BindableProperty.Create("CancelButtonColor", typeof(Color), typeof(SearchBar), default(Color));
+
+ public new static readonly BindableProperty PlaceholderProperty = InputView.PlaceholderProperty;
+
+ public new static readonly BindableProperty PlaceholderColorProperty = InputView.PlaceholderColorProperty;
+
+ public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty;
+
+ public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;
+
+ public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;
+
+ public static readonly BindableProperty HorizontalTextAlignmentProperty = TextAlignmentElement.HorizontalTextAlignmentProperty;
+
+ public static readonly BindableProperty VerticalTextAlignmentProperty = TextAlignmentElement.VerticalTextAlignmentProperty;
+
+ public new static readonly BindableProperty TextColorProperty = InputView.TextColorProperty;
+
+ public new static readonly BindableProperty CharacterSpacingProperty = InputView.CharacterSpacingProperty;
+
+ readonly Lazy<PlatformConfigurationRegistry<SearchBar>> _platformConfigurationRegistry;
+
+ public Color CancelButtonColor
+ {
+ get { return (Color)GetValue(CancelButtonColorProperty); }
+ set { SetValue(CancelButtonColorProperty, value); }
+ }
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(TextAlignmentElement.HorizontalTextAlignmentProperty); }
+ set { SetValue(TextAlignmentElement.HorizontalTextAlignmentProperty, value); }
+ }
+
+ public TextAlignment VerticalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(TextAlignmentElement.VerticalTextAlignmentProperty); }
+ set { SetValue(TextAlignmentElement.VerticalTextAlignmentProperty, value); }
+ }
+
+ public ICommand SearchCommand
+ {
+ get { return (ICommand)GetValue(SearchCommandProperty); }
+ set { SetValue(SearchCommandProperty, value); }
+ }
+
+ public object SearchCommandParameter
+ {
+ get { return GetValue(SearchCommandParameterProperty); }
+ set { SetValue(SearchCommandParameterProperty, value); }
+ }
+
+ bool IsEnabledCore
+ {
+ set { SetValueCore(IsEnabledProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ void IFontElement.OnFontFamilyChanged(string oldValue, string newValue)
+ {
+ }
+
+ void IFontElement.OnFontSizeChanged(double oldValue, double newValue)
+ {
+ }
+
+ double IFontElement.FontSizeDefaultValueCreator() =>
+ Device.GetNamedSize(NamedSize.Default, (SearchBar)this);
+
+ void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue)
+ {
+ }
+
+ void IFontElement.OnFontChanged(Font oldValue, Font newValue)
+ {
+ }
+
+ public event EventHandler SearchButtonPressed;
+
+ public SearchBar()
+ {
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<SearchBar>>(() => new PlatformConfigurationRegistry<SearchBar>(this));
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void OnSearchButtonPressed()
+ {
+ ICommand cmd = SearchCommand;
+
+ if (cmd != null && !cmd.CanExecute(SearchCommandParameter))
+ return;
+
+ cmd?.Execute(SearchCommandParameter);
+ SearchButtonPressed?.Invoke(this, EventArgs.Empty);
+ }
+
+ void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ ICommand cmd = SearchCommand;
+ if (cmd != null)
+ IsEnabledCore = cmd.CanExecute(SearchCommandParameter);
+ }
+
+ static void OnCommandChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var self = (SearchBar)bindable;
+ var newCommand = (ICommand)newValue;
+ var oldCommand = (ICommand)oldValue;
+
+ if (oldCommand != null)
+ {
+ oldCommand.CanExecuteChanged -= self.CommandCanExecuteChanged;
+ }
+
+ if (newCommand != null)
+ {
+ newCommand.CanExecuteChanged += self.CommandCanExecuteChanged;
+ self.CommandCanExecuteChanged(self, EventArgs.Empty);
+ }
+ else
+ {
+ self.IsEnabledCore = true;
+ }
+ }
+
+ public IPlatformElementConfiguration<T, SearchBar> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+
+ void ITextAlignmentElement.OnHorizontalTextAlignmentPropertyChanged(TextAlignment oldValue, TextAlignment newValue)
+ {
+ }
+ }
+}
\ No newline at end of file
public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Slider), Color.Default);
+ public static readonly BindableProperty ThumbImageSourceProperty = BindableProperty.Create(nameof(ThumbImageSource), typeof(ImageSource), typeof(Slider), default(ImageSource));
+
+ [Obsolete("ThumbImageProperty is obsolete as of 4.0.0. Please use ThumbImageSourceProperty instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static readonly BindableProperty ThumbImageProperty = ThumbImageSourceProperty;
+
public static readonly BindableProperty DragStartedCommandProperty = BindableProperty.Create(nameof(DragStartedCommand), typeof(ICommand), typeof(Slider), default(ICommand));
public static readonly BindableProperty DragCompletedCommandProperty = BindableProperty.Create(nameof(DragCompletedCommand), typeof(ICommand), typeof(Slider), default(ICommand));
set { SetValue(ThumbColorProperty, value); }
}
+ public ImageSource ThumbImageSource
+ {
+ get { return (ImageSource)GetValue(ThumbImageSourceProperty); }
+ set { SetValue(ThumbImageSourceProperty, value); }
+ }
+
+ [Obsolete("ThumbImage is obsolete as of 4.0.0. Please use ThumbImageSource instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public FileImageSource ThumbImage
+ {
+ get { return GetValue(ThumbImageProperty) as FileImageSource; }
+ set { SetValue(ThumbImageProperty, value); }
+ }
+
public ICommand DragStartedCommand
{
get { return (ICommand)GetValue(DragStartedCommandProperty); }
public static readonly BindableProperty OnColorProperty = BindableProperty.Create(nameof(OnColor), typeof(Color), typeof(Switch), Color.Default);
+ public static readonly BindableProperty ThumbColorProperty = BindableProperty.Create(nameof(ThumbColor), typeof(Color), typeof(Switch), Color.Default);
+
public Color OnColor
{
get { return (Color)GetValue(OnColorProperty); }
set { SetValue(OnColorProperty, value); }
}
+ public Color ThumbColor
+ {
+ get { return (Color)GetValue(ThumbColorProperty); }
+ set { SetValue(ThumbColorProperty, value); }
+ }
+
readonly Lazy<PlatformConfigurationRegistry<Switch>> _platformConfigurationRegistry;
public Switch()
--- /dev/null
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_TabbedPageRenderer))]
+ public class TabbedPage : MultiPage<Page>, IBarElement, IElementConfiguration<TabbedPage>
+ {
+ public static readonly BindableProperty BarBackgroundColorProperty = BarElement.BarBackgroundColorProperty;
+
+ public static readonly BindableProperty BarTextColorProperty = BarElement.BarTextColorProperty;
+
+ public static readonly BindableProperty UnselectedTabColorProperty = BindableProperty.Create(nameof(UnselectedTabColor), typeof(Color), typeof(TabbedPage), default(Color));
+
+ public static readonly BindableProperty SelectedTabColorProperty = BindableProperty.Create(nameof(SelectedTabColor), typeof(Color), typeof(TabbedPage), default(Color));
+
+ readonly Lazy<PlatformConfigurationRegistry<TabbedPage>> _platformConfigurationRegistry;
+
+ public Color BarBackgroundColor {
+ get => (Color)GetValue(BarElement.BarBackgroundColorProperty);
+ set => SetValue(BarElement.BarBackgroundColorProperty, value);
+ }
+
+ public Color BarTextColor {
+ get => (Color)GetValue(BarElement.BarTextColorProperty);
+ set => SetValue(BarElement.BarTextColorProperty, value);
+ }
+
+ public Color UnselectedTabColor
+ {
+ get => (Color)GetValue(UnselectedTabColorProperty);
+ set => SetValue(UnselectedTabColorProperty, value);
+ }
+ public Color SelectedTabColor
+ {
+ get => (Color)GetValue(SelectedTabColorProperty);
+ set => SetValue(SelectedTabColorProperty, value);
+ }
+
+ protected override Page CreateDefault(object item)
+ {
+ var page = new Page();
+ if (item != null)
+ page.Title = item.ToString();
+
+ return page;
+ }
+
+ public TabbedPage()
+ {
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<TabbedPage>>(() => new PlatformConfigurationRegistry<TabbedPage>(this));
+ }
+
+ public new IPlatformElementConfiguration<T, TabbedPage> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_TimePickerRenderer))]
+ public class TimePicker : View, IFontElement, ITextElement, IElementConfiguration<TimePicker>
+ {
+ public static readonly BindableProperty FormatProperty = BindableProperty.Create(nameof(Format), typeof(string), typeof(TimePicker), "t");
+
+ public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;
+
+ public static readonly BindableProperty CharacterSpacingProperty = TextElement.CharacterSpacingProperty;
+
+ public static readonly BindableProperty TimeProperty = BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(TimePicker), new TimeSpan(0), BindingMode.TwoWay, (bindable, value) =>
+ {
+ var time = (TimeSpan)value;
+ return time.TotalHours < 24 && time.TotalMilliseconds >= 0;
+ });
+
+ public static readonly BindableProperty FontFamilyProperty = FontElement.FontFamilyProperty;
+
+ public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;
+
+ public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;
+
+ readonly Lazy<PlatformConfigurationRegistry<TimePicker>> _platformConfigurationRegistry;
+
+ public TimePicker()
+ {
+ _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<TimePicker>>(() => new PlatformConfigurationRegistry<TimePicker>(this));
+ }
+
+ public string Format
+ {
+ get { return (string)GetValue(FormatProperty); }
+ set { SetValue(FormatProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextElement.TextColorProperty); }
+ set { SetValue(TextElement.TextColorProperty, value); }
+ }
+
+ public double CharacterSpacing
+ {
+ get { return (double)GetValue(TextElement.CharacterSpacingProperty); }
+ set { SetValue(TextElement.CharacterSpacingProperty, value); }
+ }
+
+ public TimeSpan Time
+ {
+ get { return (TimeSpan)GetValue(TimeProperty); }
+ set { SetValue(TimeProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontSizeChanged(double oldValue, double newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ void IFontElement.OnFontChanged(Font oldValue, Font newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ double IFontElement.FontSizeDefaultValueCreator() =>
+ Device.GetNamedSize(NamedSize.Default, (TimePicker)this);
+
+ void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) =>
+ InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
+
+ public IPlatformElementConfiguration<T, TimePicker> On<T>() where T : IConfigPlatform
+ {
+ return _platformConfigurationRegistry.Value.On<T>();
+ }
+
+ void ITextElement.OnTextColorPropertyChanged(Color oldValue, Color newValue)
+ {
+ }
+
+ void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newValue)
+ {
+ InvalidateMeasure();
+ }
+
+ }
+}
\ No newline at end of file
{
const int _defaultHeight = 55;
- public ImageCellRenderer() : this("1icon_2text")
+ public ImageCellRenderer() : this(Device.Idiom == TargetIdiom.Watch ? "1icon_2text" : (Device.Idiom == TargetIdiom.Phone ? "double_label" : "default"))
{
ImagePart = "elm.swallow.icon";
}
toggle.SetBinding(Switch.OnColorProperty, new Binding(SwitchCell.OnColorProperty.PropertyName));
var nativeView = Platform.GetOrCreateRenderer(toggle).NativeView;
- nativeView.MinimumWidth += 8;
- nativeView.PropagateEvents = false;
-
+ if (Device.Idiom == TargetIdiom.Watch)
+ {
+ nativeView.MinimumWidth += 8;
+ }
+
+ //It is a temporary way to prevent that the check of the Cell gets focus until the UX about views in the Cell for TV is defined.
+ if (Device.Idiom == TargetIdiom.TV)
+ {
+ ((Check)nativeView).AllowFocus(false);
+ }
+ else
+ {
+ nativeView.PropagateEvents = false;
+ }
return nativeView;
}
return null;
public class TextCellRenderer : CellRenderer
{
bool _groupMode = false;
-
- public TextCellRenderer() : this("double_label") { }
+ // TextCell.Detail property is not supported on TV profile due to UX limitation.
+ public TextCellRenderer() : this(Device.Idiom == TargetIdiom.Phone || Device.Idiom == TargetIdiom.Watch ? "double_label" : "default") { }
protected TextCellRenderer(string style) : base(style)
{
else
{
Class = null;
- Style = "default";
+ Style = Device.Idiom == TargetIdiom.Phone ? "double_label" : "default";
DetailPart = "elm.text.sub";
}
}
public static class Forms
{
+ static Lazy<string> s_profile = new Lazy<string>(() =>
+ {
+ //TODO : Fix me if elm_config_profile_get() unavailable
+ return Elementary.GetProfile();
+ });
+
static Lazy<int> s_dpi = new Lazy<int>(() =>
{
int dpi = 0;
+ if (s_profile.Value == "tv")
+ {
+ // Use fixed DPI value (72) if TV profile
+ return 72;
+ }
TSystemInfo.TryGetValue<int>("http://tizen.org/feature/screen.dpi", out dpi);
return dpi;
});
readonly double scalingFactor;
+ readonly string profile;
+
public override Size PixelScreenSize
{
get
}
}
+ public string Profile
+ {
+ get
+ {
+ return this.profile;
+ }
+ }
+
public TizenDeviceInfo() : this(getScreenWidth(), getScreenHeight())
{
}
}
scaledScreenSize = new Size(width / scalingFactor, height / scalingFactor);
+ profile = s_profile.Value;
}
public TizenDeviceInfo RefreshByDIP()
if (!Forms.IsInitialized)
{
- Device.SetIdiom(TargetIdiom.Watch);
- Color.SetAccent(Color.FromRgba(10, 27, 41, 255)); // Theme A (Default) 1st HSB: 207 75 16
+ string profile = ((TizenDeviceInfo)Device.Info).Profile;
+ if (profile == "mobile")
+ {
+ Device.SetIdiom(TargetIdiom.Phone);
+ }
+ else if (profile == "tv")
+ {
+ Device.SetIdiom(TargetIdiom.TV);
+ }
+ else if (profile == "desktop")
+ {
+ Device.SetIdiom(TargetIdiom.Desktop);
+ }
+ else if (profile == "wearable")
+ {
+ Device.SetIdiom(TargetIdiom.Watch);
+ }
+ else
+ {
+ Device.SetIdiom(TargetIdiom.Unsupported);
+ }
+ Color.SetAccent(GetAccentColor(profile));
ExpressionSearch.Default = new TizenExpressionSearch();
IsInitialized = true;
}
}
+ static Color GetAccentColor(string profile)
+ {
+ // On Windows Phone, this is the complementary color chosen by the user.
+ // Good Windows Phone applications use this as part of their styling to provide a native look and feel.
+ // On iOS and Android this instance is set to a contrasting color that is visible on the default
+ // background but is not the same as the default text color.
+
+ switch (profile)
+ {
+ case "mobile":
+ // [Tizen_3.0]Basic_Interaction_GUI_[REF].xlsx Theme 001 (Default) 1st HSB: 188 70 80
+ return Color.FromRgba(61, 185, 204, 255);
+ case "tv":
+ return Color.FromRgba(15, 15, 15, 230);
+ case "wearable":
+ // Theme A (Default) 1st HSB: 207 75 16
+ return Color.FromRgba(10, 27, 41, 255);
+ default:
+ return Color.Black;
+ }
+ }
+
/// <summary>
/// Converts the dp into pixel considering current DPI value.
/// </summary>
return eflPt / s_elmScale.Value;
}
+ /// <summary>
+ /// Get the EFL's profile
+ /// </summary>
+ /// <returns></returns>
+ public static string GetProfile()
+ {
+ return s_profile.Value;
+ }
+
// for internal use only
[EditorBrowsable(EditorBrowsableState.Never)]
public static EvasObject Preload()
typeof(BoxView),
typeof(Button),
typeof(ImageButton),
+ typeof(CheckBox),
typeof(Slider),
typeof(Stepper),
typeof(Switch),
+ typeof(DatePicker),
+ typeof(TimePicker),
typeof(Entry),
typeof(Editor),
typeof(ActivityIndicator),
typeof(CarouselView),
typeof(CollectionView),
typeof(ListView),
+ typeof(Picker),
typeof(TableView),
typeof(TextCell),
typeof(ImageCell),
--- /dev/null
+using System;
+
+namespace Xamarin.Forms.Platform.Tizen.Native
+{
+ /// <summary>
+ /// Event arguments for <see cref="DatePicker.DateChanged"/> event.
+ /// </summary>
+ public class DateChangedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// The date that the user entered.
+ /// </summary>
+ public DateTime NewDate { get; }
+
+ /// <summary>
+ /// Creates a new <see cref="DateChangedEventArgs"/> object that represents a change from <paramref name="oldDate"/> to <paramref name="newDate"/>.
+ /// </summary>
+ /// <param name="oldDate">Old date of <see cref="DatePicker"/>.</param>
+ /// <param name="newDate">Current date of <see cref="DatePicker"/>.</param>
+ public DateChangedEventArgs(DateTime newDate)
+ {
+ NewDate = newDate;
+ }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+
+namespace Xamarin.Forms.Platform.Tizen.Native
+{
+ public enum DateTimePickerMode
+ {
+ Date,
+ Time
+ }
+
+ public class DateTimePicker : DateTimeSelector
+ {
+ const string TimeFormat = "%d/%b/%Y %I:%M %p";
+ const string TimeLayoutStyle = "time_layout";
+
+ const string DateFormat = "%d/%b/%Y";
+ const string DateLayoutStyle = "date_layout";
+
+ DateTimePickerMode _mode = DateTimePickerMode.Date;
+
+ public DateTimePicker(EvasObject parent) : base(parent)
+ {
+ UpdateMode();
+ }
+
+ protected DateTimePicker() : base()
+ {
+ }
+
+ public DateTimePickerMode Mode
+ {
+ get { return _mode; }
+ set
+ {
+ if (_mode != value)
+ {
+ _mode = value;
+ UpdateMode();
+ }
+ }
+ }
+
+ public TimeSpan Time
+ {
+ get
+ {
+ return DateTime.TimeOfDay;
+ }
+ set
+ {
+ DateTime -= DateTime.TimeOfDay;
+ DateTime += value;
+ }
+ }
+
+ protected virtual void UpdateMode()
+ {
+ if (Mode == DateTimePickerMode.Date)
+ {
+ Style = DateLayoutStyle;
+ Format = DateFormat;
+ }
+ else
+ {
+ Style = TimeLayoutStyle;
+ Format = TimeFormat;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using EButton = ElmSharp.Button;
+
+namespace Xamarin.Forms.Platform.Tizen.Native
+{
+ public class DateTimePickerDialog : Dialog, IDateTimeDialog
+ {
+ EvasObject _parent;
+ /// <summary>
+ /// Creates a dialog window.
+ /// </summary>
+ public DateTimePickerDialog(EvasObject parent) : base(parent)
+ {
+ _parent = parent;
+ Initialize();
+ }
+
+ public DateTimePicker Picker { get; protected set; }
+
+ /// <summary>
+ /// Occurs when the date of this dialog has changed.
+ /// </summary>
+ public event EventHandler<DateChangedEventArgs> DateTimeChanged;
+
+ protected virtual DateTimePicker CreatePicker(EvasObject parent)
+ {
+ return new DateTimePicker(parent);
+ }
+
+ void Initialize()
+ {
+ Picker = CreatePicker(_parent);
+ Picker.Show();
+ Content = Picker;
+
+ //TODO need to add internationalization support
+ PositiveButton = new EButton(_parent) { Text = "Set" };
+ PositiveButton.Clicked += (s, e) =>
+ {
+ Confirm();
+ };
+
+ //TODO need to add internationalization support
+ NegativeButton = new EButton(_parent) { Text = "Cancel" };
+ NegativeButton.Clicked += (s, e) =>
+ {
+ Hide();
+ };
+ BackButtonPressed += (object s, EventArgs e) =>
+ {
+ Hide();
+ };
+
+ // TODO This is Tizen TV Limitation.
+ // UX is defined and the focus move processing is complete, it should be removed(After Tizen 5.0)
+ if (Device.Idiom == TargetIdiom.TV)
+ {
+ KeyDown += (s, e) =>
+ {
+ if (e.KeyName == "Return")
+ {
+ if (Picker != null && Picker.IsFocused)
+ {
+ Confirm();
+ e.Flags |= EvasEventFlag.OnHold;
+ }
+ }
+ };
+ }
+ }
+
+ void Confirm()
+ {
+ DateTimeChanged?.Invoke(this, new DateChangedEventArgs(Picker.DateTime));
+ Hide();
+ }
+ }
+}
/// </summary>
public static Dialog CreateDialog(EvasObject parent, bool hasAcceptButton = false)
{
- return new Watch.WatchDialog(Forms.NativeParent, hasAcceptButton);
+ if (Device.Idiom == TargetIdiom.Watch)
+ {
+ return new Watch.WatchDialog(Forms.NativeParent, hasAcceptButton);
+ }
+ else
+ {
+ return new Dialog(Forms.NativeParent);
+ }
}
/// <summary>
protected virtual void ApplyTitleColor(EColor color)
{
- SetPartColor("text_maintitle", color);
+ SetPartColor(Device.Idiom == TargetIdiom.TV ? "text_title" : "text_maintitle", color);
}
/// <summary>
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ElmSharp;
+
+namespace Xamarin.Forms.Platform.Tizen.Native
+{
+ public interface IDateTimeDialog
+ {
+ string Title { get; set; }
+ DateTimePicker Picker { get; }
+ event EventHandler<DateChangedEventArgs> DateTimeChanged;
+ void Show();
+ void Hide();
+ void Unrealize();
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Platform.Tizen.Native
+{
+ /// <summary>
+ /// The native widget which provides Xamarin.MasterDetailPage features.
+ /// </summary>
+ public class MasterDetailPage : Box
+ {
+ /// <summary>
+ /// The default master behavior (a.k.a mode).
+ /// </summary>
+ static readonly MasterBehavior s_defaultMasterBehavior = (Device.Idiom == TargetIdiom.Phone || Device.Idiom == TargetIdiom.Watch) ? MasterBehavior.Popover : MasterBehavior.SplitOnLandscape;
+
+ /// <summary>
+ /// The MasterPage native container.
+ /// </summary>
+ readonly Canvas _masterCanvas;
+
+ /// <summary>
+ /// The DetailPage native container.
+ /// </summary>
+ readonly Canvas _detailCanvas;
+
+ /// <summary>
+ /// The container for <c>_masterCanvas</c> and <c>_detailCanvas</c> used in split mode.
+ /// </summary>
+ readonly Panes _splitPane;
+
+ /// <summary>
+ /// The container for <c>_masterCanvas</c> used in popover mode.
+ /// </summary>
+ readonly Panel _drawer;
+
+ /// <summary>
+ /// The <see cref="MasterBehavior"/> property value.
+ /// </summary>
+ MasterBehavior _masterBehavior = s_defaultMasterBehavior;
+
+ /// <summary>
+ /// The actual MasterDetailPage mode - either split or popover. It depends on <c>_masterBehavior</c> and screen orientation.
+ /// </summary>
+ MasterBehavior _internalMasterBehavior = MasterBehavior.Popover;
+
+ /// <summary>
+ /// The <see cref="Master"/> property value.
+ /// </summary>
+ EvasObject _master;
+
+ /// <summary>
+ /// The <see cref="Detail"/> property value.
+ /// </summary>
+ EvasObject _detail;
+
+ /// <summary>
+ /// The main widget - either <see cref="_splitPlane"/> or <see cref="_detailPage"/>, depending on the mode.
+ /// </summary>
+ EvasObject _mainWidget;
+
+ /// <summary>
+ /// The <see cref="IsGestureEnabled"/> property value.
+ /// </summary>
+ bool _isGestureEnabled = true;
+
+ /// <summary>
+ /// The portion of the screen that the MasterPage takes in Split mode.
+ /// </summary>
+ double _splitRatio = 0.35;
+
+ /// <summary>
+ /// The portion of the screen that the MasterPage takes in Popover mode.
+ /// </summary>
+ double _popoverRatio = 0.8;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Xamarin.Forms.Platform.Tizen.Native.MasterDetailPage"/> class.
+ /// </summary>
+ /// <param name="parent">Parent evas object.</param>
+ public MasterDetailPage(EvasObject parent) : base(parent)
+ {
+ LayoutUpdated += (s, e) =>
+ {
+ UpdateChildCanvasGeometry();
+ };
+
+ // create the controls which will hold the master and detail pages
+ _masterCanvas = new Canvas(this);
+ _masterCanvas.SetAlignment(-1.0, -1.0); // fill
+ _masterCanvas.SetWeight(1.0, 1.0); // expand
+ _masterCanvas.LayoutUpdated += (sender, e) =>
+ {
+ UpdatePageGeometry(_master);
+ };
+
+ _detailCanvas = new Canvas(this);
+ _detailCanvas.SetAlignment(-1.0, -1.0); // fill
+ _detailCanvas.SetWeight(1.0, 1.0); // expand
+ _detailCanvas.LayoutUpdated += (sender, e) =>
+ {
+ UpdatePageGeometry(_detail);
+ };
+
+ _splitPane = new Panes(this)
+ {
+ AlignmentX = -1,
+ AlignmentY = -1,
+ WeightX = 1,
+ WeightY = 1,
+ IsFixed = true,
+ IsHorizontal = false,
+ Proportion = _splitRatio,
+ };
+
+ _drawer = new Panel(Forms.NativeParent);
+ _drawer.SetScrollable(_isGestureEnabled);
+ _drawer.SetScrollableArea(1.0);
+ _drawer.Direction = PanelDirection.Left;
+ _drawer.Toggled += (object sender, EventArgs e) =>
+ {
+ UpdateFocusPolicy();
+ IsPresentedChanged?.Invoke(this, new IsPresentedChangedEventArgs(_drawer.IsOpen));
+ };
+
+ ConfigureLayout();
+
+ // in case of the screen rotation we may need to update the choice between split
+ // and popover behaviors and reconfigure the layout
+ Device.Info.PropertyChanged += (s, e) =>
+ {
+ if (e.PropertyName == nameof(Device.Info.CurrentOrientation))
+ {
+ UpdateMasterBehavior();
+ }
+ };
+ }
+
+ /// <summary>
+ /// Occurs when the MasterPage is shown or hidden.
+ /// </summary>
+ public event EventHandler<IsPresentedChangedEventArgs> IsPresentedChanged;
+
+ /// <summary>
+ /// Occurs when the IsPresentChangeable was changed.
+ /// </summary>
+ public event EventHandler<UpdateIsPresentChangeableEventArgs> UpdateIsPresentChangeable;
+
+ /// <summary>
+ /// Gets or sets the MasterDetailPage behavior.
+ /// </summary>
+ /// <value>The behavior of the <c>MasterDetailPage</c> requested by the user.</value>
+ public MasterBehavior MasterBehavior
+ {
+ get
+ {
+ return _masterBehavior;
+ }
+
+ set
+ {
+ _masterBehavior = value;
+ UpdateMasterBehavior();
+ }
+ }
+
+ /// <summary>
+ /// Gets the MasterDEtailPage was splited
+ /// </summary>
+ public bool IsSplit => _internalMasterBehavior == MasterBehavior.Split;
+
+ /// <summary>
+ /// Gets or sets the content of the MasterPage.
+ /// </summary>
+ /// <value>The MasterPage.</value>
+ public EvasObject Master
+ {
+ get
+ {
+ return _master;
+ }
+
+ set
+ {
+ if (_master != value)
+ {
+ _master = value;
+ UpdatePageGeometry(_master);
+ _masterCanvas.Children.Clear();
+ _masterCanvas.Children.Add(_master);
+ if (!IsSplit)
+ UpdateFocusPolicy();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the content of the DetailPage.
+ /// </summary>
+ /// <value>The DetailPage.</value>
+ public EvasObject Detail
+ {
+ get
+ {
+ return _detail;
+ }
+
+ set
+ {
+ if (_detail != value)
+ {
+ _detail = value;
+ UpdatePageGeometry(_detail);
+ _detailCanvas.Children.Clear();
+ _detailCanvas.Children.Add(_detail);
+ if (!IsSplit)
+ UpdateFocusPolicy();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the MasterPage is shown.
+ /// </summary>
+ /// <value><c>true</c> if the MasterPage is presented.</value>
+ public bool IsPresented
+ {
+ get
+ {
+ return _drawer.IsOpen;
+ }
+
+ set
+ {
+ if (_drawer.IsOpen != value)
+ {
+ _drawer.IsOpen = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether a MasterDetailPage allows showing MasterPage with swipe gesture.
+ /// </summary>
+ /// <value><c>true</c> if the MasterPage can be revealed with a gesture.</value>
+ public bool IsGestureEnabled
+ {
+ get
+ {
+ return _isGestureEnabled;
+ }
+
+ set
+ {
+ if (_isGestureEnabled != value)
+ {
+ _isGestureEnabled = value;
+ // Fixme
+ // Elementary panel was not support to change scrollable property on runtime
+ // Please uncomment when EFL was updated
+ //_drawer.SetScrollable(_isGestureEnabled);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or Sets the portion of the screen that the MasterPage takes in split mode.
+ /// </summary>
+ /// <value>The portion.</value>
+ public double SplitRatio
+ {
+ get
+ {
+ return _splitRatio;
+ }
+ set
+ {
+ if (_splitRatio != value)
+ {
+ _splitRatio = value;
+ _splitPane.Proportion = _splitRatio;
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Gets or sets the portion of the screen that the MasterPage takes in Popover mode.
+ /// </summary>
+ /// <value>The portion.</value>
+ public double PopoverRatio
+ {
+ get
+ {
+ return _popoverRatio;
+ }
+ set
+ {
+ if (_popoverRatio != value)
+ {
+ _popoverRatio = value;
+ UpdateChildCanvasGeometry();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides destruction for native element and contained elements.
+ /// </summary>
+ protected override void OnUnrealize()
+ {
+ // Views that are not belong to view tree should be unrealized.
+ if (IsSplit)
+ {
+ _drawer.Unrealize();
+ }
+ else
+ {
+ _splitPane.Unrealize();
+ }
+ base.OnUnrealize();
+ }
+
+ /// <summary>
+ /// Updates the geometry of the selected page.
+ /// </summary>
+ /// <param name="page">Master or Detail page to be updated.</param>
+ void UpdatePageGeometry(EvasObject page)
+ {
+ if (page != null)
+ {
+ if (_master == page)
+ {
+ // update the geometry of the master page
+ page.Geometry = _masterCanvas.Geometry;
+ }
+ else if (_detail == page)
+ {
+ // update the geometry of the detail page
+ page.Geometry = _detailCanvas.Geometry;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Updates <see cref="_internalMasterBehavior"/> according to <see cref="MasterDetailBehavior"/> set by the user and current screen orientation.
+ /// </summary>
+ void UpdateMasterBehavior()
+ {
+ var behavior = (_masterBehavior == MasterBehavior.Default) ? s_defaultMasterBehavior : _masterBehavior;
+
+ // Screen orientation affects those 2 behaviors
+ if (behavior == MasterBehavior.SplitOnLandscape ||
+ behavior == MasterBehavior.SplitOnPortrait)
+ {
+ var orientation = Device.Info.CurrentOrientation;
+
+ if ((orientation.IsLandscape() && behavior == MasterBehavior.SplitOnLandscape) ||
+ (orientation.IsPortrait() && behavior == MasterBehavior.SplitOnPortrait))
+ {
+ behavior = MasterBehavior.Split;
+ }
+ else
+ {
+ behavior = MasterBehavior.Popover;
+ }
+ }
+
+ if (behavior != _internalMasterBehavior)
+ {
+ _internalMasterBehavior = behavior;
+ ConfigureLayout();
+ }
+ }
+
+ /// <summary>
+ /// Composes the structure of all the necessary widgets.
+ /// </summary>
+ void ConfigureLayout()
+ {
+ _drawer.SetContent(null, true);
+ _drawer.Hide();
+
+ _splitPane.SetPartContent("left", null, true);
+ _splitPane.SetPartContent("right", null, true);
+ _splitPane.Hide();
+
+ UnPackAll();
+
+ // the structure for split mode and for popover mode looks differently
+ if (IsSplit)
+ {
+ _splitPane.SetPartContent("left", _masterCanvas, true);
+ _splitPane.SetPartContent("right", _detailCanvas, true);
+ _splitPane.Show();
+ _mainWidget = _splitPane;
+ PackEnd(_splitPane);
+
+ IsPresented = true;
+ UpdateIsPresentChangeable?.Invoke(this, new UpdateIsPresentChangeableEventArgs(false));
+ UpdateFocusPolicy(true);
+ }
+ else
+ {
+ _drawer.SetContent(_masterCanvas, true);
+ _drawer.Show();
+ _mainWidget = _detailCanvas;
+ PackEnd(_detailCanvas);
+ PackEnd(_drawer);
+
+ _drawer.IsOpen = IsPresented;
+ UpdateIsPresentChangeable?.Invoke(this, new UpdateIsPresentChangeableEventArgs(true));
+ UpdateFocusPolicy();
+ }
+
+ _masterCanvas.Show();
+ _detailCanvas.Show();
+
+ // even though child was changed, Layout callback was not called, so i manually call layout function.
+ // Layout callback was filter out when geometry was not changed in Native.Box
+ UpdateChildCanvasGeometry();
+ }
+
+ void UpdateChildCanvasGeometry()
+ {
+ var bound = Geometry;
+ // main widget should fill the area of the MasterDetailPage
+ if (_mainWidget != null)
+ {
+ _mainWidget.Geometry = bound;
+ }
+
+ bound.Width = (int)((_popoverRatio * bound.Width));
+ _drawer.Geometry = bound;
+ // When a _drawer.IsOpen was false, Content of _drawer area is not allocated. So, need to manaully set the content area
+ if (!IsSplit)
+ _masterCanvas.Geometry = bound;
+ }
+
+ /// <summary>
+ /// Force update the focus management
+ /// </summary>
+ void UpdateFocusPolicy(bool forceAllowFocusAll=false)
+ {
+ var master = _master as Widget;
+ var detail = _detail as Widget;
+
+ if(forceAllowFocusAll)
+ {
+ if (master != null)
+ master.AllowTreeFocus = true;
+ if (detail != null)
+ detail.AllowTreeFocus = true;
+ return;
+ }
+
+ if (_drawer.IsOpen)
+ {
+ if (detail != null)
+ {
+ detail.AllowTreeFocus = false;
+ }
+ if (master != null)
+ {
+ master.AllowTreeFocus = true;
+ master.SetFocus(true);
+ }
+ }
+ else
+ {
+ if (master != null)
+ {
+ master.AllowTreeFocus = false;
+ }
+ if (detail != null)
+ {
+ detail.AllowTreeFocus = true;
+ detail.SetFocus(true);
+ }
+ }
+ }
+ }
+
+ public class IsPresentedChangedEventArgs : EventArgs
+ {
+ public IsPresentedChangedEventArgs (bool isPresent)
+ {
+ IsPresent = isPresent;
+ }
+
+ /// <summary>
+ /// Value of IsPresent
+ /// </summary>
+ public bool IsPresent { get; private set; }
+ }
+
+ public class UpdateIsPresentChangeableEventArgs : EventArgs
+ {
+ public UpdateIsPresentChangeableEventArgs(bool canChange)
+ {
+ CanChange = canChange;
+ }
+
+ /// <summary>
+ /// Value of changeable
+ /// </summary>
+ public bool CanChange { get; private set; }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using ElmSharp.Wearable;
+using ELayout = ElmSharp.Layout;
+using EButton = ElmSharp.Button;
+
+namespace Xamarin.Forms.Platform.Tizen.Native.Watch
+{
+ public class WatchDataTimePickerDialog : Popup, IDateTimeDialog
+ {
+ ELayout _surfaceLayout;
+ ELayout _datetimeLayout;
+ CircleSurface _surface;
+ EButton _doneButton;
+ Box _container;
+ string _title;
+
+ public WatchDataTimePickerDialog(EvasObject parent) : base(parent)
+ {
+ AlignmentX = -1;
+ AlignmentY = -1;
+ WeightX = 1.0;
+ WeightY = 1.0;
+ Style = "circle";
+
+ _container = new Box(parent) { AlignmentX = -1, AlignmentY = -1, WeightX = 1, WeightY = 1 };
+ _container.BackgroundColor = ElmSharp.Color.Blue;
+ _container.SetLayoutCallback(OnContainerLayout);
+
+ _datetimeLayout = new ELayout(parent);
+ _surfaceLayout = new ELayout(parent);
+
+ _container.PackEnd(_datetimeLayout);
+ _container.PackEnd(_surfaceLayout);
+
+ _datetimeLayout.SetTheme("layout", "circle", "datetime");
+ _surface = new CircleSurface(_surfaceLayout);
+
+ WatchPicker = new WatchDateTimePicker(parent, _surface);
+ WatchPicker.Show();
+ _datetimeLayout.SetContent(WatchPicker);
+
+ _doneButton = new Button(parent)
+ {
+ Text = "Set",
+ Style = "bottom",
+ };
+ _datetimeLayout.SetPartContent("elm.swallow.btn", _doneButton);
+ _doneButton.Clicked += OnDoneClicked;
+
+ ((IRotaryActionWidget)WatchPicker.CircleSelector).Activate();
+
+ _datetimeLayout.Show();
+ _surfaceLayout.Show();
+ _container.Show();
+
+ SetContent(_container);
+ BackButtonPressed += OnBackButtonPressed;
+ }
+
+ public string Title
+ {
+ get => _title;
+ set
+ {
+ _title = value;
+ _datetimeLayout.SetPartText("elm.text", _title);
+ }
+ }
+
+ public DateTimePicker Picker => WatchPicker;
+ protected WatchDateTimePicker WatchPicker { get; }
+
+ public event EventHandler<DateChangedEventArgs> DateTimeChanged;
+
+ void OnContainerLayout()
+ {
+ _surfaceLayout.Geometry = _container.Geometry;
+ _datetimeLayout.Geometry = _container.Geometry;
+ }
+
+ void OnDoneClicked(object sender, EventArgs e)
+ {
+ System.Console.WriteLine("Done clicked");
+ System.Console.WriteLine("Picker.DateTime - {0} ", Picker.DateTime);
+ DateTimeChanged?.Invoke(this, new DateChangedEventArgs(Picker.DateTime));
+ Hide();
+ }
+
+ void OnBackButtonPressed(object sender, EventArgs e)
+ {
+ Hide();
+ }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using ElmSharp.Wearable;
+
+namespace Xamarin.Forms.Platform.Tizen.Native.Watch
+{
+ public class WatchDateTimePicker : DateTimePicker
+ {
+ readonly CircleSurface _surface;
+ public WatchDateTimePicker(EvasObject parent, CircleSurface surface) : base()
+ {
+ _surface = surface;
+ Realize(parent);
+ UpdateMode();
+ }
+
+ public CircleDateTimeSelector CircleSelector { get; private set; }
+
+ protected override void UpdateMode()
+ {
+ if (Mode == DateTimePickerMode.Date)
+ {
+ Style = "datepicker/circle";
+ }
+ else
+ {
+ Style = "timepicker/circle";
+ }
+ }
+
+ protected override IntPtr CreateHandle(EvasObject parent)
+ {
+ CircleSelector = new CircleDateTimeSelector(parent, _surface);
+ if (CircleSelector.RealHandle != CircleSelector.Handle)
+ {
+ RealHandle = CircleSelector.RealHandle;
+ }
+ return CircleSelector.Handle;
+ }
+ }
+}
BackgroundColor = EColor.Transparent
};
- _pageBusyDialog.Style = "circle";
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ _pageBusyDialog.SetPartColor("bg_title", EColor.Transparent);
+ _pageBusyDialog.SetPartColor("bg_content", EColor.Transparent);
+ }
+ else if (Device.Idiom == TargetIdiom.Watch)
+ {
+ _pageBusyDialog.Style = "circle";
+ }
var activity = new EProgressBar(_pageBusyDialog)
{
[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer))]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MasterDetailPageRenderer))]
+[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer))]
[assembly: ExportRenderer(typeof(Shell), typeof(ShellRenderer))]
[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
+[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
+[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
+[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
+[assembly: ExportRenderer(typeof(CheckBox), typeof(CheckBoxRenderer))]
[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
+[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
protected virtual EButton CreateNativeControl()
{
- return NativeFactory.GetNativeControl(typeof(Native.Watch.WatchButton)) as Native.Watch.WatchButton;
+ if (Device.Idiom == TargetIdiom.Watch)
+ return NativeFactory.GetNativeControl(typeof(Native.Watch.WatchButton)) as Native.Watch.WatchButton;
+ else
+ return NativeFactory.GetNativeControl(typeof(Native.Button)) as Native.Button;
}
protected override Size MinimumSize()
--- /dev/null
+using System;
+using ElmSharp;
+using EColor = ElmSharp.Color;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class CheckBoxRenderer : ViewRenderer<CheckBox, Check>
+ {
+ readonly string[] _onColorParts;
+ readonly string[] _onColorEdjeParts;
+
+ public CheckBoxRenderer()
+ {
+ _onColorParts = Device.Idiom == TargetIdiom.Watch ? new string[] {"outer_bg_on", "outer_bg_on_pressed", "check_on", "check_on_pressed"} : new string[] {"bg_on", "stroke"};
+ _onColorEdjeParts = new string[_onColorParts.Length];
+ RegisterPropertyHandler(CheckBox.IsCheckedProperty, UpdateIsChecked);
+ RegisterPropertyHandler(CheckBox.ColorProperty, UpdateOnColor);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CheckBox> e)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new Check(Forms.NativeParent));
+ Control.StateChanged += OnStateChanged;
+ for (int i=0; i<_onColorParts.Length; i++)
+ {
+ _onColorEdjeParts[i] = Control.ClassName.ToLower().Replace("elm_", "") + "/" + _onColorParts[i];
+ }
+ }
+ base.OnElementChanged(e);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.StateChanged -= OnStateChanged;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ void OnStateChanged(object sender, EventArgs e)
+ {
+ Element.SetValueFromRenderer(CheckBox.IsCheckedProperty, Control.IsChecked);
+ }
+
+ void UpdateIsChecked()
+ {
+ Control.IsChecked = Element.IsChecked;
+ }
+
+ void UpdateOnColor(bool initialize)
+ {
+ if (initialize && Element.Color.IsDefault)
+ return;
+
+ if (Element.Color.IsDefault)
+ {
+ foreach(string s in _onColorEdjeParts)
+ {
+ Control.EdjeObject.DeleteColorClass(s);
+ }
+ }
+ else
+ {
+ EColor color = Element.Color.ToNative();
+ foreach (string s in _onColorParts)
+ {
+ Control.SetPartColor(s, color);
+ }
+ }
+ }
+ }
+}
{
return false;
}
+ if (parentPage is MasterDetailPage mdPage && mdPage.Master == parent && !mdPage.IsPresented)
+ {
+ return false;
+ }
return PageIsVisible(parentPage);
}
return ret;
}
}
-}
+}
\ No newline at end of file
--- /dev/null
+using System;
+using Xamarin.Forms.Platform.Tizen.Native;
+using WatchDataTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDataTimePickerDialog;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class DatePickerRenderer : ViewRenderer<DatePicker, EditfieldEntry>
+ {
+ //TODO need to add internationalization support
+ const string DialogTitle = "Choose Date";
+ Lazy<IDateTimeDialog> _lazyDialog;
+
+ public DatePickerRenderer()
+ {
+ RegisterPropertyHandler(DatePicker.DateProperty, UpdateDate);
+ RegisterPropertyHandler(DatePicker.FormatProperty, UpdateDate);
+ RegisterPropertyHandler(DatePicker.TextColorProperty, UpdateTextColor);
+ RegisterPropertyHandler(DatePicker.FontAttributesProperty, UpdateFontAttributes);
+ RegisterPropertyHandler(DatePicker.FontFamilyProperty, UpdateFontFamily);
+ RegisterPropertyHandler(DatePicker.FontSizeProperty, UpdateFontSize);
+ }
+
+ protected virtual IDateTimeDialog CreateDialog()
+ {
+ if (Device.Idiom == TargetIdiom.Watch)
+ {
+ return new WatchDataTimePickerDialog(Forms.NativeParent);
+ }
+ else
+ {
+ return new DateTimePickerDialog(Forms.NativeParent);
+ }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
+ {
+ if (Control == null)
+ {
+ var entry = new Native.EditfieldEntry(Forms.NativeParent)
+ {
+ IsSingleLine = true,
+ HorizontalTextAlignment = Native.TextAlignment.Center,
+ InputPanelShowByOnDemand = true,
+ };
+ entry.SetVerticalTextAlignment("elm.text", 0.5);
+ entry.TextBlockFocused += OnTextBlockFocused;
+ SetNativeControl(entry);
+
+ _lazyDialog = new Lazy<IDateTimeDialog>(() =>
+ {
+ var dialog = CreateDialog();
+ dialog.Title = DialogTitle;
+ dialog.DateTimeChanged += OnDateTimeChanged;
+ return dialog;
+ });
+ }
+ base.OnElementChanged(e);
+ }
+
+ protected override Size MinimumSize()
+ {
+ return Control.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.TextBlockFocused -= OnTextBlockFocused;
+ }
+ if (_lazyDialog.IsValueCreated)
+ {
+ _lazyDialog.Value.DateTimeChanged -= OnDateTimeChanged;
+ _lazyDialog.Value.Unrealize();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ void OnTextBlockFocused(object sender, EventArgs e)
+ {
+ // For EFL Entry, the event will occur even if it is currently disabled.
+ // If the problem is resolved, no conditional statement is required.
+ if (Element.IsEnabled)
+ {
+ var dialog = _lazyDialog.Value;
+ dialog.Picker.DateTime = Element.Date;
+ dialog.Picker.MaximumDateTime = Element.MaximumDate;
+ dialog.Picker.MinimumDateTime = Element.MinimumDate;
+ // You need to call Show() after ui thread occupation because of EFL problem.
+ // Otherwise, the content of the popup will not receive focus.
+ Device.BeginInvokeOnMainThread(() => dialog.Show());
+ }
+ }
+
+ void OnDateTimeChanged(object sender, Native.DateChangedEventArgs dcea)
+ {
+ Element.Date = dcea.NewDate;
+ Control.Text = dcea.NewDate.ToString(Element.Format);
+ }
+
+ void UpdateDate()
+ {
+ Control.Text = Element.Date.ToString(Element.Format);
+ }
+
+ void UpdateTextColor()
+ {
+ Control.TextColor = Element.TextColor.ToNative();
+ }
+
+ void UpdateFontSize()
+ {
+ Control.FontSize = Element.FontSize;
+ }
+
+ void UpdateFontFamily()
+ {
+ Control.FontFamily = Element.FontFamily;
+ }
+
+ void UpdateFontAttributes()
+ {
+ Control.FontAttributes = Element.FontAttributes;
+ }
+ }
+}
if (Control == null)
{
// Multiline EditField style is only available on Mobile and TV profile
- var entry = new Native.Entry(Forms.NativeParent)
+ var entry = Device.Idiom == TargetIdiom.Phone || Device.Idiom == TargetIdiom.TV ? new Native.EditfieldEntry(Forms.NativeParent, "multiline") : new Native.Entry(Forms.NativeParent)
{
IsSingleLine = false,
};
const int _shadow_shift = 2;
const int _shadow_thickness = _thickness + 2;
- static readonly EColor s_DefaultColor = EColor.Gray;
+ static readonly EColor s_DefaultColor = Device.Idiom == TargetIdiom.TV || Device.Idiom == TargetIdiom.Watch ? EColor.Gray : EColor.Black;
static readonly EColor s_ShadowColor = EColor.FromRgba(80, 80, 80, 50);
Polygon _shadow = null;
--- /dev/null
+using System;
+
+namespace Xamarin.Forms.Platform.Tizen.Renderers
+{
+ public class MasterDetailContainer : ElmSharp.Box, IDisposable
+ {
+ readonly MasterDetailPage _parent;
+ readonly bool _isMaster;
+
+ VisualElement _childView;
+ bool _disposed;
+ bool _hasAppearedToParent;
+
+ IPageController PageController => ChildView as IPageController;
+ IMasterDetailPageController MasterDetailPageController => _parent as IMasterDetailPageController;
+
+ public MasterDetailContainer(MasterDetailPage parentElement, bool isMaster) : base(Forms.NativeParent)
+ {
+ _parent = parentElement;
+ _isMaster = isMaster;
+
+ SetLayoutCallback(OnLayoutUpdated);
+ Show();
+ }
+
+ ~MasterDetailContainer()
+ {
+ Dispose(false);
+ }
+
+ public VisualElement ChildView
+ {
+ get { return _childView; }
+ set
+ {
+ if (_childView == value)
+ return;
+
+ if (_childView != null)
+ {
+ RemoveChildView();
+ }
+
+ _childView = value;
+
+ if (_childView == null)
+ return;
+
+ AddChildView(_childView);
+
+ if (_hasAppearedToParent)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ if (!_disposed && _hasAppearedToParent)
+ PageController?.SendAppearing();
+ });
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected void RemoveChildView()
+ {
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(_childView);
+ if (childRenderer != null)
+ {
+ UnPack(childRenderer.NativeView);
+ childRenderer.Dispose();
+ }
+ }
+
+ protected void AddChildView(VisualElement childView)
+ {
+ IVisualElementRenderer renderer = Platform.GetOrCreateRenderer(childView);
+ this.PackEnd(renderer.NativeView);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ return;
+
+ if (disposing)
+ {
+ if (_childView != null)
+ {
+ RemoveChildView();
+ }
+ SetLayoutCallback(null);
+ }
+ _disposed = true;
+ }
+
+ void OnLayoutUpdated()
+ {
+ if (_childView != null)
+ {
+ if (_isMaster)
+ MasterDetailPageController.MasterBounds = this.Geometry.ToDP();
+ else
+ MasterDetailPageController.DetailBounds = this.Geometry.ToDP();
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
+ renderer.NativeView.Geometry = this.Geometry;
+ }
+ }
+
+ public void SendAppearing()
+ {
+ if (_hasAppearedToParent)
+ return;
+
+ _hasAppearedToParent = true;
+
+ PageController?.SendAppearing();
+ }
+
+ public void SendDisappearing()
+ {
+ if (!_hasAppearedToParent)
+ return;
+
+ _hasAppearedToParent = false;
+
+ PageController?.SendDisappearing();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using Xamarin.Forms.Platform.Tizen.Renderers;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class MasterDetailPageRenderer : VisualElementRenderer<MasterDetailPage>
+ {
+ Native.MasterDetailPage _mdpage;
+ MasterDetailContainer _masterContainer = null;
+ MasterDetailContainer _detailContainer = null;
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public MasterDetailPageRenderer()
+ {
+ RegisterPropertyHandler(nameof(Element.Master), UpdateMasterPage);
+ RegisterPropertyHandler(nameof(Element.Detail), UpdateDetailPage);
+ RegisterPropertyHandler(MasterDetailPage.IsPresentedProperty,
+ UpdateIsPresented);
+ RegisterPropertyHandler(MasterDetailPage.MasterBehaviorProperty,
+ UpdateMasterBehavior);
+ RegisterPropertyHandler(MasterDetailPage.IsGestureEnabledProperty,
+ UpdateIsGestureEnabled);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<MasterDetailPage> e)
+ {
+ if (_mdpage == null)
+ {
+ _mdpage = new Native.MasterDetailPage(Forms.NativeParent)
+ {
+ IsPresented = e.NewElement.IsPresented,
+ Master = _masterContainer = new MasterDetailContainer(Element, true),
+ Detail = _detailContainer = new MasterDetailContainer(Element, false),
+ };
+
+ _mdpage.IsPresentedChanged += (sender, ev) =>
+ {
+ Element.IsPresented = ev.IsPresent;
+ };
+ _mdpage.UpdateIsPresentChangeable += (sender, ev) =>
+ {
+ (Element as IMasterDetailPageController).CanChangeIsPresented = ev.CanChange;
+ };
+ SetNativeView(_mdpage);
+ }
+
+ if (e.OldElement != null)
+ {
+ (e.OldElement as IMasterDetailPageController).BackButtonPressed -= OnBackButtonPressed;
+ e.OldElement.Appearing -= OnMasterDetailAppearing;
+ e.OldElement.Disappearing -= OnMasterDetailDisappearing;
+ }
+
+ if (e.NewElement != null)
+ {
+ (e.NewElement as IMasterDetailPageController).BackButtonPressed += OnBackButtonPressed;
+ e.NewElement.Appearing += OnMasterDetailAppearing;
+ e.NewElement.Disappearing += OnMasterDetailDisappearing;
+ }
+
+ UpdateMasterBehavior();
+ base.OnElementChanged(e);
+ }
+
+ void OnMasterDetailDisappearing(object sender, EventArgs e)
+ {
+ _masterContainer?.SendDisappearing();
+ _detailContainer?.SendDisappearing();
+ }
+
+ void OnMasterDetailAppearing(object sender, EventArgs e)
+ {
+ _masterContainer?.SendAppearing();
+ _detailContainer?.SendAppearing();
+ }
+
+ protected override void OnElementReady()
+ {
+ base.OnElementReady();
+ UpdateMasterPage(false);
+ UpdateDetailPage(false);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_masterContainer != null)
+ {
+ _masterContainer.Dispose();
+ _masterContainer = null;
+ }
+
+ if (_detailContainer != null)
+ {
+ _detailContainer.Dispose();
+ _detailContainer = null;
+ }
+
+ if (Element != null)
+ {
+ Element.Appearing -= OnMasterDetailAppearing;
+ Element.Disappearing -= OnMasterDetailDisappearing;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected void UpdateMasterPageRatio(double popoverRatio, double splitRatio)
+ {
+ _mdpage.PopoverRatio = popoverRatio;
+ _mdpage.SplitRatio = splitRatio;
+ }
+
+ void OnBackButtonPressed(object sender, BackButtonPressedEventArgs e)
+ {
+ if ((Element != null) && Element.IsPresented && !_mdpage.IsSplit)
+ {
+ Element.IsPresented = false;
+ e.Handled = true;
+ }
+ }
+
+ void UpdateMasterBehavior()
+ {
+ _mdpage.MasterBehavior = Element.MasterBehavior;
+ }
+
+ void UpdateMasterPage(bool isInit)
+ {
+ if (!isInit)
+ _masterContainer.ChildView = Element.Master;
+ }
+
+ void UpdateDetailPage(bool isInit)
+ {
+ if (!isInit)
+ _detailContainer.ChildView = Element.Detail;
+ }
+
+ void UpdateIsPresented()
+ {
+ // To update TabIndex order
+ CustomFocusManager.StartReorderTabIndex();
+
+ _mdpage.IsPresented = Element.IsPresented;
+ }
+
+ void UpdateIsGestureEnabled()
+ {
+ _mdpage.IsGestureEnabled = Element.IsGestureEnabled;
+ }
+ }
+}
using System.Threading.Tasks;
using System.Collections.Generic;
using Xamarin.Forms.Internals;
+using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
using ElmSharp;
+using EButton = ElmSharp.Button;
+using EToolbar = ElmSharp.Toolbar;
+using EToolbarItem = ElmSharp.ToolbarItem;
+using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.NavigationPage;
+using SpecificPage = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Page;
namespace Xamarin.Forms.Platform.Tizen
{
public class NavigationPageRenderer : VisualElementRenderer<NavigationPage>
{
+ enum ToolbarButtonPosition
+ {
+ Left,
+ Right
+ };
+
const string PartTitle = "default";
+ const string PartBackButton = "elm.swallow.prev_btn";
+ const string PartLeftToolbar = "title_left_btn";
+ const string PartRightToolbar = "title_right_btn";
+ const string PartNavigationBar = "navigationbar";
+ const string StyleBackButton = "naviframe/back_btn/default";
+ const string StyleNavigationBar = "navigationbar";
readonly List<Widget> _naviItemContentPartList = new List<Widget>();
Naviframe _naviFrame = null;
Page _previousPage = null;
TaskCompletionSource<bool> _currentTaskSource = null;
+ ToolbarTracker _toolbarTracker = null;
IDictionary<Page, NaviItem> _naviItemMap;
Page CurrentPage => Element.CurrentPage;
{
_naviFrame.AnimationFinished -= OnAnimationFinished;
}
+ if (_toolbarTracker != null)
+ {
+ _toolbarTracker.CollectionChanged -= OnToolbarCollectionChanged;
+ }
}
base.Dispose(disposing);
}
_naviItemMap = new Dictionary<Page, NaviItem>();
}
+ if (_toolbarTracker == null)
+ {
+ _toolbarTracker = new ToolbarTracker();
+ _toolbarTracker.CollectionChanged += OnToolbarCollectionChanged;
+ }
+
if (e.OldElement != null)
{
var navigation = e.OldElement as INavigationPageController;
navigation.RemovePageRequested += OnRemovePageRequested;
navigation.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
+ _toolbarTracker.Target = e.NewElement;
_previousPage = e.NewElement.CurrentPage;
}
base.OnElementChanged(e);
// Tizen does not support 'Tint', but only 'BarBackgroundColor'
else if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
UpdateBarBackgroundColor(CurrentNaviItem);
+ else if (e.PropertyName == Specific.HasBreadCrumbsBarProperty.PropertyName)
+ UpdateBreadCrumbsBar(CurrentNaviItem);
+
}
void OnPageCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
page.PropertyChanged += NavigationBarPropertyChangedHandler;
}
+ void OnToolbarCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ UpdateToolbarItem(Element.CurrentPage);
+ }
+
void NavigationBarPropertyChangedHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// this handler is invoked only for child pages (contained on a navigation stack)
if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
UpdateHasNavigationBar(sender as Page);
+ else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName ||
+ e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
+ UpdateHasBackButton(sender as Page);
else if (e.PropertyName == Page.TitleProperty.PropertyName)
UpdateTitle(sender as Page);
+ else if (e.PropertyName == SpecificPage.BreadCrumbProperty.PropertyName)
+ UpdateBreadCrumbsBar(GetNaviItemForPage(sender as Page));
}
void UpdateHasNavigationBar(Page page)
}
return;
}
+ //According to TV UX Guideline, item style should be set to "tabbar" in case of TabbedPage only for TV profile.
+ if (Device.Idiom == TargetIdiom.TV)
+ {
+ item.Style = page is TabbedPage ? "tabbar" : "default";
+ }
item.TitleBarVisible = (bool)page.GetValue(NavigationPage.HasNavigationBarProperty);
+ UpdateToolbarItem(page, item);
UpdateBarBackgroundColor(item);
+ UpdateBreadCrumbsBar(item);
+ }
+
+ void UpdateToolbarItem(Page page, NaviItem item = null)
+ {
+ if (item == null)
+ item = GetNaviItemForPage(page);
+
+ if (_naviFrame.NavigationStack.Count == 0 || item == null || item != _naviFrame.NavigationStack.Last())
+ return;
+
+ Native.Button rightButton = GetToolbarButton(ToolbarButtonPosition.Right);
+ item.SetPartContent(PartRightToolbar, rightButton);
+
+ Native.Button leftButton = GetToolbarButton(ToolbarButtonPosition.Left);
+ item.SetPartContent(PartLeftToolbar, leftButton);
+ UpdateHasBackButton(page, item);
+ }
+
+ void UpdateHasBackButton(Page page, NaviItem item = null)
+ {
+ if (item == null)
+ item = GetNaviItemForPage(page);
+
+ EButton button = null;
+
+ if ((bool)page.GetValue(NavigationPage.HasBackButtonProperty) && _naviFrame.NavigationStack.Count > 1)
+ {
+ button = CreateNavigationButton((string)page.GetValue(NavigationPage.BackButtonTitleProperty));
+ }
+ item.SetPartContent(PartBackButton, button);
}
void UpdateTitle(Page page, NaviItem item = null)
UpdateBarBackgroundColor(item);
}
+ void UpdateBreadCrumbsBar(NaviItem item)
+ {
+ if (Element.OnThisPlatform().HasBreadCrumbsBar())
+ {
+ item.Style = StyleNavigationBar;
+ item.SetPartContent(PartNavigationBar, GetBreadCrumbsBar());
+ }
+ else
+ {
+ item.SetPartContent(PartNavigationBar, null, false);
+ }
+ }
+
+ EButton CreateNavigationButton(string text)
+ {
+ EButton button = new EButton(Forms.NativeParent);
+ button.Clicked += (sender, e) =>
+ {
+ if (!Element.SendBackButtonPressed())
+ Forms.Context.Exit();
+ };
+
+ button.Style = StyleBackButton;
+ button.Text = text;
+
+ _naviItemContentPartList.Add(button);
+ button.Deleted += NaviItemPartContentDeletedHandler;
+
+ return button;
+ }
+
void NaviItemPartContentDeletedHandler(object sender, EventArgs e)
{
_naviItemContentPartList.Remove(sender as Widget);
return null;
}
+ Native.Button GetToolbarButton(ToolbarButtonPosition position)
+ {
+ ToolbarItem item = _toolbarTracker.ToolbarItems.Where(
+ i => (position == ToolbarButtonPosition.Right && i.Order <= ToolbarItemOrder.Primary)
+ || (position == ToolbarButtonPosition.Left && i.Order == ToolbarItemOrder.Secondary))
+ .OrderBy(i => i.Priority).FirstOrDefault();
+
+ if (item == default(ToolbarItem))
+ return null;
+
+ Native.ToolbarItemButton button = new Native.ToolbarItemButton(item);
+ return button;
+ }
+
+ EToolbar GetBreadCrumbsBar()
+ {
+ EToolbar toolbar = new EToolbar(Forms.NativeParent)
+ {
+ Style = StyleNavigationBar,
+ ItemAlignment = 0,
+ Homogeneous = false,
+ ShrinkMode = ToolbarShrinkMode.Scroll
+ };
+
+ foreach (var p in Element.Navigation.NavigationStack)
+ {
+ string breadCrumb = p.OnThisPlatform().GetBreadCrumb();
+ if (!string.IsNullOrEmpty(breadCrumb))
+ {
+ EToolbarItem toolbarItem = toolbar.Append(breadCrumb);
+ toolbarItem.Selected += (s, e) =>
+ {
+ var copyOfStack = Element.Navigation.NavigationStack.Reverse().Skip(1);
+ foreach (var lp in copyOfStack)
+ {
+ if (lp == p) break;
+ Element.Navigation.RemovePage(lp);
+ }
+ if (Element.Navigation.NavigationStack.Last() != p)
+ Element.Navigation.PopAsync();
+ };
+ }
+ }
+
+ return toolbar;
+ }
+
void OnPopRequested(object sender, NavigationRequestedEventArgs nre)
{
if ((Element as IPageController).InternalChildren.Count == _naviFrame.NavigationStack.Count)
--- /dev/null
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.Platform.Tizen.Native;
+using Xamarin.Forms.Platform.Tizen.Native.Watch;
+using ElmSharp;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class PickerRenderer : ViewRenderer<Picker, EditfieldEntry>
+ {
+ List _list;
+ Dialog _dialog;
+ Dictionary<ListItem, int> _itemToItemNumber = new Dictionary<ListItem, int>();
+
+ public PickerRenderer()
+ {
+ RegisterPropertyHandler(Picker.SelectedIndexProperty, UpdateSelectedIndex);
+ RegisterPropertyHandler(Picker.TextColorProperty, UpdateTextColor);
+ RegisterPropertyHandler(Picker.FontSizeProperty, UpdateFontSize);
+ RegisterPropertyHandler(Picker.FontFamilyProperty, UpdateFontFamily);
+ RegisterPropertyHandler(Picker.FontAttributesProperty, UpdateFontAttributes);
+ RegisterPropertyHandler(Picker.TitleProperty, UpdateTitle);
+ RegisterPropertyHandler(Picker.TitleColorProperty, UpdateTitleColor);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.TextBlockFocused -= OnTextBlockFocused;
+ if (Device.Idiom == TargetIdiom.TV)
+ {
+ Control.LayoutFocused -= OnLayoutFocused;
+ Control.LayoutUnfocused -= OnLayoutUnfocused;
+ }
+ CleanView();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (Control == null)
+ {
+ var entry = new EditfieldEntry(Forms.NativeParent)
+ {
+ IsSingleLine = true,
+ InputPanelShowByOnDemand = true,
+ };
+ entry.SetVerticalTextAlignment("elm.text", 0.5);
+ entry.HorizontalTextAlignment = Native.TextAlignment.Center;
+ entry.TextBlockFocused += OnTextBlockFocused;
+
+ if (Device.Idiom == TargetIdiom.TV)
+ {
+ entry.LayoutFocused += OnLayoutFocused;
+ entry.LayoutUnfocused += OnLayoutUnfocused;
+ }
+
+ SetNativeControl(entry);
+ }
+ base.OnElementChanged(e);
+ }
+
+ void UpdateSelectedIndex()
+ {
+ Control.Text = (Element.SelectedIndex == -1 || Element.Items == null ?
+ "" : Element.Items[Element.SelectedIndex]);
+ }
+
+ void UpdateTextColor()
+ {
+ Control.TextColor = Element.TextColor.ToNative();
+ }
+
+ void UpdateFontSize()
+ {
+ Control.FontSize = Element.FontSize;
+ }
+
+ void UpdateFontFamily()
+ {
+ Control.FontFamily = Element.FontFamily;
+ }
+
+ void UpdateFontAttributes()
+ {
+ Control.FontAttributes = Element.FontAttributes;
+ }
+
+ void UpdateTitle()
+ {
+ Control.Placeholder = Element.Title;
+ }
+
+ void UpdateTitleColor()
+ {
+ Control.PlaceholderColor = Element.TitleColor.ToNative();
+ }
+
+ void OnLayoutFocused(object sender, EventArgs e)
+ {
+ Control.FontSize = Control.FontSize * 1.5;
+ }
+
+ void OnLayoutUnfocused(object sender, EventArgs e)
+ {
+ Control.FontSize = Control.FontSize / 1.5;
+ }
+
+ void OnTextBlockFocused(object sender, EventArgs e)
+ {
+ // For EFL Entry, the event will occur even if it is currently disabled.
+ // If the problem is resolved, no conditional statement is required.
+ if (Element.IsEnabled)
+ {
+ int i = 0;
+ if (Device.Idiom == TargetIdiom.Watch)
+ {
+ _dialog = new WatchDialog(Forms.NativeParent, false);
+ }
+ else
+ {
+ _dialog = new Dialog(Forms.NativeParent);
+ }
+ _dialog.AlignmentX = -1;
+ _dialog.AlignmentY = -1;
+ _dialog.Title = Element.Title;
+ _dialog.TitleColor = Element.TitleColor.ToNative();
+ _dialog.Dismissed += OnDialogDismissed;
+ _dialog.BackButtonPressed += (object senders, EventArgs es) =>
+ {
+ _dialog.Dismiss();
+ };
+
+ _list = new List(_dialog);
+ foreach (var s in Element.Items)
+ {
+ ListItem item = _list.Append(s);
+ _itemToItemNumber[item] = i;
+ i++;
+ }
+ _list.ItemSelected += OnItemSelected;
+ _dialog.Content = _list;
+
+ // You need to call Show() after ui thread occupation because of EFL problem.
+ // Otherwise, the content of the popup will not receive focus.
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ _dialog.Show();
+ _list.Show();
+ });
+ }
+ }
+
+ void OnItemSelected(object senderObject, EventArgs ev)
+ {
+ Element.SetValueFromRenderer(Picker.SelectedIndexProperty, _itemToItemNumber[(senderObject as List).SelectedItem]);
+ _dialog.Dismiss();
+ }
+
+ void OnDialogDismissed(object sender, EventArgs e)
+ {
+ CleanView();
+ }
+
+ void CleanView()
+ {
+ if (null != _list)
+ {
+ _list.Unrealize();
+ _itemToItemNumber.Clear();
+ _list = null;
+ }
+ if (null != _dialog)
+ {
+ _dialog.Unrealize();
+ _dialog = null;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using EColor = ElmSharp.Color;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class SearchBarRenderer : ViewRenderer<SearchBar, Native.SearchBar>
+ {
+
+ /// <summary>
+ /// Creates a new instance of the <see cref="Xamarin.Forms.Platform.Tizen.SearchBarRenderer"/> class.
+ /// Registers handlers for various properties of the SearchBar widget.
+ /// </summary>
+ public SearchBarRenderer()
+ {
+ RegisterPropertyHandler(SearchBar.CancelButtonColorProperty, CancelButtonColorPropertyHandler);
+ RegisterPropertyHandler(SearchBar.FontAttributesProperty, FontAttributesPropertyHandler);
+ RegisterPropertyHandler(SearchBar.FontFamilyProperty, FontFamilyPropertyHandler);
+ RegisterPropertyHandler(SearchBar.FontSizeProperty, FontSizePropertyHandler);
+ RegisterPropertyHandler(SearchBar.HorizontalTextAlignmentProperty, HorizontalTextAlignmentPropertyHandler);
+ RegisterPropertyHandler(SearchBar.PlaceholderProperty, PlaceholderPropertyHandler);
+ RegisterPropertyHandler(SearchBar.PlaceholderColorProperty, PlaceholderColorPropertyHandler);
+ RegisterPropertyHandler(SearchBar.TextProperty, TextPropertyHandler);
+ RegisterPropertyHandler(SearchBar.TextColorProperty, TextColorPropertyHandler);
+ RegisterPropertyHandler(InputView.KeyboardProperty, UpdateKeyboard);
+ RegisterPropertyHandler(InputView.MaxLengthProperty, UpdateMaxLength);
+ RegisterPropertyHandler(InputView.IsSpellCheckEnabledProperty, UpdateIsSpellCheckEnabled);
+ RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
+ }
+
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.TextChanged -= OnTextChanged;
+ Control.Activated -= OnActivated;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ /// <summary>
+ /// A method called whenever the associated element has changed.
+ /// </summary>
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new Native.SearchBar(Forms.NativeParent));
+ Control.IsSingleLine = true;
+ Control.SetInputPanelReturnKeyType(ElmSharp.InputPanelReturnKeyType.Search);
+
+ Control.TextChanged += OnTextChanged;
+ Control.Activated += OnActivated;
+ Control.PrependMarkUpFilter(MaxLengthFilter);
+
+ }
+ base.OnElementChanged(e);
+ }
+
+ protected override Size MinimumSize()
+ {
+ return Control.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's cancel button color property.
+ /// Converts current Color to ElmSharp.Color instance and sets it in the underlying Xamarin.Forms.Platform.Tizen.Native widget.
+ /// </summary>
+ void CancelButtonColorPropertyHandler(bool initialize)
+ {
+ if (initialize && Element.CancelButtonColor.IsDefault)
+ return;
+
+ Control.SetClearButtonColor(Element.CancelButtonColor.ToNative());
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's font attributes property.
+ /// Converts current FontAttributes to ElmSharp.FontAttributes instance
+ /// and sets it in the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void FontAttributesPropertyHandler()
+ {
+ Control.FontAttributes = Element.FontAttributes;
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's font family property.
+ /// Sets current value of FontFamily property to the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void FontFamilyPropertyHandler()
+ {
+ Control.FontFamily = Element.FontFamily;
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's font size property.
+ /// Sets current value of FontSize property to the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void FontSizePropertyHandler()
+ {
+ Control.FontSize = Element.FontSize;
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's horizontal text alignment property.
+ /// Converts current HorizontalTextAlignment property's value to Xamarin.Forms.Platform.Tizen.Native.TextAlignment instance
+ /// and sets it in the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void HorizontalTextAlignmentPropertyHandler()
+ {
+ Control.HorizontalTextAlignment = Element.HorizontalTextAlignment.ToNative();
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's placeholder color property.
+ /// Converts current PlaceholderColor property value to ElmSharp.Color instance
+ /// and sets it in the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void PlaceholderColorPropertyHandler(bool initialize)
+ {
+ if (initialize && Element.TextColor.IsDefault)
+ return;
+
+ Control.PlaceholderColor = Element.PlaceholderColor.ToNative();
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's placeholder text property.
+ /// </summary>
+ void PlaceholderPropertyHandler()
+ {
+ Control.Placeholder = Element.Placeholder;
+ }
+
+ /// <summary>
+ /// Called on every change of underlying SearchBar's Text property.
+ /// Rewrites current underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar's Text contents to its Xamarin counterpart.
+ /// </summary>
+ /// <param name="sender">Sender.</param>
+ void OnTextChanged(object sender, EventArgs e)
+ {
+ Element.SetValueFromRenderer(SearchBar.TextProperty, Control.Text);
+ }
+
+ /// <summary>
+ /// Called when the user clicks the Search button.
+ /// </summary>
+ /// <param name="sender">Sender.</param>
+ /// <param name="e">Event arguments.</param>
+ void OnActivated(object sender, EventArgs e)
+ {
+ Control.HideInputPanel();
+ (Element as ISearchBarController).OnSearchButtonPressed();
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's text color property.
+ /// Converts current TextColor property value to ElmSharp.Color instance
+ /// and sets it in the underlying Xamarin.Forms.Platform.Tizen.Native.SearchBar widget.
+ /// </summary>
+ void TextColorPropertyHandler(bool initialize)
+ {
+ if (initialize && Element.TextColor.IsDefault)
+ return;
+
+ Control.TextColor = Element.TextColor.ToNative();
+ }
+
+ /// <summary>
+ /// Called upon changing of Xamarin widget's text property.
+ /// </summary>
+ void TextPropertyHandler()
+ {
+ Control.Text = Element.Text;
+ }
+
+ void UpdateKeyboard(bool initialize)
+ {
+ if (initialize && Element.Keyboard == Keyboard.Default)
+ return;
+ Control.UpdateKeyboard(Element.Keyboard, Element.IsSpellCheckEnabled, true);
+ }
+
+ void UpdateIsSpellCheckEnabled()
+ {
+ Control.InputHint = Element.Keyboard.ToInputHints(Element.IsSpellCheckEnabled, true);
+ }
+
+ void UpdateMaxLength()
+ {
+ if (Control.Text.Length > Element.MaxLength)
+ Control.Text = Control.Text.Substring(0, Element.MaxLength);
+ }
+
+ string MaxLengthFilter(ElmSharp.Entry entry, string s)
+ {
+ if (entry.Text.Length < Element.MaxLength)
+ return s;
+
+ return null;
+ }
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsEditable = !Element.IsReadOnly;
+ }
+ }
+}
public class SwitchRenderer : ViewRenderer<Switch, Check>
{
readonly string _onColorPart;
+ readonly bool _isTV;
string _onColorEdjePart;
public SwitchRenderer()
{
- _onColorPart = "outer_bg_on";
+ _isTV = Device.Idiom == TargetIdiom.TV;
+ _onColorPart = _isTV ? "slider_on" : Device.Idiom == TargetIdiom.Watch ? "outer_bg_on" : "bg_on";
RegisterPropertyHandler(Switch.IsToggledProperty, HandleToggled);
RegisterPropertyHandler(Switch.OnColorProperty, UpdateOnColor);
}
if (Element.OnColor.IsDefault)
{
Control.EdjeObject.DeleteColorClass(_onColorEdjePart);
+ if (_isTV)
+ Control.EdjeObject.DeleteColorClass(_onColorEdjePart.Replace(_onColorPart, "slider_focused_on"));
}
else
{
EColor color = Element.OnColor.ToNative();
Control.SetPartColor(_onColorPart, color);
+ if (_isTV)
+ Control.SetPartColor("slider_focused_on", color);
}
}
}
--- /dev/null
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using ElmSharp;
+using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
+using EColor = ElmSharp.Color;
+using EToolbarItem = ElmSharp.ToolbarItem;
+using EToolbarItemEventArgs = ElmSharp.ToolbarItemEventArgs;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class TabbedPageRenderer : VisualElementRenderer<TabbedPage>
+ {
+ Box _outterLayout;
+ Box _innerBox;
+ Scroller _scroller;
+ Toolbar _toolbar;
+ Dictionary<EToolbarItem, Page> _itemToItemPage = new Dictionary<EToolbarItem, Page>();
+ List<EToolbarItem> _toolbarItemList = new List<EToolbarItem>();
+ bool _isResettingToolbarItems = false;
+ bool _isInitialized = false;
+ bool _isUpdateByToolbar = false;
+ bool _isUpdateByScroller = false;
+ bool _isUpdateByCurrentPage = false;
+
+ public TabbedPageRenderer()
+ {
+ RegisterPropertyHandler(Page.TitleProperty, UpdateTitle);
+ RegisterPropertyHandler(nameof(Element.CurrentPage), OnCurrentPageChanged);
+ RegisterPropertyHandler(TabbedPage.BarBackgroundColorProperty, UpdateBarBackgroundColor);
+ RegisterPropertyHandler(TabbedPage.BarTextColorProperty, UpdateBarTextColor);
+ RegisterPropertyHandler(TabbedPage.SelectedTabColorProperty, UpdateSelectedTabColor);
+ RegisterPropertyHandler(TabbedPage.UnselectedTabColorProperty, UpdateUnselectedTabColor);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
+ {
+ if (_toolbar == null)
+ {
+ //Create box that holds toolbar and selected content
+ _outterLayout = new Box(Forms.NativeParent)
+ {
+ AlignmentX = -1,
+ AlignmentY = -1,
+ WeightX = 1,
+ WeightY = 1,
+ IsHorizontal = false,
+ };
+ _outterLayout.Show();
+
+ //Create toolbar that is placed inside the _outterLayout
+ _toolbar = new Toolbar(Forms.NativeParent)
+ {
+ AlignmentX = -1,
+ WeightX = 1,
+ SelectionMode = ToolbarSelectionMode.Always,
+ };
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ //Set ShrinkMode to Expand as defauly only for Mobile profile
+ _toolbar.ShrinkMode = ToolbarShrinkMode.Expand;
+ }
+ else if (Device.Idiom == TargetIdiom.TV)
+ {
+ //According to TV UX Guideline, toolbar style should be set to "tabbar_with_title" in case of TabbedPage only for TV profile.
+ _toolbar.Style = "tabbar_with_title";
+ }
+
+ _toolbar.Show();
+ //Add callback for Toolbar item selection
+ _toolbar.Selected += OnToolbarItemSelected;
+ _outterLayout.PackEnd(_toolbar);
+
+ _scroller = new Scroller(_outterLayout)
+ {
+ AlignmentX = -1,
+ AlignmentY = -1,
+ WeightX = 1,
+ WeightY = 1,
+ HorizontalPageScrollLimit = 1,
+ ScrollBlock = ScrollBlock.Vertical,
+ HorizontalScrollBarVisiblePolicy = ScrollBarVisiblePolicy.Invisible
+ };
+ _scroller.SetPageSize(1.0, 1.0);
+ _scroller.PageScrolled += OnItemPageScrolled;
+
+ _innerBox = new Box(Forms.NativeParent)
+ {
+ AlignmentX = -1,
+ AlignmentY = -1,
+ WeightX = 1,
+ WeightY = 1,
+ IsHorizontal = true,
+ };
+
+ _innerBox.SetLayoutCallback(OnInnerLayoutUpdate);
+
+ _scroller.SetContent(_innerBox);
+ _scroller.Show();
+
+ _outterLayout.PackEnd(_scroller);
+
+ SetNativeView(_outterLayout);
+ UpdateTitle();
+ }
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.PagesChanged -= OnElementPagesChanged;
+ _isInitialized = false;
+ }
+ if (e.NewElement != null)
+ {
+ e.NewElement.PagesChanged += OnElementPagesChanged;
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Element.PagesChanged -= OnElementPagesChanged;
+ if (_outterLayout != null)
+ {
+ _outterLayout.Unrealize();
+ _outterLayout = null;
+ }
+ if (_toolbar != null)
+ {
+ _toolbar.Selected -= OnToolbarItemSelected;
+ _scroller.PageScrolled -= OnItemPageScrolled;
+ _toolbar.Unrealize();
+ _toolbar = null;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementReady()
+ {
+ base.OnElementReady();
+ _isInitialized = true;
+ FillToolbarAndContents();
+ Element.UpdateFocusTreePolicy();
+ }
+
+ protected override void UpdateThemeStyle()
+ {
+ var style = Element.OnThisPlatform().GetStyle();
+ if (!string.IsNullOrEmpty(style))
+ {
+ _toolbar.Style = style;
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+ }
+
+ void OnInnerLayoutUpdate()
+ {
+ if (!_isInitialized)
+ return;
+
+ int baseX = _innerBox.Geometry.X;
+ Rect bound = _scroller.Geometry;
+ int index = 0;
+ foreach (var page in Element.Children)
+ {
+ var nativeView = Platform.GetRenderer(page).NativeView;
+ bound.X = baseX + index * bound.Width;
+ nativeView.Geometry = bound;
+ index++;
+ }
+ _innerBox.MinimumWidth = Element.Children.Count * bound.Width;
+ if (_toolbar.SelectedItem == null)
+ return;
+ int currentPage = MultiPage<Page>.GetIndex(_itemToItemPage[_toolbar.SelectedItem]);
+ _scroller.ScrollTo(currentPage, 0, false);
+ }
+
+ void OnItemPageScrolled(object sender, System.EventArgs e)
+ {
+ if (_isUpdateByToolbar || _isUpdateByCurrentPage)
+ return;
+ _isUpdateByScroller = true;
+
+ var oldPage = Element.CurrentPage;
+ var toBeSelectedItem = _toolbarItemList[_scroller.HorizontalPageIndex];
+ var newPage = _itemToItemPage[toBeSelectedItem];
+
+ if (oldPage != newPage)
+ {
+ oldPage?.SendDisappearing();
+ newPage.SendAppearing();
+
+ toBeSelectedItem.IsSelected = true;
+ Element.CurrentPage = newPage;
+ Element.UpdateFocusTreePolicy();
+ }
+
+ _isUpdateByScroller = false;
+ }
+
+ void UpdateBarBackgroundColor(bool initialize)
+ {
+ if (initialize && Element.BarBackgroundColor.IsDefault)
+ return;
+
+ EColor bgColor = Element.BarBackgroundColor.ToNative();
+ _toolbar.BackgroundColor = bgColor;
+ foreach (EToolbarItem item in _itemToItemPage.Keys)
+ {
+ ApplyBarItemColors(item, BarItemColorType.Background, bgColor);
+ }
+ }
+
+ void UpdateBarTextColor(bool initialize)
+ {
+ if (initialize && Element.BarTextColor.IsDefault)
+ return;
+
+ foreach (EToolbarItem item in _itemToItemPage.Keys)
+ {
+ ApplyBarItemColors(item, BarItemColorType.Text, Element.BarTextColor.ToNative());
+ }
+ }
+
+ void UpdateSelectedTabColor(bool initialize)
+ {
+ if (initialize && Element.SelectedTabColor.IsDefault)
+ return;
+
+ foreach (EToolbarItem item in _itemToItemPage.Keys)
+ {
+ ApplyBarItemColors(item, BarItemColorType.SelectedTab, Element.SelectedTabColor.ToNative());
+ }
+ }
+
+ void UpdateUnselectedTabColor(bool initialize)
+ {
+ if (initialize && Element.UnselectedTabColor.IsDefault)
+ return;
+
+ foreach (EToolbarItem item in _itemToItemPage.Keys)
+ {
+ ApplyBarItemColors(item, BarItemColorType.UnselectedTab, Element.UnselectedTabColor.ToNative());
+ }
+ }
+
+ void UpdateTitle()
+ {
+ _toolbar.Text = Element.Title;
+ }
+
+ void UpdateTitle(Page page)
+ {
+ if (_itemToItemPage.ContainsValue(page))
+ {
+ var pair = _itemToItemPage.FirstOrDefault(x => x.Value == page);
+ pair.Key.SetPartText(null, pair.Value.Title);
+ }
+ }
+
+ void OnPageTitleChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName)
+ {
+ UpdateTitle(sender as Page);
+ }
+ }
+
+ void OnElementPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ AddToolbarItems(e);
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ RemoveToolbarItems(e);
+ break;
+ default:
+ ResetToolbarItems();
+ break;
+ }
+ Element.UpdateFocusTreePolicy();
+ }
+
+ void AddToolbarItems(NotifyCollectionChangedEventArgs e)
+ {
+ int index = e.NewStartingIndex < 0 ? _toolbar.ItemsCount : e.NewStartingIndex;
+ foreach (Page item in e.NewItems)
+ {
+ AddToolbarItem(item, index++);
+ }
+ }
+
+ EToolbarItem AddToolbarItem(Page newItem, int index)
+ {
+ EToolbarItem toolbarItem;
+
+ // TODO: investigate if we can use the other image source types: stream, font, uri
+
+ var iconSource = newItem.IconImageSource as FileImageSource;
+ var icon = iconSource.IsNullOrEmpty() ? null : ResourcePath.GetPath(iconSource);
+
+ if (index == 0)
+ {
+ toolbarItem = _toolbar.Prepend(newItem.Title, icon);
+ }
+ else
+ {
+ toolbarItem = _toolbar.InsertAfter(_toolbarItemList[index - 1], newItem.Title, icon);
+ }
+ _toolbarItemList.Insert(index, toolbarItem);
+ _itemToItemPage.Add(toolbarItem, newItem);
+
+ ApplyBarItemColors(toolbarItem, BarItemColorType.Background, Element.BarBackgroundColor.ToNative());
+ ApplyBarItemColors(toolbarItem, BarItemColorType.Text, Element.BarTextColor.ToNative());
+ ApplyBarItemColors(toolbarItem, BarItemColorType.SelectedTab, Element.SelectedTabColor.ToNative());
+ ApplyBarItemColors(toolbarItem, BarItemColorType.UnselectedTab, Element.UnselectedTabColor.ToNative());
+
+ var childContent = Platform.GetOrCreateRenderer(newItem).NativeView;
+ _innerBox.PackEnd(childContent);
+
+ newItem.PropertyChanged += OnPageTitleChanged;
+
+ return toolbarItem;
+ }
+
+ void RemoveToolbarItems(NotifyCollectionChangedEventArgs e)
+ {
+ foreach (Page item in e.OldItems)
+ {
+ RemoveToolbarItem(item);
+ }
+ }
+
+ void RemoveToolbarItem(Page oldItem)
+ {
+ foreach (var pair in _itemToItemPage)
+ {
+ if (pair.Value == oldItem)
+ {
+ pair.Value.PropertyChanged -= OnPageTitleChanged;
+ _toolbarItemList.Remove(pair.Key);
+ _itemToItemPage.Remove(pair.Key);
+ pair.Key.Delete();
+ return;
+ }
+ }
+ }
+
+ void ResetToolbarItems()
+ {
+ _isResettingToolbarItems = true;
+ foreach (var pair in _itemToItemPage)
+ {
+ pair.Value.PropertyChanged -= OnPageTitleChanged;
+ pair.Key.Delete();
+ }
+ _itemToItemPage.Clear();
+ _toolbarItemList.Clear();
+
+ FillToolbarAndContents();
+ _isResettingToolbarItems = false;
+ }
+
+ void FillToolbarAndContents()
+ {
+ int index = 0;
+ //add items to toolbar
+ foreach (Page child in Element.Children)
+ {
+ EToolbarItem toolbarItem = AddToolbarItem(child, index++);
+
+ if (Element.CurrentPage == child)
+ {
+ //select item on the toolbar and fill content
+ toolbarItem.IsSelected = true;
+ }
+ }
+ }
+
+ void OnToolbarItemSelected(object sender, EToolbarItemEventArgs e)
+ {
+ if (_toolbar.SelectedItem == null || _isResettingToolbarItems)
+ return;
+ if (_isUpdateByCurrentPage || _isUpdateByScroller)
+ return;
+ _isUpdateByToolbar = true;
+
+ var oldPage = Element.CurrentPage;
+ var newPage = _itemToItemPage[_toolbar.SelectedItem];
+
+ if (oldPage != newPage)
+ {
+ oldPage?.SendDisappearing();
+ Element.CurrentPage = newPage;
+ newPage?.SendAppearing();
+
+ int index = MultiPage<Page>.GetIndex(newPage);
+ _scroller.ScrollTo(index, 0, true);
+
+ Element.UpdateFocusTreePolicy();
+ }
+ _isUpdateByToolbar = false;
+ }
+
+ void OnCurrentPageChanged()
+ {
+ // To update TabIndex order
+ CustomFocusManager.StartReorderTabIndex();
+
+ if (_isUpdateByScroller || _isUpdateByToolbar || !_isInitialized)
+ return;
+
+ _isUpdateByCurrentPage = true;
+ Page oldPage = null;
+ if (_toolbar.SelectedItem != null && _itemToItemPage.ContainsKey(_toolbar.SelectedItem))
+ oldPage = _itemToItemPage[_toolbar.SelectedItem];
+
+ oldPage?.SendDisappearing();
+ Element.CurrentPage?.SendAppearing();
+
+ int index = MultiPage<Page>.GetIndex(Element.CurrentPage);
+ _toolbarItemList[index].IsSelected = true;
+ _scroller.ScrollTo(index, 0, true);
+
+ Element.UpdateFocusTreePolicy();
+ _isUpdateByCurrentPage = false;
+ }
+
+ void ApplyBarItemColors(EToolbarItem item, BarItemColorType type, EColor color)
+ {
+ if (color.IsDefault)
+ {
+ ClearBarItemColors(item, type);
+ }
+ else
+ {
+ switch (type)
+ {
+ case BarItemColorType.Background:
+ item.SetPartColor("bg", color);
+ break;
+ case BarItemColorType.Text:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.SetPartColor("text", color);
+ item.SetPartColor("text_pressed", color);
+ item.SetPartColor("text_selected", color);
+ }
+ else
+ {
+ item.SetPartColor("text_under_icon", color);
+ item.SetPartColor("text_under_icon_pressed", color);
+ item.SetPartColor("text_under_icon_selected", color);
+ }
+ item.SetPartColor("underline", color);
+ break;
+ case BarItemColorType.SelectedTab:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.SetPartColor("text_selected", color);
+ }
+ else
+ {
+ item.SetPartColor("text_under_icon_selected", color);
+ item.SetPartColor("icon_selected", color);
+ }
+ item.SetPartColor("underline", color);
+ break;
+ case BarItemColorType.UnselectedTab:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.SetPartColor("text", color);
+ item.SetPartColor("text_pressed", color);
+ }
+ else
+ {
+ item.SetPartColor("text_under_icon", color);
+ item.SetPartColor("text_under_icon_pressed", color);
+ item.SetPartColor("icon", color);
+ item.SetPartColor("icon_pressed", color);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void ClearBarItemColors(EToolbarItem item, BarItemColorType type)
+ {
+ switch (type)
+ {
+ case BarItemColorType.Background:
+ item.DeletePartColor("bg");
+ break;
+ case BarItemColorType.Text:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.DeletePartColor("text");
+ item.DeletePartColor("text_pressed");
+ item.DeletePartColor("text_selected");
+ }
+ else
+ {
+ item.DeletePartColor("text_under_icon");
+ item.DeletePartColor("text_under_icon_pressed");
+ item.DeletePartColor("text_under_icon_selected");
+ }
+ item.DeletePartColor("underline");
+ break;
+ case BarItemColorType.SelectedTab:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.DeletePartColor("text_selected");
+ }
+ else
+ {
+ item.DeletePartColor("text_under_icon_selected");
+ item.DeletePartColor("icon_selected");
+ }
+ item.DeletePartColor("underline");
+ break;
+ case BarItemColorType.UnselectedTab:
+ if (string.IsNullOrEmpty(item.Icon))
+ {
+ item.DeletePartColor("text");
+ item.DeletePartColor("text_pressed");
+ }
+ else
+ {
+ item.DeletePartColor("text_under_icon");
+ item.DeletePartColor("text_under_icon_pressed");
+ item.DeletePartColor("icon");
+ item.DeletePartColor("icon_pressed");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ enum BarItemColorType
+ {
+ Background,
+ Text,
+ SelectedTab,
+ UnselectedTab
+ }
+}
--- /dev/null
+using System;
+using System.Globalization;
+using Xamarin.Forms.Platform.Tizen.Native;
+using WatchDataTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDataTimePickerDialog;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+ public class TimePickerRenderer : ViewRenderer<TimePicker, EditfieldEntry>
+ {
+ //TODO need to add internationalization support
+ const string DialogTitle = "Choose Time";
+ static readonly string s_defaultFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
+
+ TimeSpan _time = DateTime.Now.TimeOfDay;
+ Lazy<IDateTimeDialog> _lazyDialog;
+
+ public TimePickerRenderer()
+ {
+ RegisterPropertyHandler(TimePicker.FormatProperty, UpdateFormat);
+ RegisterPropertyHandler(TimePicker.TimeProperty, UpdateTime);
+ RegisterPropertyHandler(TimePicker.TextColorProperty, UpdateTextColor);
+ RegisterPropertyHandler(TimePicker.FontAttributesProperty, UpdateFontAttributes);
+ RegisterPropertyHandler(TimePicker.FontFamilyProperty, UpdateFontFamily);
+ RegisterPropertyHandler(TimePicker.FontSizeProperty, UpdateFontSize);
+ }
+
+ protected virtual IDateTimeDialog CreateDialog()
+ {
+ if (Device.Idiom == TargetIdiom.Watch)
+ {
+ return new WatchDataTimePickerDialog(Forms.NativeParent);
+ }
+ else
+ {
+ return new DateTimePickerDialog(Forms.NativeParent);
+ }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
+ {
+ if (Control == null)
+ {
+ var entry = new Native.EditfieldEntry(Forms.NativeParent)
+ {
+ IsSingleLine = true,
+ HorizontalTextAlignment = Native.TextAlignment.Center,
+ InputPanelShowByOnDemand = true,
+ };
+ entry.SetVerticalTextAlignment("elm.text", 0.5);
+ entry.TextBlockFocused += OnTextBlockFocused;
+ SetNativeControl(entry);
+
+ _lazyDialog = new Lazy<IDateTimeDialog>(() => {
+ var dialog = CreateDialog();
+ dialog.Picker.Mode = DateTimePickerMode.Time;
+ dialog.Title = DialogTitle;
+ dialog.DateTimeChanged += OnDialogTimeChanged;
+ return dialog;
+ });
+ }
+ base.OnElementChanged(e);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.TextBlockFocused -= OnTextBlockFocused;
+ }
+ if (_lazyDialog.IsValueCreated)
+ {
+ _lazyDialog.Value.DateTimeChanged -= OnDialogTimeChanged;
+ _lazyDialog.Value.Unrealize();
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override Size MinimumSize()
+ {
+ return Control.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+ }
+
+ void OnTextBlockFocused(object o, EventArgs e)
+ {
+ // For EFL Entry, the event will occur even if it is currently disabled.
+ // If the problem is resolved, no conditional statement is required.
+ if (Element.IsEnabled)
+ {
+ var dialog = _lazyDialog.Value;
+ dialog.Picker.Time = Element.Time;
+ // You need to call Show() after ui thread occupation because of EFL problem.
+ // Otherwise, the content of the popup will not receive focus.
+ Device.BeginInvokeOnMainThread(() => dialog.Show());
+ }
+ }
+
+ void OnDialogTimeChanged(object sender, Native.DateChangedEventArgs dcea)
+ {
+ Element.SetValueFromRenderer(TimePicker.TimeProperty, dcea.NewDate.TimeOfDay);
+ UpdateTime();
+ }
+
+ void UpdateFormat()
+ {
+ UpdateTimeAndFormat();
+ }
+
+ void UpdateTextColor()
+ {
+ Control.TextColor = Element.TextColor.ToNative();
+ }
+
+ void UpdateTime()
+ {
+ _time = Element.Time;
+ UpdateTimeAndFormat();
+ }
+
+ void UpdateFontSize()
+ {
+ Control.FontSize = Element.FontSize;
+ }
+
+ void UpdateFontFamily()
+ {
+ Control.FontFamily = Element.FontFamily;
+ }
+
+ void UpdateFontAttributes()
+ {
+ Control.FontAttributes = Element.FontAttributes;
+ }
+
+ void UpdateTimeAndFormat()
+ {
+ // Xamarin using DateTime formatting (https://developer.xamarin.com/api/property/Xamarin.Forms.TimePicker.Format/)
+ Control.Text = new DateTime(_time.Ticks).ToString(Element.Format ?? s_defaultFormat);
+ }
+ }
+}
_title = new Native.Label(Forms.NativeParent)
{
- FontSize = 23,
+ FontSize = Device.Idiom == TargetIdiom.TV ? 60 : 23,
VerticalTextAlignment = Native.TextAlignment.Center,
TextColor = _backgroudColor,
FontAttributes = FontAttributes.Bold,
Registered.Register(typeof(CarouselPage), () => new CarouselPageRenderer());
Registered.Register(typeof(Page), () => new PageRenderer());
Registered.Register(typeof(NavigationPage), () => new NavigationPageRenderer());
+ Registered.Register(typeof(MasterDetailPage), () => new MasterDetailPageRenderer());
+ Registered.Register(typeof(TabbedPage), () => new TabbedPageRenderer());
Registered.Register(typeof(Shell), () => new ShellRenderer());
Registered.Register(typeof(Label), () => new LabelRenderer());
Registered.Register(typeof(Button), () => new ButtonRenderer());
Registered.Register(typeof(Image), () => new ImageRenderer());
Registered.Register(typeof(Slider), () => new SliderRenderer());
+ Registered.Register(typeof(Picker), () => new PickerRenderer());
Registered.Register(typeof(Frame), () => new FrameRenderer());
Registered.Register(typeof(Stepper), () => new StepperRenderer());
+ Registered.Register(typeof(DatePicker), () => new DatePickerRenderer());
+ Registered.Register(typeof(TimePicker), () => new TimePickerRenderer());
Registered.Register(typeof(ProgressBar), () => new ProgressBarRenderer());
Registered.Register(typeof(Switch), () => new SwitchRenderer());
+ Registered.Register(typeof(CheckBox), () => new CheckBoxRenderer());
Registered.Register(typeof(ListView), () => new ListViewRenderer());
Registered.Register(typeof(BoxView), () => new BoxViewRenderer());
Registered.Register(typeof(ActivityIndicator), () => new ActivityIndicatorRenderer());
+ Registered.Register(typeof(SearchBar), () => new SearchBarRenderer());
Registered.Register(typeof(Entry), () => new EntryRenderer());
Registered.Register(typeof(Editor), () => new EditorRenderer());
Registered.Register(typeof(TableView), () => new TableViewRenderer());
switch (size)
{
case NamedSize.Micro:
- pt = 24;
+ pt = Device.Idiom == TargetIdiom.TV || Device.Idiom == TargetIdiom.Watch ? 24 : 19;
break;
case NamedSize.Small:
- pt = 30;
+ pt = Device.Idiom == TargetIdiom.TV ? 26 : (Device.Idiom == TargetIdiom.Watch ? 30 : 22);
break;
case NamedSize.Default:
case NamedSize.Medium:
- pt = 32;
+ pt = Device.Idiom == TargetIdiom.TV ? 28 : (Device.Idiom == TargetIdiom.Watch ? 32 : 25);
break;
case NamedSize.Large:
- pt = 36;
+ pt = Device.Idiom == TargetIdiom.TV ? 32 : (Device.Idiom == TargetIdiom.Watch ? 36 : 31);
break;
case NamedSize.Body:
- pt = 32;
+ pt = Device.Idiom == TargetIdiom.TV ? 30 : (Device.Idiom == TargetIdiom.Watch ? 32 : 28);
break;
case NamedSize.Caption:
- pt = 24;
+ pt = Device.Idiom == TargetIdiom.TV ? 26 : (Device.Idiom == TargetIdiom.Watch ? 24 : 22);
break;
case NamedSize.Header:
- pt = 36;
+ pt = Device.Idiom == TargetIdiom.TV ? 84 : (Device.Idiom == TargetIdiom.Watch ? 36 : 138);
break;
case NamedSize.Subtitle:
- pt = 30;
+ pt = Device.Idiom == TargetIdiom.TV ? 30 : (Device.Idiom == TargetIdiom.Watch ? 30 : 28);
break;
case NamedSize.Title:
- pt = 36;
+ pt = Device.Idiom == TargetIdiom.TV ? 42 : (Device.Idiom == TargetIdiom.Watch ? 36 : 40);
break;
default:
throw new ArgumentOutOfRangeException(nameof(size));
{
}
+ internal class _SearchBarRenderer
+ {
+ }
+
internal class _SwitchRenderer
{
}
+ internal class _DatePickerRenderer
+ {
+ }
+
+ internal class _TimePickerRenderer
+ {
+ }
+
+ internal class _PickerRenderer
+ {
+ }
+
internal class _StepperRenderer
{
}
{
}
+ internal class _CheckBoxRenderer
+ {
+ }
+
internal class _IndicatorViewRenderer
{
}
{
}
+ internal class _TabbedPageRenderer
+ {
+ }
+
internal class _NavigationPageRenderer
{
}
{
}
+ internal class _MasterDetailPageRenderer
+ {
+ }
+
internal class _SwipeViewRenderer
{
}
-}
+}
\ No newline at end of file