27 June 2014

Google I/O 2014 - Quick Bits

Another year another Google I/O. I have to say I was very disappointed not to go this year, especially after hearing that the attendees got to pick an Android Wear watch to take home, but also will be receive the Motorola 360 when it becomes available this Autumn.

This post is to give you links to some of the important parts of the Google I/O this year, most that were mentioned in the Keynote.

Keynote: It's 3 hrs long but reveals some great insight into the eco-system Google are building.
http://www.youtube.com/watch?v=wtLJPvx7-ys

Android L: The new Android version. New notifications, new design paradigms, 5000 new API's.
Keynote part: http://www.youtube.com/watch?v=oMF6JIGhsH8
What's new in Android: http://www.youtube.com/watch?v=3TtVsy98ces

Material Design: About 13 mins into the Keynote. New flat designs paradigm. Looks really nice, anyone with an interest in UI will love this.
http://www.google.com/design/spec/material-design/introduction.html

Polymer: Web development tool to make it easier to build applications. Uses material design.
http://www.polymer-project.org/ 


Android Wear: 49 mins into the keynote. The most exciting part for me. The keynote really showed off the power of these devices.
http://www.android.com/wear/
Also they are available in Ireland: https://play.google.com/store/devices/collection/promotion_500013a_android_wear_ie?hl=en-GB

Android Auto: 1hr 5 mins into keynote. Takes control of you car screen (if you have one). Music, calls, mapping etc controlled with voice or your steering wheel controls.
http://www.android.com/auto/

Android TV: 1hr 16 into keynote. Android takes over your TV with Google Play Movies and Music. Don't worry you can still have Netflix there. Also allows you to play games, and you can cast from your devices.
http://www.android.com/tv/

Chromecast Updates: 1hr 28 into keynote. One of the best purchases I made was my Chromecast. I am delighted to see it is still being improved even with the development of Android TV. It will now be able to allow users to cast without connecting to the wifi, allow cast of entire device screen so any app can be on screen. Also allows you to choose photos for it to cycle through when not casting.
http://www.google.com/intl/en/chrome/devices/chromecast/?gclid=CPDzna_cmb8CFabm7AodHUQApw

Chromebooks: 1hr 38 into keynote. Chromebooks will now sync better with your phone, showing notifications and will allow apps on your phone to be used on the laptop
http://www.google.com/intl/en/chrome/devices/


There is of course lots more to see on the Google I/O site.
https://www.google.com/events/io


16 June 2014

Making a Fragment Utility

Android's fragments bring much versatility to UI development. But if you want to show and hide multiple fragments with options, this can take a few coding lines. Repeat this throughout and your code can become ugly and difficult to manage.

A simple solution is to create a small Fragment Utility class. This class should handle the showing and hiding of a fragment with some simple method calls. It should allow you to add the fragment to the back stack, or not, to add a tag for the fragment and to decide on your entrance and exit animations.

To do this, we first create the animations. We usually want slide in and out animations, mostly from the right hand side or from the bottom.
To create the slide in animation from the right hand side, we use a simple translate animation.

<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate 
     android:fromXDelta="100%p" 
     android:toXDelta="0"
        android:duration="@integer/slide_out_animation_duration"/>
</set>
 
Here we are translating from xDelta of 100% to 0. For the slide out animation we simply reverse this.

<set xmlns:android="http://schemas.android.com/apk/res/android">
 <translate 
     android:fromXDelta="0" 
     android:toXDelta="100%p"
        android:duration="@integer/slide_out_animation_duration"/>
</set>

We can repeat these type of animations for slide entrance and exit from differing sides.

To create the utility we make a class named FragmentUtil.

We first will create an enum called FragmentSlideAnimation to contain our entrance and exit animations. We then add a function to return the chosen animations.

public enum FragmentSlideAnimation {fromtop, frombottom, fromright, 
fromleft};
 
/**
 * I get the slide in and out animations based on the FragmentSlideAnimation
 * @param animation
 * @return int array of size 2 of animations resource id's
 */
 public static int[] getSlideAnimations(FragmentSlideAnimation animation){
 int [] animations = new int [2];
 if (animation.equals(FragmentSlideAnimation.fromtop)){
  animations[0] = R.anim.slide_in_from_top;
  animations[1] = R.anim.slide_out_to_top;
 }
 else if (animation.equals(FragmentSlideAnimation.frombottom)){
  animations[0] = R.anim.slide_in_from_bottom;
  animations[1] = R.anim.slide_out_to_bottom;
 }
 else if (animation.equals(FragmentSlideAnimation.fromleft)){
  animations[0] = R.anim.slide_in_from_left;
  animations[1] = R.anim.slide_out_to_left;
 }
 else if (animation.equals(FragmentSlideAnimation.fromright)){
  animations[0] = R.anim.slide_in_from_right;
  animations[1] = R.anim.slide_out_to_right;
     }
 return animations;
}

We also want this class to handle fragments using the latest versions of Android, but also to support older versions using the v4 support jar.

This means that for each method we need to have a similar method for the v4 fragments.

Firstly we create a hide method. The function will take in the fragment to hide and the fragment manager or the fragment transaction. We can use overloading to create two methods with the same name but differing method signatures.

/**
 * I hide a fragment
 * @param frag
 * @param fragmentManager
 */
 public static void hideFragment(android.app.Fragment frag, 
         android.app.FragmentManager fragmentManager){
 android.app.FragmentTransaction ft = fragmentManager.beginTransaction();
 hideFragment(frag, ft);
 }
 
/**
 * I hide a fragment
 * @param frag
 * @param fragmentTransaction
 */
public static void hideFragment(android.app.Fragment frag, 
       android.app.FragmentTransaction fragmentTransaction){
      if (android.os.Build.VERSION.SDK_INT 
             >= android.os.Build.VERSION_CODES.HONEYCOMB){
   if (frag != null){
              fragmentTransaction.hide(frag);
              fragmentTransaction.commit();
 }
     }
 }

So next we want show the fragment. We are going to show all fragments on the content. We have a few options when showing a fragment.
  • To use a entrance/exit animation
  • To add to the back stack
  • To set a tag for the fragment
So, we simply use overloading to present methods with these options and without

/**
 * I show a fragment on content
 * @param fragmentManager
 * @param frag
 * @param backStackArg
 */
public static void showFragmentOnContent
  (android.app.FragmentManager fragmentManager, android.app.Fragment frag, 
  String backStackArg){
 showFragmentOnContent(fragmentManager, frag, backStackArg, null);
  }
 
/**
 * I show a fragment on content
 * @param fragmentManager
 * @param frag
 * @param backStackArg
 * @param animation
 */
public static void showFragmentOnContent
 (android.app.FragmentManager fragmentManager, 
  android.app.Fragment frag, String backStackArg,
  FragmentSlideAnimation animation){ 
        if (android.os.Build.VERSION.SDK_INT 
          >= android.os.Build.VERSION_CODES.HONEYCOMB){
 android.app.FragmentTransaction ft = fragmentManager.beginTransaction();
 showFragmentOnContent(ft, frag, backStackArg, animation);
 }
 }
 
 
/**
 * I show a fragment on content
 * @param fragmentTransaction
 * @param frag
 * @param backStackArg
 * @param animation
 */
public static void showFragmentOnContent
 (android.app.FragmentTransaction fragmentTransaction, 
  android.app.Fragment frag, String backStackArg, 
  FragmentSlideAnimation animation){
 if (android.os.Build.VERSION.SDK_INT 
         >= android.os.Build.VERSION_CODES.HONEYCOMB){
  fragmentTransaction.add(android.R.id.content, frag);
             if (backStackArg != null)
                    fragmentTransaction.addToBackStack(backStackArg);
             if (animation != null){
          int [] animations = getSlideAnimations(animation);
          fragmentTransaction.setCustomAnimations(animations[0], 
                              animations[1], animations[0], animations[1]);
             }
  fragmentTransaction.show(frag);
  fragmentTransaction.commit();
 }
 }

If you notice, we didn't get the option for adding a tag. Well we have to do this with extra methods as Android uses overloading on the fragmentTransaction.add method to achieve this.
/**
 * I show a fragment on content with a tag
 * @param fragmentManager
 * @param frag
 * @param tag
 */
public static void showFragmentOnContentWithTag
(android.app.FragmentManager fragmentManager, 
  android.app.Fragment frag, String tag){
    showFragmentOnContentWithTag(fragmentManager, frag, null, tag);
}
 
/**
 * I show a fragment on content with a tag
 * @param fragmentManager
 * @param frag
 * @param backStackArg
 * @param tag
 */
public static void showFragmentOnContentWithTag
   (android.app.FragmentManager fragmentManager,
    android.app.Fragment frag, String backStackArg, 
    String tag){
 android.app.FragmentTransaction ft = fragmentManager.beginTransaction();
     showFragmentOnContentWithTag(ft, frag, backStackArg, tag);
} 
/**
 * I show a fragment on content with a tag
 * @param fragmentTransaction
 * @param frag
 * @param tag
 */
public static void showFragmentOnContentWithTag
(android.app.FragmentTransaction fragmentTransaction, 
   android.app.Fragment frag, String tag){
 showFragmentOnContentWithTag(fragmentTransaction, frag, null, tag);
}
 
/**
 * I show a fragment on content with a tag
 * @param fragmentTransaction
 * @param frag
 * @param backStackArg
 * @param tag
 */
public static void showFragmentOnContentWithTag
(android.app.FragmentTransaction fragmentTransaction, 
   android.app.Fragment frag, String backStackArg, String tag){
 showFragmentOnContentWithTag(fragmentTransaction, frag, 
         backStackArg, tag, null);
}
 
/**
 * I show a fragment on content with a tag
 * @param fragmentTransaction
 * @param frag
 * @param backStackArg
 * @param tag
 * @param animation
 */
public static void showFragmentOnContentWithTag
  (android.app.FragmentTransaction fragmentTransaction, 
  android.app.Fragment frag, String backStackArg, 
  String tag, FragmentSlideAnimation animation){ 
 
    fragmentTransaction.add(android.R.id.content, frag, tag);
    if (backStackArg != null)fragmentTransaction.addToBackStack(backStackArg);
    if (animation != null){
     int [] animations = getSlideAnimations(animation);
     fragmentTransaction.setCustomAnimations(animations[0], 
                 animations[1], animations[0], animations[1]);
    }
    fragmentTransaction.show(frag);
    fragmentTransaction.commit();
}


And that's it. We need to repeat this for v4 fragments and we're done. We can then extend the utility to handle showing fragments on differing layouts instead of just on the content.

You can find the code for this on my github.