Cross Platform C#

Working New Android 5 Lollipop Features into Your Apps

Android 5 Lollipop has a few new features -- including some UI and performance improvements -- that can now be incorporated into your apps. Here's how to work with the update.

Who doesn't love some sugar? Android 5, code-named "Lollipop," is Google's latest release of the Android OS for phones, tablets and wearable devices. There are a large number of new features, some you should be aware as you develop apps going forward:

  • Material Design and UI controls and capabilities. Material Design is a bold, colorful, and responsive UI design for consistent and intuitive experiences across all devices. This includes responsive, natural motion, realistic lighting, shadows, and visual elements that make it easier for users to navigate on their device, and new colors, typography, animations, and edge-to-edge imagery assistance to focus user attention.
  • Notifications. The new Notifications provide ways to control when and how users receive messages. Users are able to view and respond to messages directly from the lock screen as well as hide sensitive content for these notifications.
  • New runtime and performance improvements. ART is the new Android runtime (replacing Dalvik). Let's be honest -- who hasn't had problems with a poorly performing app in Dalvik on some device? I know that my Nexus 7 2013 seems to have problems. Over time, I find that apps run slower and slower until a reboot resolves that problem. ART improves application performance and responsiveness.
  • 64 bits. Apple released 64-bit support in iOS in the fall of 2013. The competitive marketplace requires that Android does likewise. With Android 5.0, Google supports the current 32-bit ARM architecture, as well as 64-bit chips from ARM, x86 and MIPS.
  • Accessibility. I have a large number of users at one of my clients that have accessibility issues. Given the vision problems that they have, I personally feel that it's important to make their interaction with my applications work as well as possible. Previously, Android hasn't done a good job in this area. With Lollipop, Android has improved accessibility.

These are some of the high-level improvements in Android 5, but there are many more. Clearly, one article cannot do justice to an update of this magnitude.

This column will focus on one of the new controls in Android 5. Let's get started!

Support Library
One of the great things about iOS is that Apple controls its distribution. When Apple releases an update, it ensures the update is available to every iOS user no matter what mobile provider they're using worldwide. One of the issues with Android is that updates go from Google to the device manufacturer for device-specific updates, then to the cell providers and then finally to the user. There are two steps between Google and end users, which results in delays between the time Google puts out an update and the time the end users receive it. The resulting fragmentation makes it hard for you to take advantage of the latest and greatest features that can be used to provide your users with value.

Thankfully, Google has solved this problem a bit with its Android Support Library. With the release of Android 5, Google has released a new version that will provide support for new features in older versions of Android. One of these new features is the RecyclerView, which I'll discuss in this column.

There are a number of other new features included with the update to the Support Library. One of the things that Xamarin has done is that it has separated out the various features of its bindings for the Support Library into several libraries. These bindings are available via NuGet, which allows Xamarin to update its products quicker and get the updates to you without having to update the entire Xamarin.Android product.

RecyclerView
Displaying data is the most common operation in mobile apps. Nearly every application has some type of dataset that must be displayed. Android has had the ListView and Expandable ListView.

With Android 5, Google has enhanced the ListView, made it available to users of previous versions of Android with the Android Support Library, and packaged it in the RecyclerView widget. The Support Library has been discussed in a <a href=http://visualstudiomagazine.com/articles/2014/10/01/xamarin-tools.aspx target="_blank">previous column.

The RecyclerView is optimized to display large amounts of data by having a layout manager, which maintains a limited number of views. The parts of using the RecyclerView are:

  • Layout Manager. A Layout Manager positions item views inside the RecyclerView. The Layout Manager determines when to reuse item views that are no longer visible in the display. When reusing a view, the layout manager may ask the adapter to replace the contents of the existing view with some new data from the data in the adapter. With Android, this will improve performance by avoiding the creation of unnecessary views and minimizing the number of nodes to search via FindViewById. Adapter. Just like the ListView, the RecyclerView has an Adapter. It provides access to the items in the data, creates views for the items in the data, and replaces the content in the views with new data items, as appropriate. The Adapter for the RecyclerView is a bit different from the Adapter that you're familiar with in the ListView; however, the concepts are nearly the same. The biggest difference is the required use of the ViewHolder.
  • ViewHolder. The View Holder is an instance of a view. The view instance "holds" references to the various views within the cell. This eliminates the need to continually call FindViewById.

Here are the following built-in layout managers:

  • LinearLayoutManager. The LinearLayoutManager displays items in a vertical or horizontal list of data.
  • GridLayoutManager. The GridLayoutManager displays data in a grid.
  • StaggeredGridLayoutManager. The StaggeredGridLayoutManager displays data in a staggered grid layout.

Along with the built-in layout managers, there's the ability to create a custom layout manager. This can be done by creating a custom class to extend/inherit from the RecyclerView.LayoutManager class.

I'll take a look at some sample code. Note: In this example, I'm using beta software so be aware that there may be changes by the time the article is published.

Listing 1 shows the initial layout.axml file for the RecyclerView, and Listing 2 shows the displayitem.axml file.

Listing 1: The RecyclerView Layout.axml File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:minWidth="25px"
  android:minHeight="25px">
  <android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</LinearLayout>

Listing 2: The RecyclerView Displayitem.axml File
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="150dp"
  android:padding="@dimen/activity_margin"
  android:foreground="?android:attr/selectableItemBackground">
  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="150dp"
    android:orientation="vertical"
    android:padding="@dimen/activity_margin">
    <ImageView
      android:layout_width="50dp"
      android:layout_height="50dp"
      android:id="@+id/imageView"
      android:scaleType="centerCrop" />
    <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:text="Title"
      android:id="@+id/WeatherSummaryText"
      android:layout_gravity="center_horizontal"
      android:layout_marginLeft="@dimen/activity_margin" />
    <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:text="Title"
      android:id="@+id/WeatherDetailText"
      android:layout_gravity="center_horizontal"
      android:layout_marginLeft="@dimen/activity_margin" />
  </LinearLayout>
</FrameLayout>

Listing 3 shows the code for displaying the code for the RecyclerView. In this example, it displays the weather for a location.

Listing 3: RecyclerView Code Displays Location-Specific Weather
using System;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V7.Widget;
using Android.Support.V7.RecyclerView;

using PCLWebServices;

namespace DemoRecyclerView
{
  [Activity (Label = "Recycler View", MainLauncher = true, Icon = "@drawable/icon")]
  public class MainActivity : Activity
  {
    PCLWebServices.WeatherReport wr;
    async protected override void OnCreate (Bundle bundle)
    {
      base.OnCreate (bundle);
      var d = new PCLWebServices.Data ();
      wr = await d.GetData ("Knoxville, TN");

      // Set  view from the "main" layout resource
      SetContentView (Resource.Layout.main);
      RecyclerView recList = FindViewById<RecyclerView>(Resource.Id.my_recycler_view);
      recList.HasFixedSize = true;
      LinearLayoutManager llm = new LinearLayoutManager(this);
      llm.Orientation = LinearLayoutManager.Vertical;
      recList.SetLayoutManager (llm);
      var adapt = new RecycleAdapt (wr);
      recList.SetAdapter (adapt);
    }
  }

  public class RecycleAdapt : RecyclerView.Adapter
  {
    PCLWebServices.WeatherReport _wr;
    public RecycleAdapt(WeatherReport wr )
    {
      _wr = wr;
    }

    // Create new views (invoked by the layout manager)
    public override RecyclerView.ViewHolder OnCreateViewHolder(
      ViewGroup viewGroup, int position)
    {
      var li = LayoutInflater.From (viewGroup.Context);
      var v = li.Inflate (Resource.Layout.displayitem, viewGroup, false);
      ViewHolder vh = new ViewHolder (v);
      return vh;
    }
    // Replace the contents of a view (invoked by the layout manager)
    public override void OnBindViewHolder(
      RecyclerView.ViewHolder viewHolder, int position)
    {
      // Get element from your dataset at this position and replace  
      // the contents of the  view with that element
      var weather = _wr.list [position];
      var vw = viewHolder as ViewHolder;
      vw.WeatherSummaryText.SetText(
        weather.weather[0].description,TextView.BufferType.Normal);
      vw.WeatherDetailText.SetText(String.Format ("Hi: {0} Low: {1}", 
        weather.temp.max, weather.temp.min), TextView.BufferType.Normal);
      var img = BitmapFactory.DecodeByteArray(weather.weather[0].Image, 0, 
        weather.weather[0].Image.Length);
      vw.Image.SetImageBitmap(img);
    }
    // Return the size of your dataset (invoked by the layout manager)
    public override int ItemCount
    {
      get{ return _wr.list.Count; }
    }
  }

  public class ViewHolder : RecyclerView.ViewHolder
  {
    public TextView WeatherSummaryText { get; set; }
    public TextView WeatherDetailText { get; set; }
    public ImageView Image { get; set; }
    public ViewHolder(View view) :
    base(view)
    {
      WeatherSummaryText = view.FindViewById<TextView> (Resource.Id.WeatherSummaryText);
      WeatherDetailText = view.FindViewById<TextView> (Resource.Id.WeatherDetailText);
      Image = view.FindViewById<ImageView> (Resource.Id.imageView);
    }
  }
}

The result of running this code is obtaining the weather report for the next 14 days for the requested location. In the example in Figure 1, the request is made for Oxford, Ohio, where my daughter went to school during November 2014.

[Click on image for larger view.] Figure 1. Weather for November 2014 in Oxford, Ohio

Also Read…

Recycle What You've Learned
Since the release of the Android 5 Lollipop update, the Xamarin support for Android 5 has provided some great advantages. The Android update has been deployed to developers, Nexus devices and is beginning to rollout to Android devices. The Xamarin support update has been available in at least the beta channel for several months, so there's no excuse to start using it today. I hope you've learned enough just from this look at the basics of the new RecyclerView, which is just one of many new APIs in the Lollipop update.

The Android Support Library
Data Binding with the ListView

About the Author

Wallace (Wally) B. McClure has authored books on iPhone programming with Mono/Monotouch, Android programming with Mono for Android, application architecture, ADO.NET, SQL Server and AJAX. He's a Microsoft MVP, an ASPInsider and a partner at Scalable Development Inc. He maintains a blog, and can be followed on Twitter.

comments powered by Disqus

Featured

  • Microsoft Eases Integration with Semantic Kernel AI SDK

    The basic idea is to provide unified API abstractions, especially for idiomatic C# code, to help platform developers and others work with any provider with standard implementations for caching, telemetry, tool calling and other common tasks.

  • Final .NET 9 Preview Ships with Go-Live License

    Visual Studio developers can now download the SDK for .NET 9 Release Candidate 2 with a go-live license, meaning devs get Microsoft support for production applications even before the framework reaches general availability next month.

  • Upcycle Your Old Laptops into a Kubernetes Cluster

    Learn about Windows-to-Linux conversions and how to break and fix cloud containers -- all while helping to save the world from e-waste with some "sheer geeky fun."

  • Visual Studio's Future: Live Help to 'AI-ify Your App'

    Visual Studio guru Mads Kristensen provided a peek into the IDE's AI future, explaining how while in live-coding it will identify opportunities for your own app to use AI to your advantage.

Subscribe on YouTube