Upload
jeremie-laval
View
604
Download
0
Embed Size (px)
DESCRIPTION
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.
Citation preview
Jérémie LavalHappy [email protected]
Tips & Tricks to Spice Up Your Android App
Spice-Up Tricks
ListView Tricks
Why ListView? Ubiquity.
Why ListView? Ubiquity.
Why ListView? Ubiquity.
Why ListView? Ubiquity.
From Basic ListView…
Boring
… to Complete App
Let’s Build This
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
The Basics
DEMO
ListFragment Customization
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
...
LulzDog
LulzCat
...
...
Warning! Async Loadingrequest
callback
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;}
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); }); });}
The Pretty
DEMO
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>
Prettify Your List Items
<FrameLayout android:background="@drawable/list_item_box" />
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
Custom Drawablepublic 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); }}
Custom Drawable
imageView.SetImageDrawable (new RoundCornersDrawable (glacierBmp, cornerRadius: 10))
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" />
Easy Inset Effects
The Gimmick
The Animated Stuff
“The best animations are the ones your usersdon’t notice because they feel natural”
- Jérémie Laval
“The best animations are the ones your usersdon’t notice because they feel natural”
01
02
03
04
05
06
07
08
09
10
11
12
13
14
Fade ImageViewpublic 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); }); }}
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;}
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>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
Automatic Layout Transitionsif (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;}
Last Call
developers.android.com/designA worthy read for every app developer