Saturday, October 24, 2015

I now work at tretton37!

Sometimes you need to do something new in life. And when the best company in the world gives you an opportunity to be a part of their awesomeness, you just don't say no.

I now work at tretton37 (1337), still doing Xamarin stuff of course! Check it out at www.tretton37.com

Have a great day!

Tuesday, October 6, 2015

FontAwesome using Xamarin Forms and iOS

This is the same post as the one for Android, except this one is for iOS. I didn't really plan to write this one since the same info can be found https://blog.xamarin.com/custom-fonts-in-ios/. However, I got some comments about the previous post being incomplete, so I guess I have to complete myself.

Read this one first to get the background - http://www.johankarlsson.net/2015/09/fontawesome-using-xamarin-forms-and.html

I also moved the source to github since I might be adding stuff to it as I go along. Find it under johankson/awesome.

Here we go!

Download the font

Download the FontAwesome font and drop it in your Resource folder for the iOS project. Remember to change the "Copy to output directory" to "Always", otherwise you'll get a null reference exception.

Edit the info.plist file

In the root of your iOS project you'll find a file called info.plist. We need to add stuff to it by editing the file using a text editor. If you simply double click it then Xamarin Studio (or Visual Studio) will open a GUI for it. We don't want that. I recommend Sublime Text for all you text editing needs.


Add a key named UIAppFonts followed by an array. One entry in the array should point to the font, in this case the fontawesome.ttf. If you have multiple fonts just add more entries. Make sure you add the complete path if you add the font to a folder.

Edit the XAML

Add a FontFamily attribute to what ever control you'd like display an icon through. The FontFamily attribute will be ignored on Android so you still need the custom renderer covered in the last blog post. The XAML is from the file MyPage.Xaml in the Forms project.

The result

As expected, we see some FontAwesome icons. 



Extras

Remember that you can adjust the size and color by using the FontSize and TextColor properties. You can also add icons to buttons.

    <Button Text="&#xf041;" FontSize="40" FontFamily="FontAwesome" />

Summary

So you see that iOS is simpler than Android when it comes to using custom fonts. I also know at the time of writing I haven't created a Windows Phone solution yet. I will as soon as time permits.

Tuesday, September 29, 2015

FontAwesome using Xamarin Forms and Android

FontAwesome is, well, awesome... And be warned, this is kind of a hack.

EDIT: Here's the iOS version, but please read this post first anyhow.

On Android, it's a bit of a hassle use FontAwesome. This blog post is about how to use Font Awesome in the simplest way possible. It's as easy as using a Label once set up.

The hack is simple. We use a custom renderer that looks at the Label in question, determines if there is one character in the text field and if that character has the value of 0xf000 or higher. If so, we replace the font with FontAwesome.

Since the icons all begin at 0xf000 or higher, the custom renderer will make sure that the correct font is used.

The first label in the example below will simply print out the text. The second label will show a map marker icon using a single unicode character and the third references a local static object that maps all the icons to a friendly name. The static object is in the sample project.

            <!-- Business as usual -->
            <Label Text="Just Normal Text" />

            <!-- A Map marker using a single character -->
            <Label Text="&#xf041;" FontSize="40" />

            <!-- Using a resource -->
            <Label Text="{x:Static local:FontAwesome.FAPhone}" FontSize="40" />


This will result in the following screen.



Here's how you do it.

Download the font

Download the FontAwesome font and drop it in your Asset folder for the Droid project. Don't forget to check that the build type is set to AndroidAsset.

Create a custom renderer

The magic goes here. In the Droid project, create a custom renderer that looks like this.

[assembly: ExportRenderer(typeof(Label), typeof(AwesomeRenderer))]

namespace Awesome.Droid
{
    public class AwesomeRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            var label = (TextView)Control;

            var text = label.Text;
            if(text.Length > 1 || text[0] < 0xf000)
            {
                return;
            }

            var font = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, "fontawesome.ttf");
            label.Typeface = font;
        }
    }
}

Summary



Friday, August 28, 2015

Extending the ListView to make it clickable

The problem

The ListView is a fantastic control to use in Xamarin Forms. It has one big drawback, however and that is that if you navigate away from a selected item in the list and then navigate back, the same item is still selected and nothing happens when you tap it again.

The solution

We want to add a new command to the ListView and we start by adding a new class that inherits from the original ListView control. I usually create a folder called "Controls" in the Forms PCL and put stuff I want to use in the XAML in there.

   public class ListView : Xamarin.Forms.ListView
    {
        public static BindableProperty ItemClickCommandProperty = 
            BindableProperty.Create<ListView, ICommand>(x => x.ItemClickCommand, null);

        public ListView()
        {
            this.ItemTapped += this.OnItemTapped;
        }


        public ICommand ItemClickCommand
        {
            get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
            set { this.SetValue(ItemClickCommandProperty, value); }
        }


        private void OnItemTapped(object sender, ItemTappedEventArgs e)
        {
            if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e))
            {
                this.ItemClickCommand.Execute(e.Item);
            }

            this.SelectedItem = null;
        }
    }


The key here is the ItemClickCommand property. This will be the command that gets executed when we tap on an item. We also listen to the OnItemTapped event and the magic goes here by simply setting the SelectedItem to null again, allowing for the item to be tapped again.

Enter a ViewModel

Since MVVM is the way to go we need a view model. We are omitting the INotifyPropertyChanged stuff to keep it simple. What we have is an ObservableCollection of Duck objects that simple has a property called Name. We also define a command where we put the code that we want to execute when an item is tapped. In this case we navigate to a new page that simply displays the name of the duck. In the real world you should use IoC and also create a view model for the Duck view.

    // INotifyPropertyChanged implementation omitted - use fody!
    public class MainViewModel
    {
        public MainViewModel()
        {
            Ducks = new ObservableCollection<Duck>()
            {
                    new Duck() { Name = "Bob" },
                    new Duck() { Name = "Tommy" },
                    new Duck() { Name = "Donald" }
            };
        }

        public INavigation Navigation { get; set; }

        public ObservableCollection<Duck> Ducks
        {
            get;
            set;
        }

        public Command<Duck> DuckSelected
        {
            get
            {
                return new Command<Duck>(async (d) =>
                    {
                        var duckView = new DuckView();
                        duckView.LoadData(d);
                        await Navigation.PushAsync(duckView);
                    });
            }
        }

    }

    public class Duck
    {
        public string Name { get; set; }
    }

And the View 

This binds it all together. We assign the source of items from our view model as well as the command that we want to execute when an item is clicked.

xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:FancyList.Controls;assembly=FancyList"
             x:Class="FancyList.MainView" Padding="20">
    <ContentPage.Content>
        <local:ListView ItemsSource="{Binding Ducks}" ItemClickCommand="{Binding DuckSelected}">
            <ListView.ItemTemplate>
                <DataTemplate>
                      <ViewCell>
                        <ViewCell.View>
                              <Label Text="{Binding Name}" />
                          </ViewCell.View>
                      </ViewCell>
                </DataTemplate>
             </ListView.ItemTemplate>     
        </local:ListView>

    </ContentPage.Content>
</ContentPage>

Code behind

We also need to set the BindingContext in the code behind for the view. There are several navigation patterns out there and in this sample we take the easy path by simply passing in the Navigation object from the page (view) itself.

    public partial class MainView : ContentPage
    {
        public MainView()
        {
            InitializeComponent();

            var viewModel = new MainViewModel();
            viewModel.Navigation = this.Navigation;

            BindingContext = viewModel;
        }
    }

Summary

It's easy to extend controls in Xamarin Forms. This sample does however omit a lot of good practices like IoC and Fody. 

Resources

Tuesday, August 25, 2015

Using iOS standard icons in Xamarin Forms

Have you ever wished for using the standard iOS icons in the toolbar for Xamarin Forms applications? Then you are reading the correct blog post. If not, then you are in the wrong place.

The problem

We want to utilize the built in icons for iOS in our Xamarin Forms application to create something like the image below.



The solution

The good news is that is isn't really that complicated. Simply create a custom renderer and add some behavior to the NavigationRenderer.

First, the Xaml

The definition of our view looks like this.

xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    Title = "Welcome"
    x:Class="Test.MyPage">

    <ContentPage.ToolbarItems>
        <ToolbarItem Name="Add" />
        <ToolbarItem Name="Camera" />
    </ContentPage.ToolbarItems>

    <ContentPage.Content>
        <Label Text="Wow, that's cool!" HorizontalOptions="Center" VerticalOptions="Center" />
    </ContentPage.Content>

</ContentPage>


The key part here is to name your ToolbarItems to something useful and something that we can reference in the custom renderer. You also might want to make sure that the name works on Android and Windows Phone since those platforms won't be affected by this change.

Then the renderer

Being a swede, I have trouble saying the word Renderer... Rendererrerr... Anyhow, this is what it looks like in code. The key is to look at the title for each UIBarButtonItem and replace the entire button with a new one. So we first define a new list to hold our new buttons and then recreate them, one by one to finally assign the new list to the NavigationItem.

The renderer goes in the iOS project since it's iOS specific.

[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationRenderer))]

namespace ToolbarApp.iOS.Renderers
{
    public class CustomNavigationRenderer : NavigationRenderer
    {

        public override void PushViewController(UIKit.UIViewController viewController, bool animated)
        {
            base.PushViewController(viewController, animated);

            var list = new List<UIBarButtonItem>();

            foreach (var item in TopViewController.NavigationItem.RightBarButtonItems)
            {
                if(string.IsNullOrEmpty(item.Title))
                {
                    continue;
                }

                if (item.Title.ToLower() == "add")
                {
                    var newItem = new UIBarButtonItem(UIBarButtonSystemItem.Add)
                    {
                        Action = item.Action,
                        Target = item.Target
                    };
                    
                    list.Add(newItem);
                }

                if (item.Title.ToLower() == "camera")
                {
                    var newItem = new UIBarButtonItem(UIBarButtonSystemItem.Camera)
                        {
                            Action = item.Action,
                            Target = item.Target
                        };

                    list.Add(newItem);
                }

                TopViewController.NavigationItem.RightBarButtonItems = list.ToArray();
            }
        }
    }
}


Summary

It's pretty simple to utilize platform specific stuff in Forms and you should do that in order keep that native feeling. The key to success is Custom Renderers. Learn to use them and you'll excel in all parts of your life!

Resources

The original post from the Xamarin Forum. Thanks goes to Torben Kruse for initially answering this question.

A sample project for trying it out without coding a line.

Friday, August 21, 2015

Roboto Condensed Bold in Forms (iOS)

The last few days have been spent in pixel perfect land. I've done some fine tuning of a clients forms layouts that of course includes a bunch of custom fonts. I've started out with making sure that the iOS design is correct and we'll move on to Android and WP in another post perhaps.

This post is about a specific issue and that issue is how the naming of the font isn't all that matters.

Short version

Ttf-files only contain one weight. If you bold a regular version of a font it will be calculated bold and not the true bold since that one is contained in another file. To get the real bold, you need to reference the ttf-file containing the bold weight.

Start off here for the longer version

To get a grip of how to use custom fonts, please check out the Xamarin documentation at http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/fonts/ and also a post from Mike James that can be found here: https://blog.xamarin.com/custom-fonts-in-ios/

So what's the problem?

To summarize the usage of custom fonts loaded from a ttf-file on iOS, all described in the links above.

  • Add the ttf-file to the Resource folder - make it a Bundled Resource and Copy Always
  • Edit the info.plist to include the font
And then to use the font we do something like

<Label FontFamily="Roboto Condensed" Text="Very custom" />

To find out the FontFamily name to use, you open up the ttf-file in Windows by simply double clicking it and you'll find it. Since my client is a client, they wanted to use a different typeface for the bold text. No problem, I shouted and downloaded the bolder typeface perfectly named Roboto Condensed Bold.

I then opened the ttf file in windows to check out the name and it was named exactly the same. Wait what? How do I then distinguish between them?

It turns out that the Bold font has the same name and will be used if you set FontAttributes="Bold".

<Label FontFamily="Roboto Condensed" Text="Very custom" FontAttributes="Bold" />

And if you use the above without importing the "Roboto Condensed Bold" font it will Bold the regular font.

Still, what's the problem?

Really, nothing when I come to think of it. TrueType only supports one weight per file from what I understand and that's what I've missed in the past. I just thought that a font is a font and all is included within. :)

Also, if you only supply the regular weight and bold it, it would be some kind of calculated boldness instead of the real bold font that is meant to be used.

Extra material

Instead of using the FontAttributes that only supports Bold, Normal and Italic you can specify what font you'd like to us in the Font-attribute. For example, If I want to use Roboto Condensed Light I must specify the font name like this:

<Label FontFamily="Roboto Condensed" Text="Very custom" Font="RobotoCondensed-Light" />


How would I know what font names that are available for a font family? I use the following line of code on iOS to find out. 

var f =  UIFont.FontNamesForFamilyName("Roboto Condensed");

Summary

Make sure you reference all the weights you want and if they have the same name you only have to change the FontAttributes to select the font you wish for. But be careful and check that you actually get the weight you want since it would still bold a regular font instead of picking the correct one if you miss something along the way.

Resources

TrueType on Wikipedia - https://en.wikipedia.org/wiki/TrueType

Wednesday, August 19, 2015

Different images for selected and unselected using Xamarin Forms Tab Bar

This is just a simple hack for iOS using Xamarin Forms and icons for a TabbedPage.

Problem definition

In Xamarin Forms, the icon of the tab bar is fetched from what ever image you reference in the Icon property of the page added to the TabbedPage. This image is grayed out if unselected and filled in with the defined color when selected.
However, sometimes you want to display a different image if unselected or selected and there is no build in way to specify this nicely.

Solution

The solution is a small hack. Simply add event handlers to the Appearing and Disappearing events and reset the images to your liking.

         var activeImage = "active";
            var inactiveImage = "inactive";

            var tab1 = new AnotherPage();
            tab1.Title = "Check in";
            tab1.Icon = new FileImageSource() { File = activeImage };
            tab1.Appearing += (s, a) => tab1.Icon = new FileImageSource() { File = activeImage };
            tab1.Disappearing += (s, a) => tab1.Icon = new FileImageSource() { File = inactiveImage };



Summary

Should it be done? Probably not, but if your out of options (that is your customer insist of doing it in such way) then this is an option.

Also worth noting is that the images will flicker if the debugger is attached. There is no visible delay when running it in release.

Thursday, July 2, 2015

2015 MVP Award from Microsoft

Thank you Microsoft! I'm proud and honored to receive the 2015 years MVP Award in the .NET category! Great start to my vacation!

https://mvp.microsoft.com/en-us/mvp/Johan%20Karlsson-5001458

Still got some work to do with the profile page. But for now, it's vacation and the Peace & Love music festival in Borlänge that needs my attention for a few days!

Monday, June 8, 2015

Building the Swiper control - Part 2 (Android)

This is part two in a three-part series about the Swiper control. The first part can be read here, if you are new to custom control/renderers in Xamarin I suggest you read it first since I'll skip the parts that the renderers have in common.


Why didn't I just use the native controls?

I've been getting some comments about the iOS and Android implementation for this, stating that I could have done this a lot simpler by using the native controls (the ViewPager and the UICollectionView). This is perfectly true, but it wasn't the purpose why I created the control.

The reasons I choose to do it the way I did was

  • I originally planned to add custom graphic effects
  • I wanted to see if I could make it perfectly fluid on my own
Having that said, I might convert the control to use the ViewPager and the UICollectionView and create another experimental Swiper as separate control. I got lazy for the WP implementation of the renderer and used a Panorama. So I'm kind of in between the two ways to do this.

So what's the theory behind the Droid renderer?

I went even more back to basic this time. I decided to juggle pure bitmaps and override the Draw(...) method of the renderer. This means we are doing pure rendering on demand of the entire control. 

If we start from the top, you'll see that this time, the renderer inherits from ViewRenderer where View is the thin wrapper for an Android View which is the most basic building block for an Android GUI thingy. View itself inherits from java.lang.Object so it's pretty much bare metal from here on.

   public class SwiperRenderer : ViewRenderer<Swiper, View>

As with the iOS version we need to override a few methods to get going
  • OnElementChanged
  • OnElementPropertyChanged
  • Draw
  • OnTouchEvent

OnElementChanged

The first one being OnElementChanged which is called by Xamarin Forms when it's time to create a platform specific object. (I don't like to use the word Native since it implies that Xamarin isn't native). Anyhow, the method looks like this. It's way shorter than the iOS counter-part.

  protected override void OnElementChanged(ElementChangedEventArgs<Swiper> e)
  {
       base.OnElementChanged(e);
            
       UpdateSizes();

       _rootView = new View(Context);
       SetNativeControl(_rootView);
  }

The first thing we do is call UpdateSizes that simple copies size data into local variables for easier lookup later on.

  private void UpdateSizes()
   {
        if (this.Element == null)
        {
            return;
        }

        if (this.Width > 0 && this.Height > 0)
        {
            _width = this.Width;
            _halfWidth = _width / 2;

            _height = this.Height;
            _halfHeight = _height / 2;
        }
   }

Then we create the platform specific control and set it as the "Native" control. Since this is Android we need to pass the context to every corner of our code. I'm pretty sure the Android team use that as the solution to everything in life, as long as we have a context... We're fine!

At this point we have a control that will do the rendering for us.

OnElementPropertyChanged

This method is a lookalike to the iOS counterpart and I should really look into sharing some more code here by abstracting the events that go on in the renderers. All renderers have an InitializeImages method for example. I could define an interface for all common stuff and create a platform agnostic controller... Well, I didn't so we're stuck with code duplication for the time being. I didn't include the whole method in the sample below, simply the first two as an example of what it looks like.

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == Swiper.SourceProperty.PropertyName)
            {
                InitializeImages();
            }

            if (e.PropertyName == Swiper.WidthProperty.PropertyName || e.PropertyName == Swiper.HeightProperty.PropertyName)
            {
                UpdateSizes();
            }

            if (e.PropertyName == Swiper.SelectedIndexProperty.PropertyName)
            {
                // TODO Check for index overrun
                if (this.Element.SelectedIndex > 0 &&
                    _currentImageUrl != this.Element.Source[this.Element.SelectedIndex])
                {
                    _currentImageUrl = this.Element.Source[this.Element.SelectedIndex];
                    InitializeImages();
                }
            }


            // Code omitted (there's more in this method)
    }

As with the iOS version, we listen for changes in properties and call the appropriate methods to handle this change. For example, if we change the source we need to reinitialize the images. If we change the width or height we need to update sizes. Those sizes are needed to render later on.

Async image downloading

I played around with a couple of different approaches to async image downloading. I ended up with the basic WebClient since it would be cool to have download progress if the images are large. Looking at the code now, I realize that it's not fully implemented yet. I registered an issue (#13) for this and hopefully I'll get something done. The downloading works but the showing the progress is not completed yet. We just draw a loading text.

We directly convert the downloaded bits into a Android Bitmap object.

      private async Task LoadWithProgress()
        {
            try
            {
                var webClient = new WebClient();
                webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;

                var bytes = await webClient.DownloadDataTaskAsync(new Uri(_url));
                _bitmap = await BitmapFactory.DecodeByteArrayAsync(bytes, 0, bytes.Length);

                if (Completed != null && _bitmap != null)
                {
                    Completed(this);
                }
            }
            catch (Exception ex)
            {
                Log.Debug("SwipeRenderer", "Exception loading image '{0}' using WebClient", _url);
            }
        }

        void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            int i = 42;
        }

Caching

The caching in the Android version is just as basic. We simply store a dictionary of string and AsyncImageLoader for now. It's the same with all three platforms and a common caching strategy is required here.

Tracking your fingers

Handling touch events is easy. Simply override the OnTouchEvent method and check what type of event is being raised. We can break down this method in three parts categorized by the action type.


  1. The user starts a touch and we get a MotionEventActions.Down. We store the start location of the X-axis of the touch position to keep for later reference.
  2. If the action is Move we calculate the offset value of the current finger position on the X-axis. Then we call Invalidate() to force a redraw of the control.
  3. When the user lets go of the image we need to check if the image has moved far enough to count as a image switch motion and in that case, what direction. If it's not a switch we still need to animate the images back into the original place.


 public override bool OnTouchEvent(MotionEvent e)
        {
            switch(e.Action)
            {
                case MotionEventActions.Down:
                    _swipeStartX = e.GetX();
                    return true;


                case MotionEventActions.Move:
                    _swipeCurrectXOffset = e.GetX() - _swipeStartX;
                    Invalidate();
                    return true;

                case MotionEventActions.Up:
                    var index = this.Element.Source.IndexOf(_currentImageUrl);
                    
                    if(Math.Abs(_swipeCurrectXOffset)>30) // TODO Add a variable for the trigger offset?
                    {
                        if(_swipeCurrectXOffset > 0 && index > 0)
                        {
                            // Left swipe
                            AnimateLeft(index);
                        }
                        else if (_swipeCurrectXOffset < 0 && index < this.Element.Source.Count() -1)
                        {
                            // Right swipe
                            AnimateRight(index);
                        }
                        else
                        {
                            AnimateBackToStart();
                        }
                    }
                    else
                    {
                        AnimateBackToStart();
                    }
                    
                    return true;

                
            }

            return base.OnTouchEvent(e);
        }

Animation of images

Each platform offers different kind of animation APIs. In this sample I've chosen to use the static ValueAnimator to animate a float value. We can take the AnimateLeft(...) method as an example. It's dead simple to use. Simply state the initial value and the end value in the ValueAnimator.OfFloat(...). Hook up events for Update (that fires every frame) and for AnimationEnd(that fires when the end result has been achieved).

For this specific function we continue to animate the current x-offset to the left and when we hit the end we set a new _currentImageUrl (that represents the center image) and reinitialize all images so the new images are displayed.

       private void AnimateLeft(int index)
        {
            var animator = ValueAnimator.OfFloat(_swipeCurrectXOffset, this.Width);
            animator.Start();

            animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs args) =>
            {
                _swipeCurrectXOffset = (float)args.Animation.AnimatedValue;
                Invalidate();
            };
            animator.AnimationEnd += (object sender, EventArgs args) =>
            {
                _swipeCurrectXOffset = 0f;
                _currentImageUrl = this.Element.Source[index - 1];
                InitializeImages();
            };
        }

Drawing

The method signature of Draw(...) looks like this.

    public override void Draw(Android.Graphics.Canvas canvas)

It passes in a single argument in the form of a Canvas object. This Canvas represents the drawable surface that we have access to. The Draw(...) method is called everytime Invalidate() is called else where in the code or when the operating system wants you to update.

The method is quite repetitive so I'll just take a sample out of it.

     // Clear the canvas
            canvas.DrawARGB(255, 255, 255, 255);

            if(_centerBitmap != null && _centerBitmap.Bitmap != null)
            {
                var dest = CalculateCentrationRect(_centerBitmap.Bitmap);
                 canvas.DrawBitmap(_centerBitmap.Bitmap, dest.Left + _swipeCurrectXOffset, dest.Top, null);
            }
            else if (_centerBitmap != null)
            {
                DrawLoadingText(canvas, 0);
            }



This is pretty much what's going on, but times three. One for each image. First we need to clear the frame from the previous stuff drawn onto it. We do that with the canvas.DrawARBG(...) call. This could easily be extended to take a background color or image instead.

Then for each image we either draw the image or draw a loading text if the image isn't downloaded yet.

Summary

You could have made this a lot simpler and perhaps I'll revisit this control and redo it. But as a learning experience it was quite fun. Feel free to steal any code! My code is your code!