Pro Yearly is on sale from $80 to $50! »

Tips & Tricks to spice up your Android app

Tips & Tricks to spice up your Android app

We will explore how Android (especially in recent versions) lets you develop awesomer apps and how you can tap into that potential with Xamarin.Android. Topics covered will include graphics, user interaction, best practices and animations.

167f2c9daf3e040134359926747a510b?s=128

Jérémie Laval

April 17, 2013
Tweet

Transcript

  1. Jérémie Laval Happy Hacker Xamarin jeremie.laval@xamarin.com Tips & Tricks to

    Spice Up Your Android App
  2. Spice-Up Tricks

  3. ListView Tricks

  4. Why ListView? Ubiquity.

  5. Why ListView? Ubiquity.

  6. Why ListView? Ubiquity.

  7. Why ListView? Ubiquity.

  8. From Basic ListView… Boring

  9. … to Complete App

  10. Let’s Build This

  11. Breaking Things Up 1. The Basics Loading and data fetching

    2. The Pretty Improving the look and feel 3. The Gimmick Spicing up the result
  12. The Basics

  13. DEMO

  14. ListFragment Customization

  15. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 15 16 ListFragment Customization <?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">        <LinearLayout                android:orientation="horizontal"                android:id="@id/android:empty">                <ProgressBar  />                <TextView  android:text="Loading..."  />        </LinearLayout>        <ListView                android:id="@id/android:list"                android:layout_weight="1"  /> </LinearLayout
  16. ... LulzDog LulzCat ... ... Warning! Async Loading request callback

  17. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 Async Loading public  override  View  GetView  (int  position,  View  convertView,  ViewGroup  parent) {   MyCustomView  view  =  EnsureView  (convertView);   var  versionNumber  =  Interlocked.Increment  (ref  view.VersionNumber);   var  item  =  events  [position];   var  avatarView  =  view.FindViewById<ImageView>  (...);   avatarView.SetImageDrawable  (EmptyAvatarDrawable);   FetchAvatar  (view,  avatarView,  item,  versionNumber);   return  view; }
  18. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 15 Async Loading (cont) var  imageCache  =  new  ConcurrentDictionary<string,  Task<Bitmap>>  (); void  FetchAvatar  (...  view,  ...  avatarView,  string  url,  long  versionNumber) {   var  bmp  =  imageCache.GetOrAdd  (url,  u  =>  Task.Run  (()  =>  DownloadData  (u)));   if  (bmp.IsCompleted  &&  bmp.Result  !=  null)     avatarView.SetImage  (bmp.Result);   else     bmp.ContinueWith  (t  =>  {       if  (view.VersionNumber  ==  versionNumber  &&  t.Result  !=  null)         handler.Post  (()  =>  {           if  (view.VersionNumber  ==  versionNumber)             avatarView.SetImageAnimated  (t.Result);         });     }); }
  19. The Pretty

  20. DEMO

  21. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 15 Prettify Your List Items <?xml  version="1.0"  encoding="utf-­‐8"?> <shape  xmlns:android="http://schemas.android.com/apk/res/android"              android:shape="rectangle">        <corners  android:radius="3dp"  />        <gradient                  android:startColor="@android:color/transparent"                  android:endColor="#10000000"                  android:type="linear"                  android:centerColor="@android:color/transparent"                  android:centerY="0.8"                  android:angle="270"  />        <stroke                  android:width="1dp"                  android:color="#D0D0D0"  /> </shape>
  22. Prettify Your List Items <FrameLayout  android:background="@drawable/list_item_box"  />

  23. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 15 Custom Drawable public  class  RoundCornersDrawable  :  Drawable {    public  RoundCornersDrawable  (Bitmap  bitmap,  float  cornerRadius  =  5)    {        this.cornerRadius  =  cornerRadius;        this.paint  =  new  Paint  ()  {  AntiAlias  =  true  };        var  tileMode  =  Shader.TileMode.Clamp;        paint.SetShader  (new  BitmapShader  (bitmap,  tileMode,  tileMode));    }    public  override  void  Draw  (Canvas  canvas)    {        canvas.DrawRoundRect  (rect,  cornerRadius,  cornerRadius,  paint);    } }
  24. Custom Drawable imageView.SetImageDrawable  (new  RoundCornersDrawable  (glacierBmp,  cornerRadius:  10))

  25. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 15 16 Easy Inset Effects <TextView        android:text="White-­‐based  inset"        android:shadowColor="@android:color/white"        android:shadowDx="1"        android:shadowDy="1"        android:shadowRadius="0.1"  /> <TextView        android:text="Black-­‐based  inset"        android:shadowColor="@android:color/black"        android:shadowDx="-­‐1"        android:shadowDy="-­‐1"        android:shadowRadius="0.1"  />
  26. Easy Inset Effects

  27. The Gimmick

  28. The Animated Stuff

  29. “The best animations are the ones your users don’t notice

    because they feel natural”
  30. - Jérémie Laval “The best animations are the ones your

    users don’t notice because they feel natural”
  31. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 Fade ImageView public  static  class  ImageViewExtensions {    public  static  void  SetImageDrawableAnimated  (this  ImageView  view,                                                                                                  Drawable  drawable)    {        var  lng  =  view.Resources.GetInteger  (ConfigLongAnimTime);        var  med  =  view.Resources.GetInteger  (ConfigMediumAnimTime);        view.Animate  ().Alpha  (0).SetDuration  (med).WithEndAction  (()  =>  {            view.SetImageDrawable  (drawable);            view.Animate  ().Alpha  (1).SetDuration  (lng);        });    } }
  32. 01 02 03 04 05 06 07 08 09 10

    11 12 13 ListView Item Animations public  override  View  GetView  (int  position,  View  convertView,  ViewGroup  parent) {   var  view  =  EnsureView  (convertView);   var  item  =  events  [position];   if  (!item.Consumed)  {     item.Consumed  =  true;     var  animation  =  AnimationUtils.MakeInChildBottomAnimation  (context);     view.StartAnimation  (animation);   }   return  view; }
  33. 01 02 03 04 05 06 07 08 09 10

    11 12 13 Automatic Layout Transitions <LinearLayout        android:orientation="vertical"        android:id="@+id/AnimatedLayout"        android:animateLayoutChanges="true"        android:minHeight="49dp"        android:layout_height="wrap_content">        <LinearLayout  android:id="@+id/PresentationLayout"  />        <LinearLayout  android:id="@+id/ActionLayout"                                    android:layout_height="1px"  /> </LinearLayout>
  34. 01 02 03 04 05 06 07 08 09 10

    11 12 13 14 Automatic Layout Transitions if  (presentationLayout.Visibility  ==  ViewStates.Gone)  {   presentationLayout.Visibility  =  ViewStates.Visible;   var  lp  =  new  LayoutParams  (actionLayout.LayoutParameters)  {     Height  =  1   };   actionLayout.LayoutParameters  =  lp; }  else  {   var  lp  =  new  LayoutParams  (actionLayout.LayoutParameters)  {     Height  =  ViewGroup.LayoutParams.WrapContent,     Gravity  =  GravityFlags.Center   };   actionLayout.LayoutParameters  =  lp;   presentationLayout.Visibility  =  ViewStates.Gone; }
  35. Last Call

  36. developers.android.com/design A worthy read for every app developer

  37. Thanks! /garuma/EvolveDemo