Tag Archives: Hacks

XFHACKS-005 Button with full control on Text and Icon!

Ever came across an instance where you wished if you had more control or customization over the Text and Icon properties of your Xamarin.Forms Button? even better even without any Custom Renderers or Platform Specific code? Welcome to another lightening short post of me hacking around Xamarin.Forms elements!

Uh oh, in Xamarin.Forms?!

The default Xamarin.Forms Button has it’s own limitations for customisation, specially in the Text and Icon, there’s not much control over those properties in terms of,

  • Alignment of Text and Icon
  • Positioning of Text and Icon 
  • Default upper case Text in Android
  • Icon Image Size and Aspect Property
  • Icon Source only limited for Local Images

Talking of the Icon Source, you can only use Platform Specific Local Images for it, you cannot use Embedded Resources for it.

So I thought of making use of my own crazy imagination and hack my way around to fix all those limitations!

No custom renderers, no platform specific code and no third party libraries! Just by using pure out of the box Xamarin.Forms! 😉

Usual approach…

Now as an out of the box solution for this we could avoid using Xamarin.Forms Button totally and switch to a Xamarin.Forms Label or Image control with a Tap gesture recognizer attached to it. But then it wouldn’t actually give that nice look and feel of a button does it, specially in Android that nice ripple effects and on iOS the fade out effect on the button click is something really nice to have on your UI.

So… wait for it….

XFHACKS Receipe!

Here’s my awesome solution, we’re still going to stick to Xamarin.Forms Button button, and we’ll be laying down a Label or an Image on top of our Button view inside a Grid layout. This is actually very common hack of mine if you had gone through previous XFHACKS articles of my blog.

Yep sounds super simple, yet solves all of the issues I just mentioned above. Basically we’re constructing our own Custom Button control right from Xamarin.Forms elements, properties and behaviours without any custom renderers or platform code.

So getting into more details, here’s how we’re going to solve the above talked issues. For Alignment of the Text and Icon in the button, we are going to use the HorizontalOption of both Image and Label element that we’re placing on top of the Button. Then the Position of those elements, we shall resort to the Margin property of each. Since we’re using the Image control itself the Source property issue is automatically solved. Then as an added advantage you could also have the control over the Aspect property of the Image Icon you want to display in your button.

Now on top of all that one might wonder when you place a Label or Image on top of a Button, wouldn’t it obstruct the Clickable touch area of the Button? That’s where InputTransparent comes into rescue, passing down the touch even down to the Button straight away!

To add some cherry on top of the icing, we’re going to use the IsClippedToBounds property to crop out any areas of the inner elements of the Grid being rendered outside the View bounds of the Grid itself, so everything comes together as a single Element on UI.

Now all these comes together solving the issues that I have pointed out at the beginning! 😉

Sneak Peak!

That’s what we gonna be build yol!

Code and Run!

Behold the golden XAML code!

<!--  Button with Text and Icon  -->
<Grid
    Grid.Row="1"
    Grid.Column="0"
    HeightRequest="40"
    HorizontalOptions="Fill"
    IsClippedToBounds="True"
    VerticalOptions="Center">

    <!--  Button Control  -->
    <Button BackgroundColor="#2196F3">
        <Button.Margin>
            <OnPlatform x:TypeArguments="Thickness">
                <On Platform="Android" Value="-4,-6,-4,-5" />
                <On Platform="iOS" Value="0" />
            </OnPlatform>
        </Button.Margin>
    </Button>

    <!--  Text Label  -->
    <Label
        Margin="10,0,0,0"
        FontAttributes="Bold"
        FontSize="Small"
        HorizontalOptions="Start"
        HorizontalTextAlignment="Center"
        InputTransparent="True"
        Text="go next"
        TextColor="White"
        VerticalOptions="Center"
        VerticalTextAlignment="Center" />

    <!--  Icon Image  -->
    <Image
        Margin="0,0,5,0"
        HeightRequest="30"
        HorizontalOptions="End"
        InputTransparent="True"
        Source="{extensions:ImageResource XFHacks.Resources.rightarrowicon.png}"
        VerticalOptions="Center"
        WidthRequest="30" />
</Grid>

 

There you have it as we discussed earlier, our empty Button and on top of that the Label and the Image elements inside a Grid. As you can see the Button has some Margin value added for Android run time of, “-4,-6,-4,-5” which is to get rid of the default empty space that’s rendered around the Button at Android run time. The button will be spread across the whole Grid in background with its default HorizontalOptions=”Fill” property.

The Grid’s IsClippedToBounds=”True” property value makes sure it will cut off any inner elements that will render themselves out of the bounds of Grid. You can set whatever the HeightRequest or WidthRequest as you wish if you want to customize this even further.

Now speaking of the Label and Image you can see how I’m using the advantage of HorizontalOptions to align the elements as whatever the way I wish along with the Margin property of them, adding space wherever I wish. In here we have pushed the Label to the beginning of the Button and the Icon to the End of the Button horizontally.

Next the  InputTransparent=”True” comes in solving the touch issue, which will pass the touch action down to the Button element when the user clicks on it, giving the exact effect of a Button. The use of Image element we can now set whatever the size we wish for our Icon inside the button and adjust its Aspect property and so on.

And let’s try something else as well! Lets have a Button which has its Text and Icons aligned to the Right most corner.

<!--  Button with Text and Icon  -->
<Grid
    Grid.Row="0"
    Grid.Column="1"
    HeightRequest="40"
    HorizontalOptions="Fill"
    IsClippedToBounds="True"
    VerticalOptions="Center">

    <!--  Button Control  -->
    <Button Grid.ColumnSpan="2" BackgroundColor="#2196F3">
        <Button.Margin>
            <OnPlatform x:TypeArguments="Thickness">
                <On Platform="Android" Value="-4,-6,-4,-5" />
                <On Platform="iOS" Value="0" />
            </OnPlatform>
        </Button.Margin>
    </Button>

    <!--  Text Label  -->
    <Label
        Grid.Column="0"
        Margin="0,0,5,0"
        FontAttributes="Bold"
        FontSize="Small"
        HorizontalOptions="End"
        HorizontalTextAlignment="End"
        InputTransparent="True"
        Text="favs"
        TextColor="White"
        VerticalOptions="Center"
        VerticalTextAlignment="Center" />

    <!--  Icon Image  -->
    <Image
        Grid.Column="1"
        Margin="0,0,10,0"
        HeightRequest="30"
        HorizontalOptions="End"
        InputTransparent="True"
        Source="{extensions:ImageResource XFHacks.Resources.staricon.png}"
        VerticalOptions="Center"
        WidthRequest="30" />

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
</Grid>

 

Here’s another example where I have pushed the Image Icon to the End of the Button and the Label to be following it horizontally.

You can follow the same implementation and have our Button’s Text and Icon aligned t other Left most corner.

Now just like that you can customize all the aspects of a Button using this hack I just shared, just set up the Label and Icon with whatever the properties and customization as you wish on top of a Button. That’s it!

Fire it up!

Let me share some examples I’ve built using this awesomeness!

There you go our awesome Custom Button control running on Android, as you can see with all the preserved Button click effect! 😀

 

Since its completely out of the box Xamarin.Forms, you can run it across all the native platforms and expect the same results! 😉

Grab it on Github!

https://github.com/UdaraAlwis/XFHacks

Well then, that’s it for now. More awesome stuff on the way!

Cheers! 😀 share the love!

Advertisements

A Segmented Control in pure Xamarin.Forms!

A Segmented Control, or as some call it Grouped Button Control, or Tabbed Button Control or some even call the Rocker Control, is what I’m gonna share with yol today, built 100% from Xamarin.Forms!

Yeah such a platform specific UI element, right out of Xamarin.Forms without a single line of native code, how’s that even? Well if you’ve been following my blog for a while, you know that I’m all about pushing them limits of any given platform and achieve the impossibru! 😉

Whut whut in Xamarin.Forms?

So there’s many different interpretations of this UI elements and also different use cases. Specifically you can see this in native Tabbed Page views in both Android and iOS. And in native platforms they actually have their own Segmented button controls, that allows you to have a set of buttons in a single segment, that allows you to have a selected state, which will let you perform a certain operation, change a value or load a certain View to another element.

So when it comes to Xamarin.Forms, there’s no out of the box UI element that provides this view, unless you use Xamarin.Forms TappedPage control, in which case is impractical if you’re not in need of a Tabbed Page, or worse case in a Content element area where you absolutely can’t use a Page element.

Le Solucioano!

So here’s my solution for this, a Segmented Control in pure Xamarin.Forms, that allows you to have the same exact look and feel and behavior of a native Segmented Control, or a Tabbed Button Control or a Rocker Control or whatever. Lol

Specially no custom renderers, no native code or whatever, just simple and pure Xamarin.Forms! 😉

Sneak Peak

Here’s a sneak peak of what I built, on iOS..

And on Android..

Look at the eh, just like a native control with all the looks and feels and behaviours…

This whole awesome project is hosted up in my Github repo : https://github.com/UdaraAlwis/XFSegmentedControl 

Recipe time…

Buckle up, contains a whole bunch of me hacking around pushing the limits of Xamarin.Forms to achieve some impossibru! 😉

So first thing, we need to keep in mind the aspect of having the same look and feel of a native Segmented control, in aspect of both Android and iOS, therefore we’re going to be using a lot of platform specific properties in XAML and code behind.

We are going to have two Buttons inside a Layout, to emulate the two segmented Buttons. The layout is going to be a Xamarin.Forms Frame, since it has the property CornerRadius, which is vital to gain the curved corners appearance for iOS, and Border property, which we can use to draw the border around the element for iOS. As of Android we can disregard both of those properties. Also don’t forget about the IsClippedToBounds property which all the Layout elements has in Xamarin.Forms, allowing you to crop out of bounds elements inside the layout, which will allow us to have that curved corners in iOS without the button borders popping out of it.

So you might say as of the Button we could use a Label or something and then use a Tap Gesture to handle the click event. Nope! I like the perfection of whatever I’m building! 😉 Therefore we’re going to use actual Xamarin.Forms Button control, now hold on…

Now speaking of the Buttons, we can’t use Buttons with text inside, since the default behaviour of a button restricts the visibility of Text inside it. Therefore we’re going to use a little hack I have always used, that is placing one element over another inside a Grid view. So we are going to use a Button without text inside of it, and then a Label on top of it that represents the Text of the Segmented Button. So you’re probably worries about the Button click behaviour since we’re laying out a Label on top of it, but hello don’t worry, that’s where InputTransparent comes into rescue, passing down the touch even down to the Button straight away! So on selection of the Button we shall do the necessary changes to show the IsSelected status.

We are going to assign name identifiers to our elements in this control to handle some of the code behind magic as well, in case you wondered when you see the code! 😀

Also not to mention that we’re going to maintain properties inside the custom control, like Colors, Text, Selected Button Index properties and also an EventHandler to inform the changes of the Segment button selection.

Well that’s pretty much it, with a bit more details to be gotten into later.

XAML time…

We’re going to create a custom control elements that’s going to be independent and reusable anywhere in the project. Let’s call it SegmentedControl

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    x:Class="XFSegmentedControl.SegmentedControl"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:system="clr-namespace:System;assembly=netstandard">
    <ContentView.Content>
	
	<!--  Rest of content goes here (Next code snippet) -->
	
    </ContentView.Content>
</ContentView>

 

Now let’s get into the inside elements of our SegmentedControl, which is basically the Frame Layout that I explained before.

<Frame
    x:Name="FrameView"
    Padding="0"
    IsClippedToBounds="True">
    <!--  Platform specific customization values for the border  -->
    <Frame.HasShadow>
        <OnPlatform x:TypeArguments="system:Boolean">
            <On Platform="Android" Value="False" />
            <On Platform="iOS" Value="True" />
        </OnPlatform>
    </Frame.HasShadow>
    <Frame.CornerRadius>
        <OnPlatform x:TypeArguments="system:Single">
            <On Platform="Android" Value="0" />
            <On Platform="iOS" Value="5" />
        </OnPlatform>
    </Frame.CornerRadius>
    <Frame.HeightRequest>
        <OnPlatform x:TypeArguments="system:Double">
            <On Platform="Android" Value="50" />
            <On Platform="iOS" Value="35" />
        </OnPlatform>
    </Frame.HeightRequest>
    <!--  Platform specific customization values for the border  -->

    
    <!--  Segmented Buttons go in here (Next code snippet)  -->
    
</Frame>

 

As you can see I have added a whole bunch of platform specific customization values for Android and iOS to achieve the design we’re targeting for, such as CornerRadius and Height.

Then let’s add our Segmented Button elements…

<Grid ColumnSpacing="0">

    <!--  Tab button 1  -->
    <Grid Grid.Column="0" IsClippedToBounds="True">
        <Button
            x:Name="Tab1ButtonView"
            Margin="-2,-3,-2,0"
            Clicked="Tab1Button_OnClicked" />
        <Label
            x:Name="Tab1LabelView"
            FontAttributes="Bold"
            FontSize="Medium"
            HorizontalOptions="CenterAndExpand"
            InputTransparent="True"
            Text="Tab 1"
            VerticalOptions="CenterAndExpand" />
        <BoxView
            x:Name="Tab1BoxView"
            HeightRequest="2"
            InputTransparent="True"
            IsVisible="False"
            VerticalOptions="End" />
    </Grid>
    <!--  Tab button 1  -->

    <!--  Tab button 2  -->
    <Grid Grid.Column="1" IsClippedToBounds="True">
        <Button
            x:Name="Tab2ButtonView"
            Margin="-2,-3,-2,0"
            Clicked="Tab2Button_OnClicked" />
        <Label
            x:Name="Tab2LabelView"
            FontAttributes="Bold"
            FontSize="Medium"
            HorizontalOptions="CenterAndExpand"
            InputTransparent="True"
            Text="Tab 2"
            VerticalOptions="CenterAndExpand" />
        <BoxView
            x:Name="Tab2BoxView"
            HeightRequest="2"
            InputTransparent="True"
            IsVisible="False"
            VerticalOptions="End" />
    </Grid>
    <!--  Tab button 2  -->

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
</Grid>

 

Voila! behold the two button elements, with all the platform specific customizations, just like how I explained before, Label on top of a Button inside a Grid layout. Also you may have noticed the Margin property that I have used with “-2,-3,-2,0”, which is to stretch out the empty border line of the buttons out of the Grid so it crops out with the IsClippedToBounds property.

And the BoxView is to emulate the bottom line we have in Android look and feel of the Segmented Control.

Code-behind time…

Now this is where we’re basically going to handle all the action in our SegmentedControl!

So I’m not going to spoon feed the whole code in this blog post, since its going to be a pretty lengthy one, so I’ll be cutting out most of the repetitive code which you can easily figure out yourself or just check out on my github repo where I have committed this whole project code.

So like I explained at beginning we’re going to have a bunch of properties that are going to handle all the customization values such as Color, Text, SelectedIndex, EventHandler and so on. And then apply a whole bunch of code behind customization for platform specific look and feels, along with the handling of Segment button click event behavior.

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SegmentedControl : ContentView
{
    public static readonly BindableProperty PrimaryColorProperty
        = BindableProperty.Create(
            nameof(PrimaryColor),
            typeof(Color),
            typeof(SegmentedControl),
            Color.CornflowerBlue);

    public Color PrimaryColor
    {
        get { return (Color)GetValue(PrimaryColorProperty); }
        set { SetValue(PrimaryColorProperty, value); }
    }

    // SecondaryColorProperty

    // Tab1TextProperty

    // Tab2TextProperty

    // SelectedTabIndexProperty
    
    public event EventHandler<SelectedTabIndexEventArgs> SelectedTabIndexChanged;

    public SegmentedControl()
    {
        InitializeComponent();
    }

    /// <summary>
    /// load up the customizations and applying
    /// properties when the element has rendered
    /// </summary>
    protected override void OnParentSet()
    {
        base.OnParentSet();
        
        // Setting up platform specific properties for Android and iOS
        if (Device.RuntimePlatform == Device.Android)
        {
            Tab1LabelView.FontSize
                = Device.GetNamedSize(NamedSize.Medium, Tab1LabelView);
            Tab2LabelView.FontSize
                = Device.GetNamedSize(NamedSize.Medium, Tab1LabelView);

            Tab1ButtonView.BackgroundColor = PrimaryColor;
            Tab2ButtonView.BackgroundColor = PrimaryColor;

            Tab1BoxView.Color =
            Tab2BoxView.Color =
            Tab1LabelView.TextColor =
            Tab2LabelView.TextColor = SecondaryColor;
        }
        else if (Device.RuntimePlatform == Device.iOS)
        {
            Tab1LabelView.FontSize
                = Device.GetNamedSize(NamedSize.Small, Tab1LabelView);
            Tab2LabelView.FontSize
                = Device.GetNamedSize(NamedSize.Small, Tab1LabelView);

            Tab1ButtonView.BackgroundColor =
            Tab2ButtonView.BackgroundColor = PrimaryColor;

            FrameView.BorderColor =
            Tab1LabelView.TextColor =
            Tab2LabelView.TextColor = SecondaryColor;
        }

        Tab1LabelView.Text = Tab1Text;
        Tab2LabelView.Text = Tab2Text;

        // setting up default values
        SelectTab1();
        SelectedTabIndex = 1;
        SendSelectedTabIndexChangedEvent();
    }

    private void Tab1Button_OnClicked(object sender, EventArgs e)
    {
        SelectTab1();
        SelectedTabIndex = 1;
        SendSelectedTabIndexChangedEvent();
    }

    private void Tab2Button_OnClicked(object sender, EventArgs e)
    {
        SelectTab2();
        SelectedTabIndex = 2;
        SendSelectedTabIndexChangedEvent();
    }
    
    // SelectTab1()
    
    // SelectTab2()
    
    // SendSelectedTabIndexChangedEvent()
}

 

So we PrimaryColor and SecondaryColor which handles the two main colors that is styling our SegmentedControl, which is exactly how it being used in native version of this control as well, just two simple Colors styling the whole element.

Then Tab1Text and Tab2Text property to handle the Text that needs to be displayed in the Segmented buttons.

As you can see OnParentSet (this is when the View is rendered in memory and just about to be displayed on the Page) we’re applying all the platform specific customization for the elements in our SegmentedControl. Then you can see we’re setting the Tab1 and Tab2 text properties to our Labels, which is not actually good practice, but I was too lazy to add that in the PropertyChangedEvent handler of those respective bindable properties. After that at the end you can see we’re setting the default values.

Also the SelectedTabIndexChanged EventHandler is there to notify any outside element who wants to be aware of the selected Tab in our SegmentedControl, so they can perform whatever the action based on it.

Then let me get into the SelectTab1(), SelectTab2() and SendSelectedTabIndexChangedEvent methods.

private void SelectTab1()
{
    // set up platform specific
    // properties for SelectTab1 event
    if (Device.RuntimePlatform == Device.Android)
    {
        Tab1BoxView.IsVisible = true;
        Tab2BoxView.IsVisible = false;
    }
    else if (Device.RuntimePlatform == Device.iOS)
    {
        Tab1ButtonView.BackgroundColor = SecondaryColor;
        Tab2ButtonView.BackgroundColor = PrimaryColor;

        Tab1LabelView.TextColor = PrimaryColor;
        Tab2LabelView.TextColor = SecondaryColor;
    }
}

private void SelectTab2()
{
    // set up platform specific
    // properties for SelectTab2 event
    if (Device.RuntimePlatform == Device.Android)
    {
        Tab1BoxView.IsVisible = false;
        Tab2BoxView.IsVisible = true;
    }
    else if (Device.RuntimePlatform == Device.iOS)
    {
        Tab1ButtonView.BackgroundColor = PrimaryColor;
        Tab2ButtonView.BackgroundColor = SecondaryColor;

        Tab1LabelView.TextColor = SecondaryColor;
        Tab2LabelView.TextColor = PrimaryColor;
    }
}

/// <summary>
/// Invoke the SelectedTabIndexChanged event
/// for whoever has subscribed so they can
/// use it for any reative action
/// </summary>
private void SendSelectedTabIndexChangedEvent()
{
    var eventArgs = new SelectedTabIndexEventArgs();
    eventArgs.SelectedTabIndex = SelectedTabIndex;

    SelectedTabIndexChanged?.Invoke(this, eventArgs);
}

--------------

public class SelectedTabIndexEventArgs : EventArgs
{
    public int SelectedTabIndex { get; set; }
}

 

So there you can see in SelectTab1() we’re setting up the necessary customization for the Selected state of our Segmented Button for both Android and iOS, such as the BackgroundColor, TextColor and whatnot. And then in SelectTab2() we’re doing the exact opposite customization, Button 1 -> Unselected and Button 2 -> Selected appearance.

Then in the SendSelectedTabIndexChangedEvent we’re basically broadcasting the selected Tab index of our SegmentedControl with the SelectedTabIndex property value.

Time to consume!

Let’s use this awesome SegmentedControl in our Page shall we?!!! 😀

<local:SegmentedControl
	x:Name="SegmentedControlView"
	PrimaryColor="CornflowerBlue"
	SecondaryColor="White"
	SelectedTabIndexChanged="SegmentedControlView_SelectedTabIndexChanged"
	Tab1Text="Monkeys"
	Tab2Text="Minions">
	<local:SegmentedControl.Padding>
		<OnPlatform x:TypeArguments="Thickness">
			<On Platform="Android" Value="0" />
			<On Platform="iOS" Value="10,0,10,10" />
		</OnPlatform>
	</local:SegmentedControl.Padding>
</local:SegmentedControl>

 

Easy peasy, you just set the property values such as PriaryColor, SecondaryColor and so on that we created in our SegmentedControl and do a bit of customization if you wish to 😉 like I’ve added some padding for iOS!

In case if you’re wondering how to use the SelectedTabIndexChanged, you basically subscribe to that event and perform whatever the action you desire, whether it be changing some values, or swapping some Views or whatever your requirement is!

private void SegmentedControlView_SelectedTabIndexChanged
			(object sender, SelectedTabIndexEventArgs e)
{
	if (e.SelectedTabIndex == 1)
	{
		ContentView1.IsVisible = true;
		ContentView2.IsVisible = false;
	}
	else if (e.SelectedTabIndex == 2)
	{
		ContentView1.IsVisible = false;
		ContentView2.IsVisible = true;
	}
}

 

Just like that!

Let’s fire it up!

Let’s see this beauty in action now! 😀

Here we go baby! iOS and Android running side by side…

 

Let’s change up a bit of the colors shall we!

Woot, whatever the color combination you wish! 😉

Improvement suggestions..

Well if you ask me this is not the exact implementation I used for my actual requirement, this is more of a very simple implementation of it.

But there’s many ways to improve this. One would be adding Command for the selected Tab Index changed property handling. Also add both way handling of SelectedTabIndex so that we can set the default selected Tab on the go. Specially add dynamic Tabs to our SegmentedControl in the run time without just limiting to 2 buttons. 😉

Well your imagination is the limit fellas! 😀

This whole awesome project is hosted up in my Github repo : https://github.com/UdaraAlwis/XFSegmentedControl 

Cheers! 😀 Keep on going my fellow devs!

Spread the love…

 

XFHACKS-004 Editor with a Placeholder!

Ever wanted to have a Placeholder property for your Xamarin.Forms.Editor control? Welcome to another lightening short post of me hacking around Xamarin.Forms elements to build cool stuff and get sh*t done! 😉

By Default Xamarin.Forms.Editor is a pretty boring control with not much room for customization, but is a very useful control. So I had always wondered why it didn’t have a Placeholder property like we have to the Entry control.

So I thought of build an Editor with a Placeholder by myself, without any custom renderers or native code or third party libraries. 😉

Sneak Peak!

That’s what we gonna be build yol!

XFHACKS Recipe!

So this recipe is going to be a bit advanced one, although the basic here is also going to be what we’ve been using last few XFHACK articles, the stacking of Elements on top of each other! my favorite! 😀 lol

Let me begin with the concept of Placeholder, which is a text display that is visible in any Text Editable element until the user starts typing their input, and if the user clears his input the Placeholder comes back to visibility.

In simple terms we are going to stack a Label underneath our Editor control which will act as the “Placeholder” element and then we’re going to do some external handling to make that given Label to be set visible or invisible based on users text input typing event. The first part is pretty straightforward but the second part needs more explaining I assume. To do that we’re going to make use of the awesome Triggers in Xamarin.Forms, we’re going to implement a simple TriggerAction which will react to the event of Text field change of our Editor control. So inside the trigger execution we will set the Placeholder Label to be visible or invisible.

The Golden Triggers: So we’re going to use DataTriggers of Xamarin.Forms that allows us to listen to changes in a Data Field and react up on it, in this case the changes of the Text property of our Editor control. We’ll attach the DataTriggers to the Label and bind them to the Editor.Text property, then reacting on that our TriggerAction will hide or visible the Placeholder Label.

How easy is that eh!

Code!

Let’s start off by implementing our awesomely simple TriggerAction which will be handling the event of Editor’s text field change.

/// <summary>
/// A simple trigger to change a
/// View's visibility dynamically
/// </summary>
public class VisibilityTriggerAction
			: TriggerAction<View>
{
	public bool IsViewVisible { get; set; }

	protected override void Invoke(View sender)
	{
		sender.IsVisible = IsViewVisible;
	}
}

 

So we have a TriggerAction which can be reused anywhere to set a given View’s Visibility on demand, the reason I made it as a “View” type is exactly for the reason of reusability. So inside our Trigger we will be changing the value of IsViewVisible property to change the visibility of the Placeholder Label.

Behold the golden XAML code!

<!--  Editor with a Placeholder  -->
<Grid
      BackgroundColor="#b3ddff"
      HeightRequest="100"
      HorizontalOptions="Center"
      WidthRequest="250">

      <Label
            InputTransparent="True"
            Text="Type anything here..."
            TextColor="Gray">
            <Label.FontSize>
                  <OnPlatform x:TypeArguments="x:Double">
                        <On Platform="Android" Value="17" />
                        <On Platform="iOS" Value="17" />
                        <On Platform="UWP" Value="15" />
                  </OnPlatform>
            </Label.FontSize>
            <Label.Margin>
                  <OnPlatform x:TypeArguments="Thickness">
                        <On Platform="Android" Value="5,11,0,0" />
                        <On Platform="iOS" Value="4,9,0,0" />
                        <On Platform="UWP" Value="11,5,0,0" />
                  </OnPlatform>
            </Label.Margin>
            <Label.Triggers>
                  <!-- the DataTriggers 
                           reacts to Editor.Text changes -->
            </Label.Triggers>
      </Label>
      <Editor
            x:Name="editor"
            BackgroundColor="Transparent"
            TextColor="Black" />

</Grid>

 

There you have the Editor and the Label stacked on top of each other acting like a Placeholder for the Editor. Something important to note here is that, you can see the Margin property being set up in a bunch precise values, this was to align the Label’s text field with the text field of the Editor, so that they superpose each other nicely, which in returns gives the exact look and feel of a Placeholder property. 😉 In addition to that I have very carefully adjusted the default FontSize of the Label to match to the Editor’s! Smart eh!

So with that note, if you want to customize the Editor’s FontSize or Font itself, you need to make sure to do the similar changes accordingly to the underlying Label’s property to match the same appearance.

Now here’s the important bit, the golden Trigger. So we’re going to attach two DataTriggers, one for listening to the Editor.Text property’s null value instance (this is to be safe of null values in certain different platforms) and the other is for Editor.Text.Length property value changes. Based on those two instances we’re activating our Triggers accordingly with passing in the IsViewVisible value to it.

So here are the XAML of the DataTriggers we just spoke about, which you should plug into the above code!

<!--  the DataTriggers reacts to Editor.Text changes  -->
<DataTrigger
      Binding="{Binding Source={x:Reference editor}, Path=Text.Length}"
      TargetType="Label"
      Value="0">
      <DataTrigger.EnterActions>
          <triggers:VisibilityTriggerAction IsViewVisible="True" />
      </DataTrigger.EnterActions>
      <DataTrigger.ExitActions>
          <triggers:VisibilityTriggerAction IsViewVisible="False" />
      </DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger
      Binding="{Binding Source={x:Reference editor}, Path=Text}"
      TargetType="Label"
      Value="{x:Null}">
      <DataTrigger.EnterActions>
          <triggers:VisibilityTriggerAction IsViewVisible="True" />
      </DataTrigger.EnterActions>
      <DataTrigger.ExitActions>
          <triggers:VisibilityTriggerAction IsViewVisible="False" />
      </DataTrigger.ExitActions>
</DataTrigger>

 

There you have it, we’re binding our DataTriggers to the Editor’s Text property according to the two instances we discussed of, and setting the VisibilityTriggerAction‘s value to hide or visible our Placeholder Label.

Now as usualy could also move that whole piece of XAML to a separate XAML file, so that you could set it up as a reusable Control in your project! 😉

Pretty straight forward eh!

Fire it up!

 

There you have it running on Android, iOS and UWP like a charm! 😀

Grab it on Github!

https://github.com/UdaraAlwis/XFHacks

Well then, that’s it for now. More awesome stuff on the way!

Cheers! 😀 share the love!

XFHACKS-003 Editor with a Border!

Ever wanted to have a Border around your Xamarin.Forms.Editor control? Welcome to another lightening short post of me hacking around Xamarin.Forms elements!

Sneak Peak!

That’s what we gonna be build yol!

XFHACKS Recipe!

The default Xamarin.Forms.Editor control is a very dull and simple control which doesn’t have much of customization properties of its own. In this case the Editor doesn’t even have a proper border around it that explicitly shows the edge of the element. So here we’re going to look into how to add a nice Border around Editor in Xamarin.Forms without any custom renderers or 3rd party libraries!

We all know the Frame control, which has a nice Border property, and also CornerRadius property allowing us to control the curves of the corner edges of it. This is the simple magic we’re going to use here. We’re going to wrap our Editor inside this Frame control. 😀

How simple and easy is that eh!

Code!

Behold the golden XAML code!

<!--  Editor with a Border Control  -->
<Frame
	Padding="5"
	CornerRadius="8"
	HasShadow="True"
	OutlineColor="#2196F3">
	<Editor BackgroundColor="Transparent" TextColor="Black" />
</Frame>

 

So there we go as we discussed the Frame is wrapping around the Editor control. So the Frame has been configured with CornerRadius property so we can have some nice round corners. Then the Padding has been reduced to 5 so we have less space between the border and the Editor view, this you may change as you wish. 😉

HasShadow property is something you could change as you wish, which you should keep in mind, behaves differently on iOS and Android.

Now just to add something extra, imagine if you wanted to have the whole background with a certain color for the given Editor, this is how simple it is!

<!--  Editor with a Border Control  -->
<Frame
	Grid.Row="4"
	Padding="5"
	BackgroundColor="#7fc5ff"
	CornerRadius="8"
	HasShadow="False">
	<Editor BackgroundColor="Transparent" TextColor="Black" />
</Frame>

 

We simply add the BackgroundColor property of the Frame and then you set the HasShadow to false so it doesn’t show up Border Color just for the kicks of it. 😀 So just like that you could easily customize this as you wish!

 Important: You could also move that whole piece of XAML to a separate XAML file, so that you could set it up as a reusable Control in your project! 😉

Fire it up!

There you have it running on Android and iOS like a charm!

Let me type something inside our “cool” Editor…

 

Grab it on Github!

https://github.com/UdaraAlwis/XFHacks

Well then, that’s it for now. More awesome stuff on the way!

Cheers! 😀 share the love!

XFHACKS-002 Button with an Icon!

Ever wanted to have an Icon element attached to a Xamarin.Forms.Button control? Welcome to another lightening short post of me hacking around Xamarin.Forms elements!

No custom renderers, no platform specific code and no third party libraries! Just by using pure out of the box Xamarin.Forms! 😉

Sneak Peak!

That’s what we gonna be build yol!

Now for something like that you’re going to assume we need some custom renderers or platform specific code or third party library use, but no no no! not on my watch! 😀

XFHACKS Recipe!

In this recipe we’re going to use the same concept that we used in the XFHACKS-001 article, stacking Elements on top of each other using Xamarin.Forms Grid Layout. So here we’re placing an Image on top of a Button.

Now you might wonder wouldn’t that void the touch event of the Button, since the Image will be covering a part of the Button touch area? Now that’s where the magic property called InputTransparent comes into play. Using this property we can disable the touch input interaction for any given View and pass it down to the next child underneath. 😀

Code!

Behold the golden XAML code!

<!--  Button with an Icon Control  -->
<Grid
	Grid.Row="1"
	HorizontalOptions="FillAndExpand"
	WidthRequest="200">

	<!--  Button Control  -->
	<Button
		Grid.Column="0"
		Grid.ColumnSpan="2"
		BackgroundColor="#2196F3"
		HorizontalOptions="FillAndExpand"
		Text="Click me!"
		TextColor="White" />

	<!--  Icon Image  -->
	<Image
		Grid.Column="1"
		Margin="0,0,10,0"
		HeightRequest="25"
		HorizontalOptions="End"
		InputTransparent="True"
		Source="{local:ImageResource
			XFHacks.Resources.dropdownicon.png}"
		VerticalOptions="Center"
		WidthRequest="25" />

        <Grid.RowDefinitions>
          <RowDefinition>
               <RowDefinition.Height>
                    <OnPlatform x:TypeArguments="GridLength">
                         <On Platform="Android" Value="50" />
                         <On Platform="iOS" Value="40" />
                         <On Platform="UWP" Value="40" />
                    </OnPlatform>
               </RowDefinition.Height>
          </RowDefinition>
        </Grid.RowDefinitions>
	<Grid.ColumnDefinitions>
		<ColumnDefinition Width="*" />
		<ColumnDefinition Width="35" />
	</Grid.ColumnDefinitions>
</Grid>

There you have it just like we discussed, inside the Grid we have a Button, and on top of that we have an Image, with our magical property InputTransparent set to true, which disables the touch events of the Image redirecting them on to the Button itself. So by this the whole Image and Button works as a single Button control.

I have given a little padding to the Image, so that the icon doesn’t corner itself in the Button. The Image has a fixed width and height of 25 units, and its set to the second column of the Grid, whereas the Button spreads across two columns filling up the entire space of the Grid. Thereby you can set any fixed size to the Grid itself or let it Fill up whatever the parent container its holding.

 Important: You could also move that whole piece of XAML to a separate XAML file, so that you could set it up as a reusable Control in your project! 😉

Pretty straight forward eh!

Fire it up!

  

There you have it running on Android, iOS and UWP like a charm!

Grab it on Github!

https://github.com/UdaraAlwis/XFHacks

Well then, that’s it for now. More awesome stuff on the way!

Cheers! 😀 share the love!

XFHACKS-001 Picker with an Icon!

Ever wanted to have an Icon element attached to a Xamarin.Forms.Picker control? Then you’re at the right place. Welcome to another lightening short post of me hacking around Xamarin.Forms elements!

Sneak Peak!

That’s what we gonna be build yol!

XFHACKS Recipe!

Usually you would think you need to implement a Custom Renderer to get this done or use a third party control! I say NO! NO! NO!

You can easily do this right from Xamarin.Forms without any native coding or 3rd party library, let me explain.

In a Xamarin.Forms Grid layout we could place Elements on top of each other, using this simple advantage, we’re going to place an Image as an icon under a Picker control, and of course we’ll be setting the Background color of the Picker to Transparent! 😉 Simple right?!

Code!

Behold the golden XAML code!

<!--  Picker with an Icon Control  -->
<Grid
     Grid.Row="1"
     HorizontalOptions="Center"
     WidthRequest="200">

     <!--  Icon Image  -->
     <Image
          Grid.Column="1"
          HeightRequest="25"
          HorizontalOptions="End"
          Source="{local:ImageResource XFHacks.Resources.dropdownicon.png}"
          VerticalOptions="Center"
          WidthRequest="25" />

     <!--  Picker Control  -->
     <Picker
          Title="Select a Monkey"
          Grid.Column="0"
          Grid.ColumnSpan="2"
          BackgroundColor="Transparent">
          <Picker.ItemsSource>
               <x:Array Type="{x:Type x:String}">
                    <x:String>Baboon</x:String>
                    <x:String>Capuchin Monkey</x:String>
                    <x:String>Blue Monkey</x:String>
                    <x:String>Squirrel Monkey</x:String>
                    <x:String>Golden Lion Tamarin</x:String>
                    <x:String>Howler Monkey</x:String>
                    <x:String>Japanese Macaque</x:String>
               </x:Array>
          </Picker.ItemsSource>
     </Picker>

     <Grid.RowDefinitions>
          <RowDefinition>
               <RowDefinition.Height>
                    <OnPlatform x:TypeArguments="GridLength">
                         <On Platform="Android" Value="50" />
                         <On Platform="iOS" Value="35" />
                    </OnPlatform>
               </RowDefinition.Height>
          </RowDefinition>
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="25" />
     </Grid.ColumnDefinitions>
</Grid>

 

There you have it just like we discussed in the recipe, we have placed our Picker control on top of the Image control, and we’re using a Grid to bring all of this together. If you look closely, we are using two columns, the Picker is spread across both columns, and the Icon Image is only added to the last column, with a fixed width of 25 units, thereby aligning the Icon to the right most corner of the Picker from underneath it. 😀

You can set the WidthRequest to whatever the value you prefer. And as of Platform specific values we’re setting the Grid Height accordingly to the best appearance of Android and iOS separately, you’re in full liberty to change them as you wish. 

Important: You could also move that whole piece of XAML to a separate XAML file, so that you could set it up as a reusable Control in your project! 😉

Pretty straight forward eh!

Fire it up!

 

There you have it running on Android and iOS!

Grab it on Github!

https://github.com/UdaraAlwis/XFHacks

Well then, that’s it for now. More awesome stuff on the way!

Cheers! 😀 share the love!

Welcome to XFHACKS Series!

Hello humans, welcome to my XFHACKS series, where I share my experience on hacking around the Xamarin.Forms environment and pushing the limits of it to get sh*t done, in all kinds of unexpected and creative ways! 😀

Specially I’m going to share my experience on implementing beautiful UI elements right from Xamarin.Forms, without any native implementations. The majority misconception is that in order to implement complex or highly customized UI elements with Xamarin.Forms, you often need to use a third party library or create custom renderers and do native customization, every single time!

I’m here to prove them wrong! There’s so many ways to implement complex and beautiful UI elements right from Xamarin.Forms out of the box without the need of any native renderers or third party libraries! 😀

Stay tuned fellas! Awesome stuff on the way!

Although I’m thinking of renaming the series name to HACKXAMFORMS though instead of XFHACKS!

Meh! I’ll think about it later! 😛