Circular Button Using Xamarin (Custom Renderer)

The shift to appcompat has affected Android developers, while developing cross platform xamarin application. The first difference you would notice is the buttons are no longer having rounded corner despite assigning the radius. That is a define roadblock when you consider you need a perfect circular button.

However things aren’t actually that bad as it sounds to be. You cannot discount the power custom renderering brings in. What we need to do is write a custom Renderer and ensure shape is set to Oval. Let’s get hands dirty and do some coding.

class CircularButtonRender : Xamarin.Forms.Platform.Android.ButtonRenderer
{
private GradientDrawable _NormalState, _PressedState;

protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);

if (Control != null)
{
var button = e.NewElement;

// Create a drawable for the button's normal state
_NormalState = new Android.Graphics.Drawables.GradientDrawable();
_NormalState.SetColor(button.BackgroundColor.ToAndroid());
_NormalState.SetStroke((int)button.BorderRadius, button.BorderColor.ToAndroid());
_NormalState.SetShape(ShapeType.Oval);

_PressedState = new Android.Graphics.Drawables.GradientDrawable();
_PressedState.SetColor(button.BackgroundColor.ToAndroid());
_PressedState.SetStroke((int)button.BorderRadius, button.BorderColor.ToAndroid());
_PressedState.SetShape(ShapeType.Oval);

// Add the drawables to a state list and assign the state list to the button
var sld = new StateListDrawable();
sld.AddState(new int[] { Android.Resource.Attribute.StatePressed }, _PressedState);
sld.AddState(new int[] { }, _NormalState);
Control.SetBackground(sld);
}
}

}

 The entire source can be found in my Git project here [GitHub].

Xamarin SearchBar in Android 7

Searchbar is one of the most sought after controls in Xamarin Forms. One of the recent issues it ran into was when it was tested with Android 7. The Control just disappeared when ran in Android 7, while the same worked well in earlier version.
The solution or rather the work around for it is simple. All you need to is explicitly the height for the control. And you are all set.

Store User Credentials using Xamarin.Auth in Xamarin.Forms

If you are working on Mobile Apps, it won’t be long before you end up with a scenario to store User Account objects locally so that the user needn’t go through the pain of authenticating himself all over again, every time he logs in. One of the easiest way to do is via the cross platform Xamarin.Auth SDK  (Click here for Details).

The SDK uses Keychain Services for iOS and KeyStore Class for Android for its implementation.

Like always with any platform specific implementation, we would be using DepedencyService to define the platform specific behavior, in this case, the SDK uses KeyChain Services for iOS and KeyStore for Droid. Let’s go ahead and declare the Interface first.

public interface IAuthService
 {
 void SaveCredentials(string UserName, string Password);
 string UserName { get; }
 string Password { get; }
 }

The next step is to go ahead and implement the interface in the required platform. We will be covering Android Platform in this example.

class AuthService : IAuthService
 {
 public string Password
 {
 get
 {
 var account = AccountStore.Create(Application.Context).FindAccountsForService(Application.Context.ApplicationInfo.Name).FirstOrDefault();
 return (account != null) ? account.Properties["Password"] : null;
 }
 }
 public string UserName
 {
 get
 {
 var account = AccountStore.Create(Application.Context).FindAccountsForService(Application.Context.ApplicationInfo.Name).FirstOrDefault();
 return (account != null) ? account.Username : null;
 }
 }
 public void SaveCredentials(string UserName, string Password)
 {
 if (!string.IsNullOrWhiteSpace(UserName) && !string.IsNullOrWhiteSpace(Password))
 {
 Account account = new Account
 {
 Username = UserName
 };
 account.Properties.Add("Password", Password);
 AccountStore.Create(Application.Context).Save(account, Application.Context.ApplicationInfo.Name);
 }
 }
 }

Do not forget to register your implementation with DependencyService by decorating the namespace with Dependency Attribute.

[assembly: Xamarin.Forms.Dependency(typeof(AuthService))]

That’s it, now you can go ahead and use it in your class in the Xamarin.Form PCL.

var AuthService = DependencyService.Get<IAuthService>();
AuthService.SaveCredentials(EmailID, Password);

Simple Timer for Xamarin Forms using Device Timer

While developing your application in Xamarin that requires a Timer, you have the option to use the Device Timer. However, one of the first caveat your would notice is that while Device Class has a Device.StartTimer method, it does not exposes a Stop method, leaving it to your own class to handle it.

I started by writing an interface for my proposed Timer Class ( in my case a Countdown timer), so that I could use it for mocking for the sake of my Unit Tests. This is how my interface looked like.

public class TimerEventArgs:EventArgs
{
public TimeSpan TimeRemaining { get; set; }
}

public interface ICountdownTimer
{
void Start(TimeSpan CountdownTime);
void Stop();

event EventHandler<TimerEventArgs> Ticked;
event EventHandler Completed;
event EventHandler Aborted;
}
 
Following is how the implementation looked like.
public class CountdownTimer : ICountdownTimer
{
#region Private Variable
private bool _Stopped = false;
private TimeSpan _Second = new TimeSpan(0, 0, 1);

private readonly TimeSpan _Interval;
private TimeSpan _TimeRemaining;

private EventHandler _TickedEvent;
private EventHandler _CompletedEvent;
private EventHandler _AbortedEvent;
#endregion

#region Ctor
public CountdownTimer()
{
_Interval = _Second;
}
#endregion

#region ICountdownTimer

event EventHandler ICountdownTimer.Ticked
{
add { _TickedEvent += value; }
remove { _TickedEvent -= value;}
}

event EventHandler ICountdownTimer.Completed
{
add { _CompletedEvent += value; }
remove { _CompletedEvent -= value;}
}

event EventHandler ICountdownTimer.Aborted
{
add { _AbortedEvent += value; }
remove { _AbortedEvent -= value;}
}

public void Start(TimeSpan CountdownTime)
{
_TimeRemaining = CountdownTime;
_Stopped = false;

Device.StartTimer(_Interval, () =>
{
if (this._Stopped)
{
_AbortedEvent?.Invoke(this, EventArgs.Empty);
return false;
}

_TimeRemaining-= _Second;
_TickedEvent?.Invoke(this,new TimerEventArgs { TimeRemaining = _TimeRemaining });

_Stopped = _TimeRemaining.Duration() == TimeSpan.Zero;

if (_Stopped)
_CompletedEvent?.Invoke(this, EventArgs.Empty);

return !_Stopped;
});
}

public void Stop()
{
_Stopped = true;
}
#endregion

Missing SDK Error

One of the first and simplest warning any newbie (just like me) to Xamarin might encounter is

An unexpected error occurred trying to initialize Android Designer.
Please verify the Android SDK path and the Java Development Kit path on
Tools->Options->Xamarin->Android Settings menu. Please see the logs for more details.

You might first ensure if the SDK folders are correctly mapped. If it is and you still get the errors, it is time to fire up your SDK Manager and update the following

  1. Android SDK Tools
  2. Andriod SDK Platform-tools
  3. Andriod SDK Build-tools

You would also need to ensure your JDK is 1.8. That should take away the warning. Just in case the following warning comes, restart your visual studio and you should be all set.

IDE0006 Error encountered while loading the project. Some project features, such as full solution analysis for the failed project and projects that depend on it, have been disabled