1
\$\begingroup\$

Heyhey, I'm attempting to implement a ToggleBar control for Xamarin as there is non up to date and fully customizeable.

Now I haven't implemented too many controls and while the control is not fully implemented yet (I want to add an Icon option for the ToggleButtons later, but want to improve on the base before I develop new features for it.

Any tips/improvements that can be done to this control?

 public class TogglesBar : ContentView
    {
        private readonly Grid _gridContainer;

        public TogglesBar()
        {
            _gridContainer = new Grid {Margin = 0, Padding = 0, ColumnSpacing = 0};

            Content = _gridContainer;
        }

        private void Render()
        {
            try
            {
                if (ItemsSource == null || !ItemsSource.Any())
                {
                    return;
                }

                var loopIndex = 0;

                // Check if we have an icon
                if (HasIcon)
                {
                    var image = new Image {Source = "waterfront.jpg"};
                }

                foreach (var optionText in ItemsSource)
                {
                    var button = new ToggleButton
                    {
                        Text = optionText,
                        BackgroundColor = NotToggledBackgroundColor,
                        ToggledTextColor = ToggledTextColor,
                        NotToggledTextColor = NotToggledTextColor,
                        ToggledBackgroundColor = ToggledBackgroundColor,
                        NotToggledBackgroundColor = NotToggledBackgroundColor
                    };


                    button.ToggledChanged += (s, toggledStatus) =>
                    {
                        // Get all buttons
                        var allToggleButtons = _gridContainer.Children.Where(x => x is ToggleButton);

                        // Set all buttons to false
                        allToggleButtons?.ForEach(x => ((ToggleButton)x).IsToggled = false);

                        // Set this button to true
                        button.IsToggled = true;

                        // Add it to the selectedList
                        //_selectedItems.Add(button);
                    };

                    // Add the column to the grid
                    _gridContainer.ColumnDefinitions.Add(new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)});

                    // Add the button to the grid
                    _gridContainer.Children.Add(button);

                    _gridContainer.Children.Add(button, loopIndex, 0);

                    loopIndex++;

                    // Set Initial Toggle
                    if (ItemsSource.IndexOf(optionText) == InitialIndex)
                    {
                        button.IsToggled = true;
                    }

                    // Set the spacing between the toggles
                    _gridContainer.ColumnSpacing = ItemsSpacing;

                    button.OnIsToggledChanged();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);

                throw;
            }
        }

        #region Bindable Properties

        public static readonly BindableProperty HasIconProperty = BindableProperty.Create(nameof(HasIcon), typeof(bool), typeof(ToggleButton), false);

        public bool HasIcon
        {
            get => (bool)GetValue(HasIconProperty);
            set => SetValue(HasIconProperty, value);
        }

        public static readonly BindableProperty InitialIndexProperty =
            BindableProperty.Create(nameof(InitialIndex), typeof(int), typeof(TogglesBar), 0);

        public int InitialIndex
        {
            get => (int)GetValue(InitialIndexProperty);
            set => SetValue(InitialIndexProperty, value);
        }


        #region ItemSource

        private static void CustomPropertyChanging(BindableObject bindable, object oldValue, object newValue)
        {
            if (newValue != null)
            {
                ((TogglesBar)bindable).Render();
            }
        }

        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(string), default(IList), propertyChanged: CustomPropertyChanging);

        public IList<string> ItemsSource
        {
            get => (IList<string>)GetValue(ItemsSourceProperty);
            set => SetValue(ItemsSourceProperty, value);
        }

        #endregion

        public static readonly BindableProperty SelectedItemsProperty =
            BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(string), default(IList), propertyChanged: CustomPropertyChanging);

        public IList<string> SelectedItems
        {
            get => (IList<string>)GetValue(ItemsSourceProperty);
            set => SetValue(ItemsSourceProperty, value);
        }


        public static readonly BindableProperty ItemsSpacingProperty =
            BindableProperty.Create(nameof(ItemsSpacing), typeof(double), typeof(TogglesBar), 0d);

        public double ItemsSpacing
        {
            get => (double)GetValue(ItemsSpacingProperty);
            set => SetValue(ItemsSpacingProperty, value);
        }

        #region SelectedColors

        public static readonly BindableProperty ToggledBackgroundColorProperty =
            BindableProperty.Create(nameof(ToggledBackgroundColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color ToggledBackgroundColor
        {
            get => (Color)GetValue(ToggledBackgroundColorProperty);
            set => SetValue(ToggledBackgroundColorProperty, value);
        }


        public static readonly BindableProperty ToggledTextColorProperty =
            BindableProperty.Create(nameof(ToggledTextColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color ToggledTextColor
        {
            get => (Color)GetValue(ToggledTextColorProperty);
            set => SetValue(ToggledTextColorProperty, value);
        }

        #endregion


        #region UnselectedColors

        public static readonly BindableProperty NotToggledTextColorProperty =
            BindableProperty.Create(nameof(NotToggledTextColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color NotToggledTextColor
        {
            get => (Color)GetValue(NotToggledTextColorProperty);
            set => SetValue(NotToggledTextColorProperty, value);
        }


        public static readonly BindableProperty NotToggledBackgroundColorProperty =
            BindableProperty.Create(nameof(NotToggledBackgroundColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color NotToggledBackgroundColor
        {
            get => (Color)GetValue(NotToggledBackgroundColorProperty);
            set => SetValue(NotToggledBackgroundColorProperty, value);
        }

        #endregion

        #endregion
    }
}

ToggleButton

  public class ToggleButton : ContentView
    {
        private StackLayout _stackLayout;
        Label _label;

        private Image image;

        public ToggleButton()
        {
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (sender, e) => ToggleButtonTapped();

            _label = new Label()
            {
                VerticalTextAlignment = TextAlignment.Center,
                HorizontalTextAlignment = TextAlignment.Center,
                Text = Text,
            };


            HorizontalOptions = LayoutOptions.Fill;
            VerticalOptions = LayoutOptions.Fill;

            _label.GestureRecognizers.Add(tapGestureRecognizer);

            Content = _label;
        }

        public event EventHandler<bool> ToggledChanged;



        /// <summary> What happens whenever we change the toggle value </summary>
        public void OnIsToggledChanged()
        {
            _label.Text = Text;

            if (IsToggled)
            {
                _label.TextColor = ToggledTextColor;
                _label.BackgroundColor = ToggledBackgroundColor;
            }
            else
            {
                _label.TextColor = NotToggledTextColor;
                _label.BackgroundColor = NotToggledBackgroundColor;
            }
        }

        private void ToggleButtonTapped()
        {
            IsToggled = !IsToggled;
            ToggledChanged?.Invoke(this, IsToggled);
        }

       


        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(ToggleButton), default(string));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        #region SelectedColors

        public static readonly BindableProperty ToggledBackgroundColorProperty = BindableProperty.Create(nameof(ToggledBackgroundColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color ToggledBackgroundColor
        {
            get => (Color)GetValue(ToggledBackgroundColorProperty);
            set => SetValue(ToggledBackgroundColorProperty, value);
        }


        public static readonly BindableProperty ToggledTextColorProperty = BindableProperty.Create(nameof(ToggledTextColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color ToggledTextColor
        {
            get => (Color)GetValue(ToggledTextColorProperty);
            set => SetValue(ToggledTextColorProperty, value);
        }



        #endregion


        #region UnselectedColors

        public static readonly BindableProperty NotToggledTextColorProperty = BindableProperty.Create(nameof(NotToggledTextColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color NotToggledTextColor
        {
            get => (Color)GetValue(NotToggledTextColorProperty);
            set => SetValue(NotToggledTextColorProperty, value);
        }


        public static readonly BindableProperty NotToggledBackgroundColorProperty = BindableProperty.Create(nameof(NotToggledBackgroundColor), typeof(Color), typeof(ToggleButton), Color.Default);

        public Color NotToggledBackgroundColor
        {
            get => (Color)GetValue(NotToggledBackgroundColorProperty);
            set => SetValue(NotToggledBackgroundColorProperty, value);
        }

        #endregion

        #region ToggledProperty


        public static readonly BindableProperty IsToggledProperty =
            BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(ToggleButton), false,
                propertyChanged: (bindable, oldValue, newValue) =>
                {
                    ((ToggleButton)bindable).OnIsToggledChanged();
                }
            );


        public bool IsToggled
        {
            get => (bool)GetValue(IsToggledProperty);
            set => SetValue(IsToggledProperty, value);
        }



        #endregion
    }
}

Implementation

 <controls:TogglesBar
                Grid.Column="2"
                HorizontalOptions="Fill"
                InitialIndex="0"
                NotToggledBackgroundColor="WhiteSmoke"
                NotToggledTextColor="#1d1d1d"
                SelectedItems="{Binding SelectedItems}"
                ToggledBackgroundColor="#c94263"
                ToggledTextColor="WhiteSmoke"
                Visual="Default">

                <controls:TogglesBar.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>List View</x:String>
                        <x:String>Map View</x:String>
                    </x:Array>
                </controls:TogglesBar.ItemsSource>

            </controls:TogglesBar>

UI Look: You can see two implementations of the Togglebar in this UI, the bottom buttons and the MapView/ListView.

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.