To apply the latest TabButton UX, TabButtonStyle class is added.
TabButtonStyle.TopLine and TabButtonStyle.BottomLine are displayed when
TabButton is pressed or selected.
Co-authored-by: Jaehyun Cho <jae_hyun.cho@samsung.com>
private TabButtonGroup tabButtonGroup;
- //TODO: This tab button height should be implemented in TabBar style.
- private float tabButtonHeight = 72.0f;
-
/// <summary>
/// Creates a new instance of TabBar.
/// </summary>
foreach (TabButton tabButton in tabButtons)
{
- if ((tabButton.Size.Width != tabButtonWidth) || (tabButton.Size.Height != tabButtonHeight))
+ if (tabButton.Size.Width != tabButtonWidth)
{
- tabButton.Size = new Size(tabButtonWidth, tabButtonHeight);
+ tabButton.Size = new Size(tabButtonWidth, tabButton.Size.Height);
}
}
}
{
private bool selectedAgain = false;
+ private TabButtonStyle tabButtonStyle = null;
+
+ private bool styleApplied = false;
+
+ private View topLine = null;
+ private View bottomLine = null; // Visible only if TabButton is selected or pressed.
+
/// <summary>
/// Creates a new instance of TabButton.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public TabButton()
{
- GridLayout.SetHorizontalStretch(this, GridLayout.StretchFlags.ExpandAndFill);
+ Initialize();
+ }
+
+ /// <summary>
+ /// Creates a new instance of TabButton.
+ /// </summary>
+ /// <param name="style">Creates TabButton by special style defined in UX.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TabButton(string style) : base(style)
+ {
+ Initialize();
+ }
+
+ /// <summary>
+ /// Creates a new instance of TabButton.
+ /// </summary>
+ /// <param name="tabButtonStyle">Creates TabButton by style customized by user.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TabButton(TabButtonStyle tabButtonStyle) : base(tabButtonStyle)
+ {
+ Initialize();
+ }
+
+ /// <summary>
+ /// Applies style to TabButton.
+ /// </summary>
+ /// <param name="viewStyle">The style to apply.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override void ApplyStyle(ViewStyle viewStyle)
+ {
+ styleApplied = false;
+
+ base.ApplyStyle(viewStyle);
+
+ tabButtonStyle = viewStyle as TabButtonStyle;
+
+ //Apply TopLine style.
+ if (tabButtonStyle?.TopLine != null)
+ {
+ topLine?.ApplyStyle(tabButtonStyle.TopLine);
+ }
+
+ //Apply BottomLine style.
+ if (tabButtonStyle?.BottomLine != null)
+ {
+ bottomLine?.ApplyStyle(tabButtonStyle.BottomLine);
+ }
+
+ styleApplied = true;
+
+ //Calculate children's sizes and positions based on padding sizes.
+ LayoutItems();
}
/// <inheritdoc/>
return ret;
}
+ /// <summary>
+ /// Dispose TabButton and all children on it.
+ /// </summary>
+ /// <param name="type">Dispose type.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void Dispose(DisposeTypes type)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ if (type == DisposeTypes.Explicit)
+ {
+ if (topLine != null)
+ {
+ Utility.Dispose(topLine);
+ }
+
+ if (bottomLine != null)
+ {
+ Utility.Dispose(bottomLine);
+ }
+ }
+
+ base.Dispose(type);
+ }
+
+ /// <summary>
+ /// Gets TabButton style.
+ /// </summary>
+ /// <returns>The default TabButton style.</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override ViewStyle CreateViewStyle()
+ {
+ return new TabButtonStyle();
+ }
+
/// <inheritdoc/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected override bool HandleControlStateOnTouch(Touch touch)
base.OnControlStateChanged(controlStateChangedInfo);
}
}
+
+ /// <inheritdoc/>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void OnUpdate()
+ {
+ base.OnUpdate();
+ LayoutItems();
+ }
+
+ /// <inheritdoc/>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void LayoutItems()
+ {
+ if (styleApplied == false)
+ {
+ return;
+ }
+
+ if ((Icon == null) && (TextLabel == null))
+ {
+ return;
+ }
+
+ // Icon is added in Button.LayoutItems().
+ if ((Icon != null) && (Children.Contains(Icon) == false))
+ {
+ Add(Icon);
+ }
+
+ // TextLabel is added in Button.LayoutItems().
+ if ((TextLabel != null) && (Children.Contains(TextLabel) == false))
+ {
+ Add(TextLabel);
+ }
+
+ // FIXME: set Selector<Extents> to padding
+ var padding = new Extents(40, 40, 24, 24);
+ var iconPadding = IconPadding;
+ var textPadding = TextPadding;
+
+ // Calculate size of TextLabel.
+ if (TextLabel != null)
+ {
+ // TODO: Other orientation cases are not implemented yet.
+ if ((IconRelativeOrientation == IconOrientation.Left) || (IconRelativeOrientation == IconOrientation.Right))
+ {
+ var naturalWidthSum = (ushort)padding?.Start + (ushort)padding?.End + iconPadding.Start + iconPadding.End + (float)Icon?.SizeWidth + TextLabel.GetNaturalSize().Width;
+ var naturalWidthDiff = SizeWidth - naturalWidthSum;
+
+ if (naturalWidthDiff > 0)
+ {
+ TextLabel.SizeWidth = TextLabel.GetNaturalSize().Width;
+ }
+ else
+ {
+ TextLabel.SizeWidth = SizeWidth - (ushort)padding?.Start - (ushort)padding?.End - iconPadding.Start - iconPadding.End - textPadding.Start - textPadding.End - (float)Icon?.SizeWidth;
+ }
+ }
+ }
+
+ // Calculate positions of Icon and TextLabel.
+ switch (IconRelativeOrientation)
+ {
+ // TODO: Other orientation cases are not implemented yet.
+ case IconOrientation.Left:
+ if (LayoutDirection == ViewLayoutDirectionType.LTR)
+ {
+ if (Icon != null)
+ {
+ float iconX = 0;
+ float iconY = (ushort)padding?.Top + iconPadding.Top;
+
+ if (string.IsNullOrEmpty(TextLabel?.Text))
+ {
+ iconX = (SizeWidth - Icon.SizeWidth) / 2;
+ }
+ else
+ {
+ var widthSum = (ushort)padding?.Start + (ushort)padding?.End + iconPadding.Start + iconPadding.End + textPadding.Start + textPadding.End + Icon.SizeWidth + (float)TextLabel?.SizeWidth;
+ var widthDiff = SizeWidth - widthSum;
+
+ if (widthDiff > 0)
+ {
+ iconX = (ushort)padding?.Start + iconPadding.Start + (widthDiff / 2);
+ }
+ else
+ {
+ iconX = (ushort)padding?.Start + iconPadding.Start;
+ }
+ }
+
+ Icon.Position = new Position(iconX, iconY);
+ }
+
+ if (TextLabel != null)
+ {
+ TextLabel.HorizontalAlignment = HorizontalAlignment.Begin;
+
+ float textX = 0;
+ float textY = 0;
+
+ if (string.IsNullOrEmpty(Icon?.ResourceUrl))
+ {
+ textX = (SizeWidth - TextLabel.SizeWidth) / 2;
+ textY = (ushort)padding?.Top + textPadding.Top;
+ }
+ else
+ {
+ textX = (float)Icon?.PositionX + (float)Icon?.SizeWidth;
+ textY = (ushort)padding?.Top + textPadding.Top + (((float)Icon?.SizeHeight - TextLabel.SizeHeight) / 2);
+ }
+
+ TextLabel.Position = new Position(textX, textY);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ padding?.Dispose();
+ }
+
+ private void Initialize()
+ {
+ Layout = new AbsoluteLayout();
+
+ topLine = new View(tabButtonStyle?.TopLine);
+ Add(topLine);
+
+ bottomLine = new View(tabButtonStyle?.BottomLine);
+ Add(bottomLine);
+ }
}
}
--- /dev/null
+/*
+ * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Binding;
+
+namespace Tizen.NUI.Components
+{
+ /// <summary>
+ /// TabButtonStyle is a class which saves TabButton's ux data.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class TabButtonStyle : ButtonStyle
+ {
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ static TabButtonStyle() { }
+
+ /// <summary>
+ /// Creates a new instance of a TabButtonStyle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TabButtonStyle() : base()
+ {
+ }
+
+ /// <summary>
+ /// Creates a new instance of a TabButtonStyle with style.
+ /// </summary>
+ /// <param name="style">Create TabButtonStyle by style customized by user.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public TabButtonStyle(TabButtonStyle style) : base(style)
+ {
+ }
+
+ /// <summary>
+ /// Gets or Sets the Line Style at the top of TabButton.
+ /// </summary>
+ internal ViewStyle TopLine { get; set; } = new ViewStyle();
+
+ /// <summary>
+ /// Gets or Sets the Line Style at the bottom of TabButton.
+ /// </summary>
+ internal ViewStyle BottomLine { get; set; } = new ViewStyle();
+
+ /// <summary>
+ /// Style's clone function.
+ /// </summary>
+ /// <param name="bindableObject">The style that need to copy.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override void CopyFrom(BindableObject bindableObject)
+ {
+ base.CopyFrom(bindableObject);
+
+ if (bindableObject is TabButtonStyle tabButtonStyle)
+ {
+ TopLine.CopyFrom(tabButtonStyle.TopLine);
+ BottomLine.CopyFrom(tabButtonStyle.BottomLine);
+ }
+ }
+ }
+}
.AddSelector("/ItemTextLabel/TextColor", (ViewStyle style, Selector<Color> value) => ((PickerStyle)style).ItemTextLabel.TextColor = value)
.AddSelector("/ItemTextLabel/PixelSize", (ViewStyle style, Selector<float?> value) => ((PickerStyle)style).ItemTextLabel.PixelSize = value)
.AddSelector("/Divider/Background", (ViewStyle style, Selector<Color> value) => ((PickerStyle)style).Divider.BackgroundColor = value),
+
+ // TabButton
+ (new ExternalThemeKeyList(typeof(TabButton), typeof(TabButtonStyle)))
+ .Add<Size>("/Size", (ViewStyle style, Size value) => ((ViewStyle)style).Size = value)
+ .Add<float?>("/CornerRadius", (ViewStyle style, float? value) => ((ViewStyle)style).CornerRadius = value)
+ .AddSelector<Color>("/BackgroundColor", (ViewStyle style, Selector<Color> value) => ((ViewStyle)style).BackgroundColor = value, ControlState.Selected)
+ .AddSelector<float?>("/Text/PixelSize", SetButtonTextPixelSize, ControlState.Selected)
+ .Add<Size>("/Text/Size", (ViewStyle style, Size value) => ((ButtonStyle)style).Text.Size = value)
+ .AddSelector<Color>("/Text/TextColor", SetButtonTextColor, ControlState.Selected)
+ .Add<Size>("/Icon/Size", (ViewStyle style, Size value) => ((ButtonStyle)style).Icon.Size = value)
+ .AddSelector<Color>("/Icon/Color", (ViewStyle style, Selector<Color> value) => ((ButtonStyle)style).Icon.Color = value, ControlState.Selected)
+ .Add<Size>("/TopLine/Size", (ViewStyle style, Size value) => ((TabButtonStyle)style).TopLine.Size = value)
+ .AddSelector<Color>("/TopLine/BackgroundColor", (ViewStyle style, Selector<Color> value) => ((TabButtonStyle)style).TopLine.BackgroundColor = value, ControlState.Selected)
+ .Add<Size>("/BottomLine/Size", (ViewStyle style, Size value) => ((TabButtonStyle)style).BottomLine.Size = value)
+ .Add<Position>("/BottomLine/Position", (ViewStyle style, Position value) => ((TabButtonStyle)style).BottomLine.Position = value)
+ .AddSelector<Color>("/BottomLine/BackgroundColor", (ViewStyle style, Selector<Color> value) => ((TabButtonStyle)style).BottomLine.BackgroundColor = value, ControlState.Selected),
};
return actionSet;
StartScrollOffset = new Size2D(0, 12),
});
+ theme.AddStyleWithoutClone("Tizen.NUI.Components.TabButton", new TabButtonStyle()
+ {
+ Size = new Size(-1, 84),
+ CornerRadius = 0,
+ BackgroundColor = Color.White,
+ Text = new TextLabelStyle()
+ {
+ PixelSize = 28,
+ Size = new Size(-2, -2),
+ TextColor = new Selector<Color>()
+ {
+ Normal = new Color("#000C2BFF"),
+ Selected = new Color("#000C2BFF"),
+ Pressed = new Color("#1473E6FF"),
+ Disabled = new Color("#C3CAD2FF"),
+ },
+ },
+ Icon = new ImageViewStyle()
+ {
+ Size = new Size(48, 48),
+ Color = new Selector<Color>()
+ {
+ Normal = new Color("#000C2BFF"),
+ Selected = new Color("#000C2BFF"),
+ Pressed = new Color("#1473E6FF"),
+ Disabled = new Color("#C3CAD2FF"),
+ },
+ },
+ TopLine = new ViewStyle()
+ {
+ Size = new Size(-1, 1),
+ BackgroundColor = new Selector<Color>()
+ {
+ Normal = new Color("#000C2BFF"),
+ Selected = new Color("#000C2BFF"),
+ Pressed = new Color("#1473E6FF"),
+ Disabled = new Color("#C3CAD2FF"),
+ },
+ },
+ BottomLine = new ViewStyle()
+ {
+ Size = new Size(-1, 8),
+ Position = new Position(0, 76), // 84 - 8
+ BackgroundColor = new Selector<Color>()
+ {
+ Normal = Color.Transparent,
+ Selected = new Color("#000C2BFF"),
+ Pressed = new Color("#1473E6FF"),
+ Disabled = Color.Transparent,
+ },
+ },
+ });
+
return theme;
}
}