04 Nov 2017
I’ve just pushed v5 of the Messaging Plugin to NuGet. The new version of the plugin has been reworked to support .NET Standard. Besides .NET Standard support, some other minor fixes/enhancements were also made. Here’s the full Change Log:
- Upgrade to .NET Standard
- Android: Update to newer Support Libraries (v25.3.1)
- Android: Fix support for formatting number using country’s default convention on API 21 and later. See
PhoneSettings.DefaultCountryIso
.
- Android: Fix HTML formatting on Android N (API 24) and later
- iOS: Improve
IPhoneCallTask.CanMakePhoneCall
on iOS to check support of url and connection to a carrier
- iOS: Fix issue with email client not appearing
- UWP: Updated to latest UWP platform
- Breaking Change: Remove Windows Store support
- Breaking Change: Remove deprecated
MessagingPlugin
facade
30 Oct 2017
Following in James Montemagno’s footsteps, I’ve now published a pre-release version of the Messaging Plugin that has been reworked to support .NET Standard to NuGet. Besides .NET Standard support, some other minor fixes/enhancements were also made (Change Log).
I hope to publish the release version of the plugin towards the end of the week.
25 May 2017
Last time around I showed how to create a Xamarin Android compound TextInputLayout
control with support for capturing user input with an associate Header
and Error
labels. This post looks at how to style the same control in Android.
Style attributes
As mentioned previously, I want all my compound controls to support a common set of attributes to create a consistent look-and-feel. Every control will have a Header
(i.e. description), Text
(i.e. value) and Error
properties. To style these attributes, we create three associated attributes in our Resources/values/attrs.xml
file to assign the styles to:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="ItcTextAppearanceLabel" format="reference"/>
<attr name="ItcTextAppearanceText" format="reference"/>
<attr name="ItcTextAppearanceError" format="reference"/>
In addition to these attributes we also associate these new style attributes with our existing ITTextInputLayout
definition in the attrs.xml:
<declare-styleable name="ITTextInputLayout" >
<attr name="android:inputType"/>
<attr name="android:maxLines"/>
<attr name="android:text"/>
<attr name="android:imeOptions"/>
<attr name="ItcLabel"/>
<attr name="ItcError"/>
<attr name="ItcTextAppearanceLabel"/>
<attr name="ItcTextAppearanceError"/>
</declare-styleable>
Notice that we don’t include the ItcTextAppearanceText
reference style in the definition. The reason being that we will re-use the already defined style attribute on the android.support.design.widget.TextInputLayout
that our ITTextInputLayout
control inherits from.
To define the default, global look-and-feel for all our controls, we also create a styles container in the attrs.xml:
<declare-styleable name="ITControls" >
<attr name="ItcTextAppearanceLabel"/>
<attr name="ItcTextAppearanceError"/>
<attr name="ItcTextAppearanceText"/>
<attr name="ItcTextInputLayoutStyle" format="reference"/>
</declare-styleable>
Widget and TextAppearance styles
With the attributes defined, we can now define a style for our compound control in the Resources/values/styles.xml
file. As our control extends the android.support.design.widget.TextInputLayout
control, it is important to first consider what style attributes is already being used so that we can associate our own styles with the existing styles. From the existing Android styles definition we see that Android widget has the following styles definition:
<style name="Widget.Design.TextInputLayout" parent="android:Widget">
<item name="hintTextAppearance">@style/TextAppearance.Design.Hint</item>
<item name="errorTextAppearance">@style/TextAppearance.Design.Error</item>
<item name="counterTextAppearance">@style/TextAppearance.Design.Counter</item>
<item name="counterOverflowTextAppearance">@style/TextAppearance.Design.Counter.Overflow</item>
<item name="passwordToggleDrawable">@drawable/design_password_eye</item>
<item name="passwordToggleTint">@color/design_tint_password_toggle</item>
<item name="passwordToggleContentDescription">@string/password_toggle_content_description</item>
</style>
The hintTextAppearance
and errorTextAppearance
is being used by the Android widget to style the label and error text. With this in mind, we can now create a style definition for our own control:
<style name="Widget.InTouch.TextInputLayout" parent="Widget.Design.TextInputLayout">
<item name="android:textColorHint">@color/accentColor</item>
<item name="hintTextAppearance">?attr/ItcTextAppearanceLabel</item>
<item name="errorTextAppearance">?attr/ItcTextAppearanceError</item>
</style>
We override the default style styles and associate them with our new common-look-and-feel style attributes that we have defined. With our control style defined, we also create the default text appearance styles to use for our common-look-and-feel:
<style name="TextAppearance.InTouch" parent="TextAppearance.AppCompat">
</style>
<style name="TextAppearance.InTouch.Label">
<item name="android:textSize">14sp</item>
</style>
<style name="TextAppearance.InTouch.Label.Error">
<item name="android:textSize">12sp</item>
<item name="android:textColor">@color/errorColor</item>
</style>
Themes
With the styles defined, we now set out to create a default Theme where we assign the default styles to the style attributes we created to create our common look-and-feel. Themes are created in a Resources/values/themes.xml
file:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="Theme.InTouch" parent="Theme.InTouch.Base">
</style>
<style name="Theme.InTouch.Base" parent="Theme.Design.Light.NoActionBar">
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryColorDark</item>
<item name="colorAccent">@color/accentColor</item>
<!-- Composites -->
<item name="ItcTextAppearanceLabel">@style/TextAppearance.InTouch.Label</item>
<item name="ItcTextAppearanceError">@style/TextAppearance.InTouch.Label.Error</item>
<item name="ItcTextInputLayoutStyle">@style/Widget.InTouch.TextInputLayout</item>
</style>
Notice that our theme associates the default text appearance with a specific style. With the theme definition in place, we can now use it our applications in Xamarin by typically assigning the Theme
property as an attribute on our startup Activity
or on the Application
instance as illustrated below:
[Application(Name = "phil.AndroidApp", Theme = "@style/Theme.InTouch")]
public class AndroidApp : Application, Application.IActivityLifecycleCallbacks
{
Control changes
With the style attributes and themes defined, we still need to enhance our control to make use of the styles defined. To cater for the styles and themes we need to change our existing control to get the style definitions and use them for changing the look-and-feel of its internal widgets:
The three different constructors cater for different scenarios of creating our compound control. The first constructor on Line 3 is typically used when I create a control programmatically. The second constructor on Line 7 is called when I define my control in a layout without specifying a style.
<intouch.controls.ITTextInputLayout
android:id="@+id/layout_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext" ...
The third constructor is called when I define my control in a layout with specifying a style:
<intouch.controls.ITTextInputLayout
style="@style/MyCustom.Style"
android:id="@+id/layout_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext" ...
Notice how the constructors call into each other and the use of the Resource.Styleable.ITControls_ItcTextInputLayoutStyle
style attribute on Line 7 that will use the style setup in our theme as the default if the user does not specify their own style for our control in a layout. Our theme is setup to use @style/Widget.InTouch.TextInputLayout
as style which makes use of the default look-and-feel style attributes to style the control.
As we are re-using the existing styles defined on the Android TextInputLayout
control, we simply have to call into the base class constructor to get these styles applied to the Error
and Hint
widgets. Feel free to browse the TextInputLayout.java source code if you want to see how this is done.
Summary
Styles and Themes in Android along with style inheritance is a really powerful tool for creating a common look-and-feel across your application. I hope this post highlighted some ways in which you can make use of this powerful functionality to create a common look-and-feel for your own compound controls.
01 May 2017
I’ve been going through some Android layouts try and remove some duplication by creating re-usable custom component controls. I’m pretty happy with how things are turning out and thought I’d share one or two of the controls. I will show how these controls can be used in vanilla Xamarin Android as well as in my favourite MVVM framework, MvvmCross.
Shared attributes
I want all my compound controls to support a common set of attributes to create a consistent look-and-feel. Every control will have a Header (i.e. description), Text (i.e. value) and Error properties. For this I define a IITComposite
interface.
All my custom compound controls will implement this interface.
Custom TextInputLayout Control
The first compound control will be used to capture text input from the user. Most of the functionality is already provided out-of-the-box via the TextInputLayout
and TextInputEditText
views of the Android.Support.Design
library.
Here’s a screen shot of of these controls in action in one of my apps:
Here’s the corresponding layout for the password field:
People familiar with MvvmCross will understand the binding syntax being used by the app:MvxLang
and app:MvxBind
attributes. The binding is what makes a MVVM framework so powerful and I’m not going to delve into the details here. From the binding syntax we can see that the Hint
, Text
and Error
properties of the views map nicely to the features required by my IITComposite
interface. It therefore makes sense for my compound view to re-use by inheriting and extending the existing TextInputLayout
control.
Control Layout
We start by defining the layout for the compound control that will be inflated in code within a Resources\layout\control_textinput.axml
file:
As the compound control inherits from TextInputLayout
, the merge
tag is being used instead of the android.support.design.widget.TextInputLayout
tag to prevent an extra instance of the control being inflated when my custom component control is included in a layout.
Control Layout Attributes
To define the set of attributes that can be set for a control in layout, you have to create a Resources\values\attrs.xml
file and include a definition for your control and its supported attributes within it.
Notice that the ITTextInputLayout
adds support for its own ItcHeader
and ItcError
attributes, but for the rest makes use of the default Android attributes already associated with TextInput controls.
Given the above attributes definition, the layout for the same password field using the ITTextInputLayout
control can be simplified to:
Notice that the control now supports the IITComposite
interface through the Header
,Text
and Error
properties. Again, the code snippet illustrates these properties being set using the binding functionality of MvvmCross. I can however also set them manually as shown by using the app:ItcHeader
attribute to set the Header property in the following snippet:
Control Properties
With these attributes defined, we can now populate the properties for our control from the layout definition (lines 8-27):
We first inflate our control and then assign the attribute values from the layout to the public properties of the control. These properties are mapped to the internally inflated controls to drive the behavior of the compound control.
Control Events
To allow external consumers to be notified of the text being entered, we add a TextChanged
event to the compound control.
We hook/unhook the Control.AfterTextChanged
event via the OnAttachedToWindow
and OnDetachFromWindow
methods and raise our own TextChanged
event whenever we get notified by the internal TextEditInputView
.
In a follow up post I will show how easy it is to create a custom MvvmCross binding for the ITTextInputLayout.TextChanged
event to automatically bind the changes to a data context.
Summary
That’s about it for now. You can find a gist for the complete code of the ITTextInputLayout
control here. I also highly recommend reading through the transcript of this talk by Daniel Lew on how to create efficient Android layouts.
20 Apr 2017
Over the past year or two we’ve been using Xamarin to build a moderately complex mobile application. On Key Work Manager is a mobile work order management solution that enables your field service staff to manage their work assignments and forms part of the On Key Enterprise Asset Management system.
To illustrate why I say this is as a moderately complex app, here are some of the features:
- Location tracking
- Maps integration
- Electronic PDF form filling and generation
- Electronic signatures to support signing off job cards
- Barcode scanning of assets
- Document attachments including photos, in-app voice recordings etc.
- Local notifications
- Background services to synchronise data whilst the app is not running
- Full offline support - i.e. app functionality works in offline environments and only requires peridic connectivity to synchronise changes to server
Based on local market demands, we targeted Android first and published the Android version of the application mid 2016. Last week we published the iOS version of the application.
I’ve had one or two enquiries from people on what tools/libaries/frameworks we used to build the app. This post will give a rundown of what we use.
Frameworks
One of the principles we followed from the word go, was to try and maximize the re-use of shared logic across the different platforms. The team had experience using the MVVM pattern so we decided on using a framework that would supprt the MVVM pattern. Xamarin Forms was still in its infancy at that stage so we decided to look for a framework that would allow us to build directly on top of the native platform thus giving us full access to the native platform performance, native iOS and Android controls, native navigation mechanisms etc.
We ended up using a blend of the excellent MvvmCross and our own small homegrown framework that covered aspects like navigation and bootstrapping a bit differently as to how MvvmCross prescribes. This is a big shout out to the community members behind MvvmCross like Tomasz and Martijn00. The fact that we were able to replace aspects of MvvmCross is also a compliment to the overall design of the framework. MvvmCross v5 is shaping up to be an awesome release as well.
Using the MVVM pattern we are able to share up to 70-75% of the code base between the different platforms in a PCL library.
Testing
We have an extensive set of NUnit unit tests covering the shared logic contained in our PCL library that we execute on our TeamCity CI server. We are also in the early phases of using Xamarin.UITest to do automated UI testing.
Plugins/3rd Party Components
We use the following plugins/components to support the app features:
NuGet Packages/Libraries
Besides the frameworks/plugins/controls, we use the following NuGet packages:
Testing/Analytics/Crash Reporting
For ALPHA, BETA testing, crash reporting and application insights we use HockeyApp
I think that’s about it! Since we started using Xamarin, the whole ecosystem around Xamarin including the plugins, components have evolved quite nicely. This allows us to focus on building the features of our app instead of having to re-invent the wheel. Overall we are quite happy with how our code base has turned out and we are looking forward to building more apps using Xamarin.