7/27/2019 Filthy Rich Android
1/96
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
2/96
Filthy Rich Clients
Romain Guy
Chet Haase
google.com/+RomainGuy
google.com/+ChetHaase
@ro
@c
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
3/96
Filthy Rich Clients
Romain Guy
Chet Haase
google.com/+RomainGuy
google.com/+ChetHaase
@ro
@c
Android
Thursday, November 14, 13
S
7/27/2019 Filthy Rich Android
4/96
Filthy Rich Clients
Romain Guy
Chet Haase
google.com/+RomainGuy
google.com/+ChetHaase
@ro
@c
Android
Shin
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
5/96
De!nition: Filthy Rich Clients
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
6/96
De!nition: Filthy Rich Clients
2007
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
7/96
Ultra-graphically rich applications that ooze coolsuck the user in from the outset and hang on to
with a death grip of excitement.
De!nition: Filthy Rich Clients
2007
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
8/96
Ultra-graphically rich applications that ooze coolsuck the user in from the outset and hang on to
with a death grip of excitement.
De!nition: Filthy Rich Clients
2007
2013
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
9/96
Ultra-graphically rich applications that ooze coolsuck the user in from the outset and hang on to
with a death grip of excitement.
De!nition: Filthy Rich Clients
Applications that look cool, run smoothly, and inwell with the user.
2007
2013
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
10/96
Graphics
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
11/96
#DV13 #Filth
Images withrounded corne
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
12/96
#DV13 #Filth
Images with rounded corners
Dont bake the shape in your images
Dont use intermediate layers Dont use clipping
Use shaders!
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
13/96
#DV13 #Filth
What is a shader?
A set of instructions that computes the source
color of a pixel being drawn.
Chet or Romain, just now
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
14/96
#DV13 #Filth
Example
Paintp =newPaint();p.setColor(Color.RED);
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
15/96
#DV13 #Filth
Example
Paintp =newPaint();p.setColor(Color.RED);
Simplestshaderever
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
16/96
#DV13 #Filth
Android shaders
Similar to OpenGL fragment shaders
Not programmable Subclasses of android.graphics.Shader
- BitmapShader
- ComposeShader
- LinearGradient
- RadialGradient
- SweepGradient
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
17/96
#DV13 #Filth
How drawing works (simplified)
+
drawRoundRect
Paint
Mask
Shader
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
18/96
#DV13 #Filth
Back to images
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
19/96
#DV13 #Filth
Back to images
BitmapShadershader =newBitmapShader(bitma Shader.TileMode.CLAMP, Shader.TileMode.C
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
20/96
#DV13 #Filth
Back to images
BitmapShadershader =newBitmapShader(bitma Shader.TileMode.CLAMP, Shader.TileMode.C
Paintpaint =newPaint();paint.setAntiAlias(true);paint.setShader(shader);
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
21/96
#DV13 #Filth
Back to images
BitmapShadershader =newBitmapShader(bitma Shader.TileMode.CLAMP, Shader.TileMode.C
Paintpaint =newPaint();paint.setAntiAlias(true);paint.setShader(shader);
RectFrect =newRectF(0.0f, 0.0f, width, hecanvas.drawRoundRect(rect, radius, radius, p
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
22/96
#DV13 #Filth
Contrary to the previous slideNever allocate in draw() methods.
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
23/96
#DV13 #Filth
Vignette
Novignette
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
24/96
#DV13 #Filth
ComposeShader
LinearGradient
BitmapShader ComposeS
xfermode
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
25/96
#DV13 #Filth
Vignette
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
26/96
#DV13 #Filth
Vignette
RadialGradientvignette =newRadialGradient( mRect.centerX(), mRect.centerY(), radius, newint[] { 0, 0, 0x7f000000}, newfloat[] { 0.0f, 0.7f, 1.0f}, Shader.TileMode.CLAMP);
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
27/96
#DV13 #Filth
Vignette
RadialGradientvignette =newRadialGradient( mRect.centerX(), mRect.centerY(), radius, newint[] { 0, 0, 0x7f000000}, newfloat[] { 0.0f, 0.7f, 1.0f}, Shader.TileMode.CLAMP);
Matrixoval =newMatrix();
oval.setScale(1.0f, 0.7f);vignette.setLocalMatrix(oval);
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
28/96
#DV13 #Filth
Vignette
RadialGradientvignette =newRadialGradient( mRect.centerX(), mRect.centerY(), radius, newint[] { 0, 0, 0x7f000000}, newfloat[] { 0.0f, 0.7f, 1.0f}, Shader.TileMode.CLAMP);
Matrixoval =newMatrix();oval.setScale(1.0f, 0.7f);vignette.setLocalMatrix(oval);mPaint.setShader(newComposeShader( mBitmapShader, vignette, PorterDuff.Mode.SRC_O
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
29/96
#DV13 #Filth
Works with any shape
drawCircle() drawPath() drawPath
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
30/96
Animation
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
31/96
#DV13 #Filth
Animation APIs
View properties: ViewPropertyAnimator
Everything else: ObjectAnimator
view.animate().alpha(0).translationX(-500);
ObjectAnimator.ofFloat(view, "someProperty", 0).s
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
32/96
#DV13 #Filth
Timing is Everything
Make those animations short!
And non-linear
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
33/96
ListViewAnimation!
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
34/96
#DV13 #Filth
ListView Animations
Recycling containers are tricky
- Views != items
Avoid per-frame layout
Determine before/after
- animate those changes
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
35/96
#DV13 #Filth
Shadowed Background
protectedvoidonDraw(Canvascanvas) {
if(mShowing) { if(mUpdateBounds) { mShadowedBackground.setBounds(0, 0 getWidth(), mOpenAreaHeight); } canvas.save(); canvas.translate(0, mOpenAreaTop); mShadowedBackground.draw(canvas); canvas.restore(); }}
Thursday, November 14, 13
d d bl
7/27/2019 Filthy Rich Android
36/96
#DV13 #Filth
Adapters and Stable IDspublicclassStableArrayAdapter extendsArrayAdapter { // ... other methods...
@Override
publiclonggetItemId(intposition) { Stringitem =getItem(position); returnmIdMap.get(item); }
@Override publicbooleanhasStableIds() { returntrue; }}
Thursday, November 14, 13
S i i M /F d
7/27/2019 Filthy Rich Android
37/96
#DV13 #Filth
Swiping: Move/Fade
publicbooleanonTouch(finalViewv, MotionEventevent) { switch(event.getAction()) { // skipping DOWN/CANCEL/UP events
caseMotionEvent.ACTION_MOVE: { if(!mSwiping) { if(deltaXAbs >mSwipeSlop) { mSwiping =true; mListView.requestDisallowInterceptTouchEvent(true) mBackgroundContainer.showBackground(v.getTop(), v.getHeight()); }
} if(mSwiping) { v.setTranslationX((x -mDownX)); v.setAlpha(1-deltaXAbs /v.getWidth()); } } break; }}
Thursday, November 14, 13
A i t t
7/27/2019 Filthy Rich Android
38/96
#DV13 #Filth
Animate out
v.animate().setDuration(duration). alpha(endAlpha).translationX(endX) withEndAction(newRunnable() { @Override publicvoidrun() { v.setAlpha(1); v.setTranslationX(0);
animateRemoval(mListView, } });
Thursday, November 14, 13
A i t l i th
7/27/2019 Filthy Rich Android
39/96
#DV13 #Filth
Animate closing the gapprivatevoidanimateRemoval(finalListViewlistview, ViewviewToRemove) { // [ Get startTop for all views ]
// Delete the item from the adapter intposition =mListView.getPositionForView(viewToRemove);
mAdapter.remove(mAdapter.getItem(position));
finalViewTreeObserverobserver =listview.getViewTreeObserver(); observer.addOnPreDrawListener(newViewTreeObserver.OnPreDrawListener() { publicbooleanonPreDraw() { observer.removeOnPreDrawListener(this); for(inti =0; i
7/27/2019 Filthy Rich Android
40/96
CircularReveal!
Thursday, November 14, 13
Circular reveal
7/27/2019 Filthy Rich Android
41/96
#DV13 #Filth
Circular reveal
Thursday, November 14, 13
Circular reveal
7/27/2019 Filthy Rich Android
42/96
#DV13 #Filth
Circular reveal
Technique similar to images with rounded corners
- Uses a BitmapShader
The mask is not a vector shape
Uses an ALPHA_8 bitmap as the mask
- Converted from any type of bitmap
Thursday, November 14, 13
Circular reveal
7/27/2019 Filthy Rich Android
43/96
#DV13 #Filth
Circular reveal
ALPHA_8
bitmap mask
Bitmaptexture
Thursday, November 14, 13
Capturing the content
7/27/2019 Filthy Rich Android
44/96
#DV13 #Filth
Capturing the content
privatestaticBitmapcreateBitmap(Viewtarg Bitmapb =Bitmap.createBitmap( target.getWidth(), target.getHeight( Bitmap.Config.ARGB_8888); Canvasc =newCanvas(b);
target.draw(c); returnb;}
Thursday, November 14, 13
Loading the alpha mask
7/27/2019 Filthy Rich Android
45/96
#DV13 #Filth
Loading the alpha mask
privateBitmaploadAsAlphaMask(intmaskId) { // Attempt to load the bitmap as an alpha mask
BitmapFactory.Optionsopts =newBitmapFactory opts.inPreferredConfig =Bitmap.Config.ALPHA_8; Bitmapb =BitmapFactory.decodeResource( mRes, maskId, opts); // If it failed, extract the alpha if(b.getConfig() ==Bitmap.Config.ALPHA_8) {
returnb; } else{ returnb.extractAlpha(); }}
Thursday, November 14, 13
Setting up the shader
7/27/2019 Filthy Rich Android
46/96
#DV13 #Filth
Setting up the shader
privatevoidcreateShader() { Viewtarget =getRootView().findViewById(mTarg mTargetBitmap =createBitmap(target); ShadertargetShader =newBitmapShader(mTarget Shader.TileMode.CLAMP, Shader.TileMode.CLA
mPaint.setShader(targetShader);}
Thursday, November 14, 13
Drawing the spotlight
7/27/2019 Filthy Rich Android
47/96
#DV13 #Filth
Drawing the spotlight
protectedvoidonDraw(Canvascanvas) { mMatrix.setScale( 1.0f/mMaskScale, 1.0f/mMaskScale) mMatrix.preTranslate(-getMaskX(), -getMas
mPaint.getShader().setLocalMatrix(mMatrix
canvas.translate(getMaskX(), getMaskY()); canvas.scale(mMaskScale, mMaskScale); canvas.drawBitmap(mMask, 0.0f, 0.0f, mPai}
Thursday, November 14, 13
Animating the spotlight
7/27/2019 Filthy Rich Android
48/96
#DV13 #Filth
Animating the spotlight
Thursday, November 14, 13
Animating the spotlight
7/27/2019 Filthy Rich Android
49/96
#DV13 #Filth
Animating the spotlight
Move left & scale up
Thursday, November 14, 13
Animating the spotlight
7/27/2019 Filthy Rich Android
50/96
#DV13 #Filth
Animating the spotlight
Move to center & scale up
Thursday, November 14, 13
Setting up the animations
7/27/2019 Filthy Rich Android
51/96
#DV13 #Filth
Setting up the animations
moveLeft =ObjectAnimator.ofFloat(spot, "maskX", leftscaleUp =ObjectAnimator.ofFloat(spot, "maskScale", moveCenter =ObjectAnimator.ofFloat(spot, "maskX", centmoveUp =ObjectAnimator.ofFloat(spot, "maskY", centscaleUp2 =ObjectAnimator.ofFloat(spot, "maskScale",
Thursday, November 14, 13
Choreographing
7/27/2019 Filthy Rich Android
52/96
#DV13 #Filth
Choreographing
AnimatorSetset =newAnimatorSet()set.play(moveLeft).with(scaleUp);set.play(moveCenter).after(scaleUp)set.play(moveUp).after(scaleUp);set.play(scaleUp2).after(scaleUp);set.start();
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
53/96
#DV13 #Filth
Android 4.4Photo Editor
Thursday, November 14, 13
Filter reveal
7/27/2019 Filthy Rich Android
54/96
#DV13 #Filth
te e ea
Same exact implementation as before
Draws the spotlight on top of original photo
Spots position depends on where you tapped the button
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
55/96
#DV13 #Filth
Google Now
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
56/96
#DV13 #FilthThursday, November 14, 13
7/27/2019 Filthy Rich Android
57/96
#DV13 #FilthThursday, November 14, 13
7/27/2019 Filthy Rich Android
58/96
#DV13 #Filth
Noantialiasing!
Thursday, November 14, 13
Path clipping
7/27/2019 Filthy Rich Android
59/96
#DV13 #Filth
pp g
Pathclip =newPath();clip.addCircle(x, y, radius, Path.Direction.CW);canvas.clipPath(clip);drawContent();
Thursday, November 14, 13
Path clipping
7/27/2019 Filthy Rich Android
60/96
#DV13 #Filth
Pros
- Easy to implement
- Uses less memory
- Faster to setup (no Bitmap copy)
Cons
- Android 4.3+ only with hardware acceleration
- No antialiasing- Can be very expensive
- Increases overdraw
Thursday, November 14, 13
A t
7/27/2019 Filthy Rich Android
61/96
ActivityTransitions!
Thursday, November 14, 13
Custom Activity Transitions
7/27/2019 Filthy Rich Android
62/96
#DV13 #Filth
Standard window animations
- default: scale/fade
- customize: slide, fade, scale
- Also thumbnail scale/crossfade
... But thats it
Totally custom requires in-activity animations
Thursday, November 14, 13
Custom Activity Transitions
7/27/2019 Filthy Rich Android
63/96
#DV13 #Filth
Disable window animations
Animate exiting activity
Launch new activity with transparent window
Animate content when activity comes up
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
64/96
Thursday, November 14, 13
Grayscale thumbnails
7/27/2019 Filthy Rich Android
65/96
#DV13 #Filth
ColorMatrixgrayMatrix =newColorMatrix();grayMatrix.setSaturation(0);ColorMatrixColorFiltergrayscaleFilter = newColorMatrixColorFilter(grayMatrix);
thumbnailDrawable.setColorFilter(grayscaleFil
Thursday, November 14, 13
Drop shadow container
7/27/2019 Filthy Rich Android
66/96
#DV13 #Filth
protectedvoidonDraw(Canvascanvas) { for(inti =0; i
7/27/2019 Filthy Rich Android
67/96
#DV13 #Filth
publicvoidsetShadowDepth(floatdepth) { if(depth !=mShadowDepth) { mShadowDepth =depth; mShadowPaint.setAlpha( (int) (100+150*(1-mShadowDepth) invalidate(); }
}
Thursday, November 14, 13
Transparent activity background
7/27/2019 Filthy Rich Android
68/96
#DV13 #Filth
true true @android:color/transparen
Thursday, November 14, 13
Launch sub-activity
7/27/2019 Filthy Rich Android
69/96
#DV13 #Filth
int[] screenLocation =newint[2];v.getLocationOnScreen(screenLocation);PictureDatainfo =mPicturesData.get(v);
intorientation =getResources().getConfiguration().orientati
IntentsubActivity =newIntent(ActivityAnimations.this, PictureDetailsActivity.class);subActivity.putExtra(PACKAGE+".orientation", orientation). putExtra(PACKAGE+".resourceId", info.resourceId). putExtra(PACKAGE+".left", screenLocation[0]). putExtra(PACKAGE+".top", screenLocation[1]).
putExtra(PACKAGE+".width", v.getWidth()). putExtra(PACKAGE+".height", v.getHeight()). putExtra(PACKAGE+".description", info.description);startActivity(subActivity);
overridePendingTransition(0, 0);
Thursday, November 14, 13
Get animation start values
7/27/2019 Filthy Rich Android
70/96
#DV13 #Filth
Bundlebundle =getIntent().getExtras();Bitmapbitmap =BitmapUtils.getBitmap(getResources(), bundle.getInt(PACKAGE_NAME+".resourceId"));Stringdescription =bundle.getString(PACKAGE_NAME+".descriptifinalintthumbnailTop =bundle.getInt(PACKAGE_NAME+".top");finalintthumbnailLeft =bundle.getInt(PACKAGE_NAME+".left")finalintthumbnailWidth =bundle.getInt(PACKAGE_NAME+".width"finalintthumbnailHeight =bundle.getInt(PACKAGE_NAME+".heighmOriginalOrientation =bundle.getInt(PACKAGE_NAME+".orientatio
Thursday, November 14, 13
Get animation end values
7/27/2019 Filthy Rich Android
71/96
#DV13 #Filth
ViewTreeObserverobserver =mImageView.getViewTreeObserver();observer.addOnPreDrawListener(newViewTreeObserver.OnPreDrawListe @Override
publicbooleanonPreDraw() { mImageView.getViewTreeObserver().removeOnPreDrawListener( int[] screenLocation =newint[2]; mImageView.getLocationOnScreen(screenLocation); mLeftDelta =thumbnailLeft -screenLocation[0]; mTopDelta =thumbnailTop -screenLocation[1]; mWidthScale =(float) thumbnailWidth /mImageView.getWidt mHeightScale =(float) thumbnailHeight /mImageView.getHe
runEnterAnimation();
returntrue; }});
Thursday, November 14, 13
Animate thumbnail & descriptionmImageView setPivotX(0);
7/27/2019 Filthy Rich Android
72/96
#DV13 #Filth
mImageView.setPivotX(0);mImageView.setPivotY(0);mImageView.setScaleX(mWidthScale);mImageView.setScaleY(mHeightScale);mImageView.setTranslationX(mLeftDelta);mImageView.setTranslationY(mTopDelta);mTextView.setAlpha(0);
mImageView.animate().setDuration(duration). scaleX(1).scaleY(1). translationX(0).translationY(0). setInterpolator(sDecelerator). withEndAction(newRunnable() {
publicvoidrun() { mTextView.setTranslationY(-mTextView.getHeight mTextView.animate().setDuration(duration/2). translationY(0).alpha(1). setInterpolator(sDecelerator); } });
Thursday, November 14, 13
Fade in black background
7/27/2019 Filthy Rich Android
73/96
#DV13 #Filth
ObjectAnimator.ofInt(mBackground, "alpha", 0, start();
Thursday, November 14, 13
Colorize thumbnail
7/27/2019 Filthy Rich Android
74/96
#DV13 #Filth
ObjectAnimatorcolorizer =ObjectAnimator.ofFl
PictureDetailsActivity.this, "saturation",colorizer.start();
publicvoidsetSaturation(floatvalue) { colorizerMatrix.setSaturation(value);
ColorMatrixColorFiltercolorizerFilter =newColorMatrixColorFilter(colorizerMa
mBitmapDrawable.setColorFilter(colorizerFi}
Thursday, November 14, 13
Animate drop shadow
7/27/2019 Filthy Rich Android
75/96
#DV13 #Filth
ObjectAnimatorshadowAnim =ObjectAnimator.of mShadowLayout, "shadowDepth", 0, 1);shadowAnim.start();
Thursday, November 14, 13
Animate back to main activity
7/27/2019 Filthy Rich Android
76/96
#DV13 #Filth
@OverridepublicvoidonBackPressed() {
runExitAnimation(newRunnable() { publicvoidrun() { finish(); } });}
@Overridepublicvoidfinish() { super.finish(); overridePendingTransition(0, 0);}
Thursday, November 14, 13
Foldi
7/27/2019 Filthy Rich Android
77/96
FoldingLayout!
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
78/96
#DV13 #Filth
Fan Fare
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
79/96
#DV13 #FilthThursday, November 14, 13
7/27/2019 Filthy Rich Android
80/96
#DV13 #Filth
Matrix.setPolyToPoly()
Thursday, November 14, 13
for(intx =0; x
7/27/2019 Filthy Rich Android
81/96
#DV13 #Filth
src =mFoldRectArray[x]; canvas.save(); canvas.concat(mMatrix[x]);
canvas.clipRect(0, 0, src.width(), src.height()); canvas.translate(-src.left, 0); super.dispatchDraw(canvas); if(x %2==0) { canvas.drawRect(0, 0, mFoldW, mFoldH, mSolidS } else{ canvas.drawRect(0, 0, mFoldW, mFoldH, mSoftSh } canvas.restore();}
Thursday, November 14, 13
for(intx =0; x
7/27/2019 Filthy Rich Android
82/96
#DV13 #Filth
src =mFoldRectArray[x]; canvas.save(); canvas.concat(mMatrix[x]);
canvas.clipRect(0, 0, src.width(), src.height()); canvas.translate(-src.left, 0); super.dispatchDraw(canvas); if(x %2==0) { canvas.drawRect(0, 0, mFoldW, mFoldH, mSolidS } else{ canvas.drawRect(0, 0, mFoldW, mFoldH, mSoftSh } canvas.restore();}
Thursday, November 14, 13
for(intx =0; x
7/27/2019 Filthy Rich Android
83/96
#DV13 #Filth
src =mFoldRectArray[x]; canvas.save(); canvas.concat(mMatrix[x]);
canvas.clipRect(0, 0, src.width(), src.height()); canvas.translate(-src.left, 0); super.dispatchDraw(canvas); if(x %2==0) { canvas.drawRect(0, 0, mFoldW, mFoldH, mSolidS } else{ canvas.drawRect(0, 0, mFoldW, mFoldH, mSoftSh } canvas.restore();}
Thursday, November 14, 13
for(intx =0; x
7/27/2019 Filthy Rich Android
84/96
#DV13 #Filth
src =mFoldRectArray[x]; canvas.save(); canvas.concat(mMatrix[x]);
canvas.clipRect(0, 0, src.width(), src.height()); canvas.translate(-src.left, 0); super.dispatchDraw(canvas); if(x %2==0) { canvas.drawRect(0, 0, mFoldW, mFoldH, mSolidS } else{ canvas.drawRect(0, 0, mFoldW, mFoldH, mSoftSh
} canvas.restore();}
Thursday, November 14, 13
Color Filters
7/27/2019 Filthy Rich Android
85/96
#DV13 #Filth
Can be used to modify a shader
Subclasses of ColorFilter
- ColorMatrixColorFilter
- LightingColorFilter
- PorterDu!ColorFilter
Thursday, November 14, 13
Sepia Effect
7/27/2019 Filthy Rich Android
86/96
#DV13 #Filth
ColorMatrixm1 =newColorMatrix();ColorMatrixm2 =newColorMatrix();
m1.setSaturation(0.1f);m2.setScale(1f, 0.95f, 0.82f, 1.0f);
m1.setConcat(m2, m1);
mSepiaPaint.setColorFilter( newColorMatrixColorFilter(m1));
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
87/96
Performance
Thursday, November 14, 13
Smoother is Better
C i t t f t
7/27/2019 Filthy Rich Android
88/96
#DV13 #Filth
Consistent frame rate
Avoid hiccups
Avoid large steps over few frames
Thursday, November 14, 13
Only Draw What You Need (ODWYN)
P f i lid t (l t b) i lid t ()
7/27/2019 Filthy Rich Android
89/96
#DV13 #Filth
Prefer invalidate(l, t, r, b) over invalidate()
Only invalidate custom views that actually change
Let the framework invalidate standard views
Thursday, November 14, 13
Avoid Overdraw
Developer options > Show Overdraw
7/27/2019 Filthy Rich Android
90/96
#DV13 #Filth
Developer options -> Show Overdraw
Window background vs. opaque containers vs. opaque vi
Thursday, November 14, 13
Get Off that UI Thread!
Avoid expensive operations on UI thread
7/27/2019 Filthy Rich Android
91/96
#DV13 #Filth
Avoid expensive operations on UI thread
- network, database, bitmaps, ...
AsyncTask is your friend
Thursday, November 14, 13
Avoid Garbage Collection
especially during animations
7/27/2019 Filthy Rich Android
92/96
#DV13 #Filth
... especiallyduring animations
Lots of small objects will eventually cause GC
Avoid Iterators, temporary objects- Consider cached objects for temporaries
Use Allocation Tracker in DDMS
Thursday, November 14, 13
clipPath
Not always the fastest way to clip to a path
7/27/2019 Filthy Rich Android
93/96
#DV13 #Filth
Not always the fastest way to clip to a path
Doesnt support antialiasing
Try BitmapShader
Thursday, November 14, 13
Consider Time Travel
Go see Android Performance Workshop 2 days ago
7/27/2019 Filthy Rich Android
94/96
#DV13 #Filth
Go see Android Performance Workshop 2 days ago
- Memory
- Performance tips- Tools
- Case studies
Thursday, November 14, 13
For More Information
ChetRomain:
7/27/2019 Filthy Rich Android
95/96
#DV13 #Filth
Google I/O talks
Parleys.com talks
Devbytes on YouTube
graphics-geek.blogspot.com
google.com/+ChetHaase
@chethaase
curious-creature.org
google.com/+RomainGuy
@romainguy
Thursday, November 14, 13
7/27/2019 Filthy Rich Android
96/96
#DV13 #Filth
Filthy Rich Clients: Developing
Animated and Graphical E!ects
Thursday, November 14, 13