android ui tips & tricks

32
Android UI Tips & Tricks Shem Magnezi

Upload: shemmag

Post on 23-Aug-2014

283 views

Category:

Mobile


7 download

DESCRIPTION

Presentation from DroidCon 2014: - Working with images - Bring your views into life with animations - Upgrade your lists views

TRANSCRIPT

Page 1: Android ui tips & tricks

Android UI Tips & TricksShem Magnezi

Page 2: Android ui tips & tricks

Making your good app great

Know your app

Understand what you need

No magic/ generic solutions

You know how to write a good app

Looks good Feel slick

Not gonna talk about viral/

design/ downloads etc...

Page 3: Android ui tips & tricks

Agenda

● Working with images● Bring your views into life with animations● Upgrade your lists views

Page 4: Android ui tips & tricks

Working with images

Page 5: Android ui tips & tricks

Cache Cache Cache

● Use cache for performance● Be careful not using too much memory

Page 6: Android ui tips & tricks

Images in memory

Bitmap memory size:Bitmap.getWidth() * Bitmap.getHeight() * Bitmap.config

Determine how much the bitmap gonna take:Image.width * Image.height * Options.config / Options.sampleSize

Page 7: Android ui tips & tricks

Determine your cache size

● Approximate per-application memory: getSystemService(Context.ACTIVITY_SERVICE).getMemoryClass()

● Pay attention to: onTrimMemory(int level) on your Application

● Profile your memory

usage live

Page 8: Android ui tips & tricks

Loading the proper image type

For small image views work with thumbnails:MediaStore.Images.Thumbnails.getThumbnail(

..., int kind, ...)

MINI_KIND: 512 x 384

MICRO_KIND: 96 x 96

Page 9: Android ui tips & tricks

Sample size

Original size is probably too big, so load smaller size.

Original

inSampleSize=2

memory/4

Page 10: Android ui tips & tricks

Determine the right sample size

● Get the original image size using: options.inJustDecodeBounds = true;

● Get the view that gonna present the image● Find the minimum sample_size so:

○ image.width / sample_size > view.width ○ image.height / sample_size > view.height

○ it also prefer that sample_size will be power of 2 for faster/ easier decoding

Page 11: Android ui tips & tricks

Find your view size

Sometimes your view size is 0 (cause is not yet drawn), so you should wait until the system will draw it:

view.getViewTreeObserver().addOnGlobalLayoutListener(

new OnGlobalLayoutListener() {

public void onGlobalLayout() {

//load image for the right size

}

});

}

Page 12: Android ui tips & tricks

Determine image sizeCENTER_CROP

float scale = Math.max(viewW / imgW, viewH / imgH)

float scaledWidth = scaale * viewW;

float scaledHeight = scale * viewHt;

CENTER_INSIDE

float scale = Math.min(viewW / imgW, viewH / imgH)

float scaledWidth = scaale * viewW;

float scaledHeight = scale * viewHt;

Page 13: Android ui tips & tricks

Make your cache a bit smarterget(Item image, Size size) {

cached = getImage(image);

if (cached != null) {

if (cached.size >= size) {

//saved time!

} else {

//maybe display a lower

//resolution until loading

//the full image

}

} else {

//photo not in cache, but we

//did our best

}

}

put(Item image, Size size) {

if (size < MICRO_KIND_SIZE) {

//load micro kind thumbnail

} else if (size < MINI_KIND_SIZE) {

//load mini kind thumbnail

} else {

//read the full image with the

//right sample size

}

}

Page 14: Android ui tips & tricks

Bitmap config

ARG_565 has no alpha channel and is it in lower quality

But:

● It’s ~x2 faster to load● It consume half of the

memory● Most of the time you won’t

see any difference

source: Romain Guy

Page 15: Android ui tips & tricks

Animations

Page 16: Android ui tips & tricks

Interpolator

Sometimes you can use interpolator instead of couple of sequenced animations.For example, the built-in bounce animation on android.

Page 17: Android ui tips & tricks

Between-activities animationsSet activity style:

<item name="android:windowBackground">@android:color/transparent</item>

When moving to this activity:

startActivity(intent);

overridePendingTransition(0, 0);

Do the animation:

ViewTreeObserver observer = animationImage.getViewTreeObserver();

observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

public boolean onPreDraw() {

animationImage.getViewTreeObserver().removeOnPreDrawListener(this);

runEnterAnimation(back, startBounds);

}

});

Page 18: Android ui tips & tricks

Pre drawer listener?

Very useful for animations!● Create enter animation to your activity● Create animation to your view when it’s

added to the screen● Animate list items when the list changes

Page 19: Android ui tips & tricks

Smart image animation

Page 20: Android ui tips & tricks

Case #1Scaling animation for the image view:ObjectAnimator.ofFloat(image_1, "scaleY", 1, 1.5f);

<ImageView

android:id="@+id/image_1"

android:layout_width="225dp"

android:layout_height="150dp"

android:scaleType="centerCrop"

/>

When animating the view there is no re-layout and the image not preserving it’s scale type

Page 21: Android ui tips & tricks

Case #2Use a frame and do a reverse scaling to the inner image:<RelativeLayout android:id="@+id/image_2"

android:layout_width="225dp"

android:layout_height="150dp">

<ImageView android:id="@+id/inner_image"

android:layout_width="225dp"

android:layout_height="300dp"

android:layout_marginTop="-75dp"

android:layout_marginBottom="-75dp"/>

</RelativeLayout>

anim.playTogether(

ObjectAnimator.ofFloat(image_2, "scaleY", 1, 1.5f),ObjectAnimator.ofFloat(inner, "scaleY", 1f, 0.6666f));

● Lots of calculations

● The animation is not linear

● Need an extra view

Page 22: Android ui tips & tricks

Case #3Use an extra image as the target view:anim.playTogether(

ObjectAnimator.ofFloat(image_3, "scaleY", 0.6666f, 1f),

ObjectAnimator.ofFloat(image_3, "alpha", 0, 1));

<ImageView

android:id="@+id/image_3"

android:layout_width="225dp"

android:layout_height=" 225dp"

android:scaleType="centerCrop"

/>

● You are losing the original view

● The animation isn’t smooth

Page 23: Android ui tips & tricks

Case #4Implement you own Animation:public class ExpandAnimation extends Animation {

protected void applyTransformation(float inp ...) {

...

if (inp < 1.0f) {

lp.height =(int)(start + (end - start)* inp);

mAnimatedView.requestLayout();

}

}

<ImageView android:id="@+id/image_4"

android:layout_width="225dp"

android:layout_height="150dp"

android:scaleType="centerCrop" />

Page 24: Android ui tips & tricks

Working with Lists

Page 25: Android ui tips & tricks

The basic things

● Reuse items● ViewHolder pattern● Long tasks should run in background with

AsyncTask● Cancel view loading tasks using

RecyclerListener

● Use ListFragment

Page 26: Android ui tips & tricks

Profile your drawing

● Design your layout as flat as you can● Avoid over drawing or nested weights● Profile your list using GPU overdraw and

GPU Rendering in developer options

Page 27: Android ui tips & tricks

Empty view in your ListFragment

Use android:id="@android:id/empty"

for the case the list is empty

<ListView

android:id="@android:id/list"

… />

<RelativeLayout

android:id="@android:id/empty"

... />

Page 28: Android ui tips & tricks

Save each item state

In your adapter:Set<Integer> opened = HashSet<Integer>();

On widget opened:opened.add(item.getId());

In getView():view.setOpened(opened.contains(item.getId());

Page 29: Android ui tips & tricks

Scrolled view inside ListViewYou sometime want to put a view that can be scrolled by himself as one of your listview items- for example putting a grid view of images.

For doing it you must let layout manager that this view must take it’s full size:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,

MeasureSpec.AT_MOST);

super.onMeasure(widthMeasureSpec, heightSpec);

getLayoutParams().height = getMeasuredHeight();

}

source: stackoverflow.com

Page 30: Android ui tips & tricks

Smart scrollbar for easy navigation

● Put a relative view that contains your list view and set him as a OnScrollListener

● On onScroll calc the right position of your scroller view using totalItemCount and visibleItemCount

● On draw put your scroller view using setTranslationY

Page 31: Android ui tips & tricks

Smart scrollbar for easy navigationYou can even add a behavior for dragging the scroller using onTouchEvent:public boolean onTouchEvent(MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {

if (//event in scroll bar view)

mDragging = true;

} else if (me.getAction() == MotionEvent.ACTION_UP) {

if (mDragging)

mDragging = false;

} else if (me.getAction() == MotionEvent.ACTION_MOVE) {

if (mDragging)

mList.setSelectionFromTop(//calc the right item index, 0);

}

}

Page 32: Android ui tips & tricks

[email protected]

Thank you.