Slide 1

Slide 1 text

Jérémie Laval Happy Hacker Xamarin [email protected] Tips & Tricks to Spice Up Your Android App

Slide 2

Slide 2 text

Spice-Up Tricks

Slide 3

Slide 3 text

ListView Tricks

Slide 4

Slide 4 text

Why ListView? Ubiquity.

Slide 5

Slide 5 text

Why ListView? Ubiquity.

Slide 6

Slide 6 text

Why ListView? Ubiquity.

Slide 7

Slide 7 text

Why ListView? Ubiquity.

Slide 8

Slide 8 text

From Basic ListView… Boring

Slide 9

Slide 9 text

… to Complete App

Slide 10

Slide 10 text

Let’s Build This

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

The Basics

Slide 13

Slide 13 text

DEMO

Slide 14

Slide 14 text

ListFragment Customization

Slide 15

Slide 15 text

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 ListFragment Customization                                                        

Slide 16

Slide 16 text

... LulzDog LulzCat ... ... Warning! Async Loading request callback

Slide 17

Slide 17 text

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  (...);   avatarView.SetImageDrawable  (EmptyAvatarDrawable);   FetchAvatar  (view,  avatarView,  item,  versionNumber);   return  view; }

Slide 18

Slide 18 text

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 Async Loading (cont) var  imageCache  =  new  ConcurrentDictionary>  (); 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);         });     }); }

Slide 19

Slide 19 text

The Pretty

Slide 20

Slide 20 text

DEMO

Slide 21

Slide 21 text

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 Prettify Your List Items                        

Slide 22

Slide 22 text

Prettify Your List Items

Slide 23

Slide 23 text

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);    } }

Slide 24

Slide 24 text

Custom Drawable imageView.SetImageDrawable  (new  RoundCornersDrawable  (glacierBmp,  cornerRadius:  10))

Slide 25

Slide 25 text

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Easy Inset Effects

Slide 26

Slide 26 text

Easy Inset Effects

Slide 27

Slide 27 text

The Gimmick

Slide 28

Slide 28 text

The Animated Stuff

Slide 29

Slide 29 text

“The best animations are the ones your users don’t notice because they feel natural”

Slide 30

Slide 30 text

- Jérémie Laval “The best animations are the ones your users don’t notice because they feel natural”

Slide 31

Slide 31 text

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);        });    } }

Slide 32

Slide 32 text

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; }

Slide 33

Slide 33 text

01 02 03 04 05 06 07 08 09 10 11 12 13 Automatic Layout Transitions                

Slide 34

Slide 34 text

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; }

Slide 35

Slide 35 text

Last Call

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Thanks! /garuma/EvolveDemo