Indicator Bar Position

15 posts, 0 answers
  1. DecisiveComputing
    DecisiveComputing avatar
    11 posts
    Member since:
    Mar 2015

    Posted 06 May Link to this post

    When I set HeaderPosition="Bottom", the indicator bar the denotes the selected tab still shows up at the bottom of the selected tab. Is there a way to move that to the top of the tab in this case?
  2. Nikolay Demirev
    Admin
    Nikolay Demirev avatar
    136 posts

    Posted 10 May Link to this post

    Hello Brian,

    You could try setting the ControlTemplate property to the TabViewHeaderItem. This will help you customize the header items. Here is a sample ControlTemplate from our QSF examples:
    <telerikPrimitives:TabViewHeaderItem Text="{Binding Name}" ControlTemplate="{StaticResource iconControlTemplate}" />
     
    <ControlTemplate x:Key="iconControlTemplate">
        <Grid BackgroundColor="Transparent" RowSpacing="0">
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
          </Grid.RowDefinitions>
          <Image Source="{Binding Icon, Converter={StaticResource uwpImageSourceConverter}}"
                 HorizontalOptions="Center"
                 VerticalOptions="Center"
                 WidthRequest="16"
                 HeightRequest="16"
                 Margin="0, 4, 0, 6" />
          <Label Grid.Row="1"
                 Text="{TemplateBinding Text}"
                 TextColor="{TemplateBinding IsSelected, Converter={StaticResource booleanAccentConverter}}"
                 FontSize="10"
                 HorizontalTextAlignment="Center"
                 Margin="0, 0, 0, 6" />
        </Grid>
      </ControlTemplate>


    You could download the QSF applications in the Android and iOS stores. It is called "Progress Telerik UI for Xamarin Examples".

    Regards,
    Nikolay Demirev
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. DecisiveComputing
    DecisiveComputing avatar
    11 posts
    Member since:
    Mar 2015

    Posted 10 May in reply to Nikolay Demirev Link to this post

    I have that app installed on my Droid device and it has some nice examples, but I didn't notice this.

    Also, I am mainly working from the sample Visual Studio Solution that gets installed with the product and I find going through that code to be most helpful. However, the examples in that code do not show this at all.

    Furthermore, this is not documented anywhere.

    I realize this is a new control, but I have used Telerik since its early days and have continued to use it for the document and support. So hopefully the documentation for Xamarin will be up-to-date soon?

    I am still deciding whether to upgrade to your Ultimate subscription based solely on the Xamarin controls. I like what I see, but am really struggling with the lack of documentation and examples. Meaning that the time the controls typically save me is being eaten away as I browse properties, code in JustDecompile, etc.

  4. Nikolay Demirev
    Admin
    Nikolay Demirev avatar
    136 posts

    Posted 15 May Link to this post

    Hi Brian,

    Thank you for your feedback. It is greatly appreciated. We will consider it while making improvements on our help articles. We are constantly working on improving our products and their documentation.

    The example I suggested is not the best, as it has that indicator bar removed. Excuse me for misleading you. I wanted to show you that the entire content of the headers can be customized. If you want you could place a BoxView in the ControlTemplate, which you could show and hide in order to achieve that indicator effect.

    In the same example, you could find the ControlTemplate for the items on the top of the TabView, which have that type of indicator. Here is the ControlTemplate code:
    <ControlTemplate x:Key="orangeControlTemplate">
      <Grid BackgroundColor="Transparent">
        <BoxView IsVisible="{TemplateBinding IsSelected}"
                 BackgroundColor="{StaticResource orange}"
                 VerticalOptions="End"
                 HeightRequest="2" />
        <Label Text="{TemplateBinding Text}"
               TextColor="{TemplateBinding IsSelected, Converter={StaticResource booleanOrangeConverter}}"
               HorizontalTextAlignment="Center"
               Margin="0, 0, 0, 8" />
      </Grid>
    </ControlTemplate>


    Regards,
    Nikolay Demirev
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  5. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 17 Jul in reply to Nikolay Demirev Link to this post

    Is possible get this code in C# only ?
  6. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 17 Jul Link to this post

    Hello Sebastian,

    You can learn how to make a ControlTemplate in C# here in the Xamarin.Forms documentation, as this is not a Telerik specific-implementation (it's a general Xamarin.Forms topic).

    Once you have a ControlTemplate class in your project, you can then add the children in the constructor. Here's the C# code for Nikolay's XAML in the CTOR of an example ControlTemplate class

    public class OrangeTemplate : Grid
        {
            public OrangeTemplate()
            {
                // 1-  Create the elements (note "this' is the root Grid)
                this.BackgroundColor = Color.Transparent;
     
                // the BoxView
                var bv = new BoxView
                {
                    BackgroundColor = (Color) Application.Current.Resources["orange"],
                    HeightRequest = 2,
                    VerticalOptions = LayoutOptions.End
                };
     
                bv.SetBinding(IsVisibleProperty, new TemplateBinding("IsSelected"));
     
                // the Label
                var label = new Label
                {
                    HorizontalTextAlignment = TextAlignment.Center,
                    Margin = new Thickness(0, 0, 0, 8)
                };
     
                label.SetBinding(Label.TextProperty, new TemplateBinding("Text"));
                label.SetBinding(Label.TextColorProperty, new TemplateBinding("IsSelected", BindingMode.Default, (IValueConverter)Application.Current.Resources["orangeBooleanConverter"]));
     
     
                // 2 - Add the children
                this.Children.Add(bv);
                this.Children.Add(label);
            }
        }

    An important note: The code above expects two StaticResources to be avaiable ("orange" and "orangeBooleanConverter"), which you would need to have or you'll get an exception. 

    Otherwise, set the colors and converter instance  in C#:

    // converter instance instead of resource
    label.SetBinding(Label.TextColorProperty, new TemplateBinding("IsSelected", BindingMode.Default, new OrangeBooleanConverter()));
     
    // using a color instead of resource
    BackgroundColor = Color.Orange,




    Telerik specific implementation

    With your ControlTemplate defined, you just do the following to use it:

    var tb = new TabViewHeaderItem();
    tb.ControlTemplate = new ControlTemplate(typeof(OrangeTemplate));

    Here's a complete implementation using those headers:

    MyTabView.Items.Add(new TabViewItem
    {
        Content = new Label { Text = "Label 1" },
        Header = new TabViewHeaderItem
        {
            ControlTemplate = new ControlTemplate(typeof(OrangeTemplate)),
            Text = "Tab 1"
        }
    });
     
    MyTabView.Items.Add(new TabViewItem
    {
        Content = new Label { Text = "Label 2" },
        Header = new TabViewHeaderItem
        {
            ControlTemplate = new ControlTemplate(typeof(OrangeTemplate)),
            Text = "Tab 2"
        }
    });

    Here's the result at runtime:




    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  7. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 17 Jul in reply to Lance | Tech Support Engineer, Sr. Link to this post

    Thank you Lance, i'm trying to implement your code but i'm missing this part:

    new OrangeBooleanConverter()

    Can you guide me what should go in that class ?

  8. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 18 Jul Link to this post

    Hello Sebastien,

    That converter belongs to Brian's project (the OP of this thread), it's just an IValueConverterthat returns one color if it's true or another color if it's false. You'll need to implement your own that meets your needs.

    If you're not familiar with creating an implementation of IValueConverter, its just a class that takes one object value and returns a different one. Value converters are common across all XAML frameworks (WPF, UWP, Xamarin, Silverlight, etc).

    Here's the basic structure of a value converter, to demonstrate how it works I'm converting a bool to a string message:


    public class SomeBoolToStringConverter : IValueConverter
    {
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {
          // Step 1 - 'value' is the incoming type, so you'll want to cast it. In this example, it's a bool
          var originalBoolValue = (bool)value;
                  
          // Step 2 - do some work to create the object you want to return, in this example, it's a string
          string returnableObject = "";
      
          if (originalBoolValue)
              returnableObject = "incoming value was true";
          else
              returnableObject = "incoming value was false";
      
          // Step 3 - Return the new "converted" object, in this example, it's just a string
          return returnableObject;
      }
      
      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {
          // do the opposite here. cast to a string and return a bool
          throw new NotImplementedException();
      }
    }


    In the case of setting the header color using the IsSelected value, you want to create a converter that 'converts' a bool object to a Color object.

    A primary goal of writing code is to be efficient as much as possible. With this in mind, you can write a single BoolToColorConverter that can use any color instead of a OrangeBooleanConverter that only returns orange.

    To do this, just add a couple properties to the converter class that allows you to set the color for true and the color for false.

    public class BoolToColorConverter : IValueConverter
    {
        // Expose a couple color properties and set some default values
        public Color SelectedColor { get; set; } = Color.Red;
        public Color UnselectedColor { get; set; } = Color.Black;
     
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // Then return the SelectedColorif the incoming bool value is true
            return (bool)value ? SelectedColor : UnselectedColor;
        }
     
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    Now you can use it like this this in place of OrangeBooleanConverter:

     
    label.SetBinding(Label.TextColorProperty, new TemplateBinding("IsSelected", BindingMode.Default, new BoolToColorConverter { SelectedColor = Color.Green, UnselectedColor = Color.Black }));

    Notice how I was able to set the color green when instantiating the converter instead of being stuck with a hard coded color in a converter class itself.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  9. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 18 Jul in reply to Lance | Tech Support Engineer, Sr. Link to this post

    Awesome explanation and solution, it is exactly what i was looking for :)
  10. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 08 Sep Link to this post

    Hi,

    Thank you again for the previous explanation, i'm looking for a upgrade to that solution. is it possible to also customize the background colors of the tabheader as happens with the textcolor?

  11. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 08 Sep Link to this post

    Hello Sebatien,

    Yes, you can since you have full control over the UI element itself. Let's revisit the actual custom template itself.

    There's a class named OrangeTabItemHeaderTemplate and it inherits from Grid.

    public class OrangeTabItemHeaderTemplate : Grid
        {
            public OrangeTabItemHeaderTemplate()
            {
                // 1-  Create the elements (note "this' is the root Grid)
                this.BackgroundColor = Color.Transparent;
     
                // the BoxView
                var bv = new BoxView
                {
                    HeightRequest = 2,
                    VerticalOptions = LayoutOptions.End
                };
     
                bv.SetBinding(IsVisibleProperty, new TemplateBinding("IsSelected"));
                bv.SetBinding(
                    BackgroundColorProperty,
                    new TemplateBinding(
                        "IsSelected",
                        BindingMode.Default,
                        new BoolToColorConverter
                        {
                            SelectedColor = Color.Green,
                            UnselectedColor = Color.Black
                        }));
     
                // the Label
                var label = new Label
                {
                    HorizontalTextAlignment = TextAlignment.Center,
                    Margin = new Thickness(0, 0, 0, 8)
                };
                 
                label.SetBinding(
                    Label.TextColorProperty,
                    new TemplateBinding(
                        "IsSelected",
                        BindingMode.Default,
                        new BoolToColorConverter
                        {
                            SelectedColor = Color.Green,
                            UnselectedColor = Color.Black
                        }));
     
                label.SetBinding(Label.TextProperty, new TemplateBinding("Text"));
     
                // 2 - Add the children
                this.Children.Add(bv);
                this.Children.Add(label);
            }
    }



    If yo notice, it is hard coding it's background to Transparent!   You can take the same approach you did for the BoxView's background.


    To demonstrate, let's replace the hard coded BackgroundColor with a Binding:


    // NOTE - "this" is the root Grid of the custom header
    // Commenting this out so we can set a binding for BackgroundColor instead
    // this.BackgroundColor = Color.Transparent;
     
    // NEW - We're now binding BackgroundColor to IsSelected
    this.SetBinding(BackgroundColorProperty,
        new TemplateBinding("IsSelected", BindingMode.Default,
            new BoolToColorConverter
            {
                SelectedColor = Color.Transparent,
                UnselectedColor = Color.Green
            }));


    Now, you'll see that when a tab is selected, the background color wil be Transparent and the Text will be Gree, and when it's not selected the background color is Green


    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  12. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 11 Sep in reply to Lance | Tech Support Engineer, Sr. Link to this post

    Hi Lance,

    I Implemented that solution but the tabs are now disabled, the selection action is missing.

  13. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 11 Sep Link to this post

    Hi Sebatian,

    I tested it on my end, it works as expected. However, I can see why a user would think selection is disabled.

    Essentially the color makes it appear like the selected item is not the selected it. Thus when attempting to select the tab, it doesn't do anything because it is already selected.

    To explain this better, I've recorded this 30 second video for you.


    If this isn't the case, I'll need to reproduce your problem on my end. Please reply back with the code I need:

    - The classes involved (converter, custom template)
    - The view (the TabView and the added items)

    With this I'll attempt to reproduce and see what the issue might be.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  14. Sebastián Soto
    Sebastián Soto avatar
    8 posts
    Member since:
    Jun 2017

    Posted 13 Sep in reply to Lance | Tech Support Engineer, Sr. Link to this post

    Hi Lance,

    I expected that works exactly like in your video but isn't. This is exactly how i'm making it.

     

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using Telerik.XamarinForms.Primitives;
    using Xamarin.Forms;

    namespace TelerikXamarin.Portable
    {
        public class TabPage : ContentPage
        {
            public TabPage()
            {

                RadTabView MyTabView = new RadTabView();

                MyTabView.Items.Add(new TabViewItem
                {
                    Content = new Label { Text = "Label 1" },
                    Header = new TabViewHeaderItem
                    {
                        ControlTemplate = new ControlTemplate(typeof(OrangeTemplate)),
                        Text = "Tab 1"
                    }
                });

                MyTabView.Items.Add(new TabViewItem
                {
                    Content = new Label { Text = "Label 2" },
                    Header = new TabViewHeaderItem
                    {
                        ControlTemplate = new ControlTemplate(typeof(OrangeTemplate)),
                        Text = "Tab 2"
                    }
                });

                Content = MyTabView;
                           

                //Content = new StackLayout
                //{
                //    Children = {
                //        new Label { Text = "Welcome to Xamarin Forms!" }
                //    }
                //};
            }
        }


        public class OrangeTemplate : Grid
        {
            public OrangeTemplate()
            {
                // 1-  Create the elements (note "this' is the root Grid)
                //this.BackgroundColor = Color.Transparent;
                this.SetBinding(BackgroundColorProperty,
                new TemplateBinding("IsSelected", BindingMode.Default,
                    new BoolToColorConverter
                    {
                        SelectedColor = Color.Transparent,
                        UnselectedColor = Color.Green
                    }));

                // the BoxView
                var bv = new BoxView
                {
                    BackgroundColor = Color.Orange,
                    HeightRequest = 2,
                    VerticalOptions = LayoutOptions.End
                };

                bv.SetBinding(IsVisibleProperty, new TemplateBinding("IsSelected"));

                // the Label
                var label = new Label
                {
                    HorizontalTextAlignment = TextAlignment.Center,
                    Margin = new Thickness(0, 0, 0, 8)
                };

                label.SetBinding(Label.TextProperty, new TemplateBinding("Text"));
                
                label.SetBinding(Label.TextColorProperty, new TemplateBinding("IsSelected", BindingMode.Default, new BoolToColorConverter { SelectedColor = Color.Green, UnselectedColor = Color.Black }));

                // 2 - Add the children
                this.Children.Add(bv);
                this.Children.Add(label);

                
            }


            public class BoolToColorConverter : IValueConverter
            {
                // Expose a couple color properties and set some default values
                public Color SelectedColor { get; set; } = Color.Red;
                public Color UnselectedColor { get; set; } = Color.Black;

                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    // Then return the SelectedColorif the incoming bool value is true
                    return (bool)value ? SelectedColor : UnselectedColor;
                }

                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    throw new NotImplementedException();
                }
            }

        }
        
    }

     

  15. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    419 posts

    Posted 15 Sep Link to this post

    Hi Sebastian,

    I was not able to replicate the problem using your code. I've attached the investigative application, in which I only used your code. The only difference is I renamed the class to be more appropriate (CustomTabViewHeader.cs).

    Your issue must be related to another element on the page or maybe you're not running the latest version which has the latest improvements and fixes (although I don't see any bug fixed for tab header not working in the release history).

    Is this on a particular device or across all platforms? Can you update the demo so that it replicates the issue and send me back the demo so I can investigate further.

    Lastly, I  recommend creating a new ticket or forum thread for this as the original thread created by Brian is no longer relevant to your issue.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top