Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

82

Click here to load reader

Transcript of Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Page 1: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Animate me !

#AnimateMeby(Mathias Seguy == Android2EE){

French Android Trainer}

Page 2: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Animate me ! If you don't do it for me,

do it for chet !

Page 3: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Demonstration !

The Tutorial

Page 4: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Animation is lifeAnimation is comprehensionAnimation is engagements

Animation is delighted your UXAnimation is necessary

Animation is simple

Why animations?

Page 5: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Make Animations simple

Animations framework's goal ?

Page 6: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Because we want you to animate your

application !Chris Banes Bruno

OliveiraRoman Nurick

Adam Powell

Chet Haase Reto Meier Taylor Ling

Romain Guy

Animations framework's goal ?

Page 7: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Animations Elementary Principles

Page 8: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Alpha Rotate

TranslateScale

And the plan transformations are yours

V1

<set android:interpolator="@[package:]anim/interpolator_resource">    <alpha        android:duration="float" android:fromAlpha="float" android:toAlpha="float" />    <scale        android:duration="float"        android:fromXScale="float" android:toXScale="float"        android:fromYScale="float" android:toYScale="float"        android:pivotX="float" android:pivotY="float" />    <translate        android:duration="float"        android:fromXDelta="float" android:toXDelta="float"        android:fromYDelta="float" android:toYDelta="float" />    <rotate        android:duration="float"        android:fromDegrees="float" android:toDegrees="float"        android:pivotX="float" android:pivotY="float" />    <set>        ...    </set></set>

Animation animIn= AnimationUtils.loadAnimation(ctx, R.anim.generic_anim);edtMessage.startAnimation(animIn);

animation/generic_anim.xml

Only change pixels not the state of the view

What we know: Tween Animations

Page 9: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Makes animations generic

V11

/** * The in Animation for after HC */AnimatorSet animInHC;

animInHC = (AnimatorSet) AnimatorInflater.loadAnimator(ctx, R.animator.generic_anim);animInHC.setTarget(edtMessage);animInHC.setTarget(btnAdd);animInHC.start();

<set > <objectAnimator android:duration="1000" android:propertyName="translationX" android:valueFrom="-250" android:valueTo="0" android:valueType="floatType" />

<objectAnimator android:duration="1000" android:propertyName="scaleX" android:valueFrom="0.0" android:valueTo="1.0" android:valueType="floatType" /> </set>

animator-v11/generic_anim.xml

Changes the state of the object

What we know: ObjectAnimator

Page 10: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Uses Handler and RunnableSimple but dangerous (memory leak, runs in UI thread,

can generates frames drops)Not optimized

Animation is changing the view/object state by dropping changes in the UI thread

Handler clipDrawableHandler=new Handler();Runnable clipDrawableRunnable=new Runnable() { @Override

public void run() {myView.changeSomething(level);clipDrawableHandler.postDelayed(clipDrawableRunnable,32);

}};

V1

Animation: Elementary principles

Page 11: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Uses Handler and RunnableSimple but dangerous (memory leak, runs in UI thread,

can generates frames drops)Not optimized

V11

Animation is changing the view/object state by dropping changes in the UI thread

Animation: Elementary principles

Handler clipDrawableHandler=new Handler();Runnable clipDrawableRunnable=new Runnable() { @Override

public void run() {myView.changeSomething(level);clipDrawableHandler.postDelayed(clipDrawableRunnable,32);

}};

Have to be replaced by ObjectAnimator when

Gingerbread is out of scope

Page 12: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Make movement real :Interpolators are simple

Page 13: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Don't be scared, it's simple. How do you go from the point from to the point to ?

V1

t1t0v0

v1

from

to?i(t)=v,

where i(t0)=v0 and i(t1)=v1

float

time

Interpolators

Page 14: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

It can be straight

V1

t1t0v0

v1

from

to

linear

Interpolators

Page 15: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

t1t0v0

v1

You can use the system's ones

V1

t1t0v0

v1

from

to

deceleration acceleration

to

fromt1t0v0

v1to

bouncing

from

<set android:interpolator="@android:anim/accelerate_interpolator">

<set android:interpolator="@android:anim/decelerate_interpolator">

<set android:interpolator="@android:anim/

bounce_interpolator">

Interpolators

Page 16: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Or build your own.V1

t1t0v0

v1

from

to

alcoholicpublic class MyInterpolator implements Interpolator { float v; @Override public float getInterpolation(float input) { //v=i(input) return v; }...}

Interpolators

Page 17: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Drawables are our best friends

Page 18: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

myDrawable= (ImageView)findViewById(R.id.imvToto).getDrawable();

<ImageView android:id="@+id/imvToto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/my_drawable"/>

V1

Think Drawables

Page 19: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawableHandler clipDrawableHandler=new Handler();Runnable clipDrawableRunnable=new Runnable() {

@Override public void run() {level++;

clipDrawableHorizontal.setLevel(level); clipDrawableHandler.postDelayed(clipDrawableRunnable,32); }};

<?xml version="1.0" encoding="utf-8"?><clip xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_android2ee" android:clipOrientation="horizontal" android:gravity="left" />

V1

Think Drawables

Page 20: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

RotateDrawable rotateDrawableWheel;Handler rotateDrawableHandler=new Handler();Runnable rotateDrawableRunnable=new Runnable() {public void run() {level++;

rotateDrawableWheel.setLevel(level);rotateDrawableHandler.postDelayed(rotateDrawableRunnable,32);

}};

<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_android2ee" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" />

V1

ClipDrawableRotateDrawable

ScaleDrawableAnimationDrawableTransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

Think Drawables

Page 21: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

ScaleDrawable scaleDrawable;Handler scaleDrawableHandler=new Handler();Runnable scaleDrawableRunnable=new Runnable() {public void run() {level++;

scaleDrawable.setLevel(level);scaleDrawableHandler.postDelayed(scaleeDrawableRunnable,32);

}};

<?xml version="1.0" encoding="utf-8"?><scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/ic_edit" android:scaleGravity="center" android:scaleHeight="100%" android:scaleWidth="100%" />

V1

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

Think Drawables

Page 22: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

animationDrawable.start();

<animation-list android:id="@+id/selected" android:oneshot="false"> <item android:drawable="@drawable/attack_magic1" android:duration="100" /> <item android:drawable="@drawable/attack_magic2" android:duration="100" /> <item android:drawable="@drawable/attack_magic3" android:duration="100" /> <item android:drawable="@drawable/attack_magic4" android:duration="100" /></animation-list>

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

V1

Think Drawables

Page 23: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

transitionDrawable.startTransition(3000); transitionDrawable.reverseTransition(3000);

<?xml version="1.0" encoding="utf-8"?><transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/ic_ok" /> <item android:drawable="@mipmap/ic_nok" /></transition>

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawable

StateListDrawableAnimatedStateListDrawa

bleAnimatedVectorDrawable

V1

Think Drawables

Page 24: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" android:enterFadeDuration="300" android:exitFadeDuration="300"> <!--Sorry below v21 there is no animated selector you can just fade in and fade out--> <item android:id="@+id/item_pressed"

android:state_pressed="true"> <bitmap android:src="@drawable/ic_android2ee"/></item>

<item android:id="@+id/item_normal"> <bitmap android:src="@drawable/ic_nut"/> </item>

</selector>

fade fade

Normal

Pressed

Normal

View state

Display

V1

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawable

StateListDrawableAnimatedStateListDrawa

bleAnimatedVectorDrawable

Think Drawables

Page 25: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

<?xml version="1.0" encoding="utf-8"?><animated-selector > <item android:id="@+id/item_pressed"

android:state_pressed="true"> <bitmap android:src="@drawable/ic_android2ee"/></item>

<item android:id="@+id/item_normal"> <bitmap android:src="@drawable/ic_nut"/> </item>

<transition android:fromId="@+id/item_pressed" android:toId="@+id/item_normal"> <animation-list android:id="@+id/selected"

android:oneshot="true"> <item android:drawable="@drawable/attack_magic1"

android:duration="100" /> <item android:drawable="@drawable/attack_magic2"

android:duration="100" /></animation-list></transition></animated-selector>

V21

Normal

Pressed

Normal

View state

Display

ClipDrawableRotateDrawableScaleDrawable

AnimationDrawableTransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

Think Drawables

Page 26: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

<?xml version="1.0" encoding="utf-8"?><vector android:viewportWidth="500" android:viewportHeight="500" android:width="500px" android:height="500px"> <!--Make group to animate them separately using ObjectAnimator--> <!--Define the pivot in the group they will be used by ObjectAnimator--> <group android:name="tete" android:pivotX="250.0" android:pivotY="100.0"> <path android:name="head" android:fillColor="#9FBF3B" android:pathData="..." /> </group>...</vector>

<?xml version="1.0" encoding="utf-8"?>

<animated-vector android:drawable="@drawable/my_svg" > <target android:name="tete" android:animation="@anim/anim_svg"

/></animated-vector>

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- res/anim/rotation.xml --><objectAnimator android:duration="6000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" />

</set>

drawable/my_svg drawable/my_svg_animated anim/anim_svg

use

use

layout/my_view

use

<ImageView android:id="@+id/imvAnimatedVector" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/my_svg_animated"/>

use

animatedVectorDrawable.start();

V21

AnimatedVectorDrawable: Animate Shapes

TransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

Page 27: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

<?xml version="1.0" encoding="utf-8"?><vector android:viewportWidth="500" android:viewportHeight="500" android:width="500px" android:height="500px"> <!--Make group to animate them separately using ObjectAnimator--> <!--Define the pivot in the group they will be used by ObjectAnimator--> <group android:name="tete" android:pivotX="250.0" android:pivotY="100.0"> <path android:name="head" android:fillColor="#9FBF3B" android:pathData="..." /> </group>...</vector>

<?xml version="1.0" encoding="utf-8"?>

<animated-vector android:drawable="@drawable/my_svg" > <target android:name="tete" android:animation="@anim/animpath_svg"

/></animated-vector>

<?xml version="1.0" encoding="utf-8"?><set > <!-- res/anim/rotation.xml --> <objectAnimator android:duration="6000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType"/>

</set>

drawable/my_svg drawable/my_svg_animated anim/animpath_svg

use

use

layout/my_view

use

<ImageView android:id="@+id/imvAnimatedVector2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/my_svg_animated"/>

use

animatedVectorDrawable.start();

V21

AnimatedVectorDrawable: Morph Shapes

TransitionDrawableStateListDrawable

AnimatedStateListDrawable

AnimatedVectorDrawable

Page 28: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

The constraints that kill for path transformation: "Note that the paths must be compatible for morphing.

In more details, the paths should have exact same length of commands , and exact same length of

parameters for each commands."

It means: you won't use it expect for so simple trick (arrow to hamburger).=>Waiting for tools !

AnimatedVectorDrawable: Morph Shapes constraintV21

Page 29: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

And here it is !!!https://github.com/bonnyfone/vectalign

V21

AnimatedVectorDrawable: Morph Shapes tool

Page 30: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

To create Svg and/or simplify themhttps://inkscape.org/

To convert Svg into VectorDrawablehttp://inloop.github.io/svg2android/

A good practice :Define your path in a String file (res\values\my_path_string.xml)

V21

AnimatedVectorDrawable: others needed tools

But even with that it's the hell on earth=>working on a Github project

Page 31: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Others best friends

Animation is simple

Page 32: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Make it simple and magic: You can animate any view

translationX , translationY, rotationX, rotationY, rotation, scaleX, scaleY, pivotX,pivotY, x,y,alpha and more

with one line of code !

myView.animate().setDuration(300).x(20).rotationY(60).start();

V13

ViewPropertyAnimator

Page 33: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

myView.animate().rotation(360);is equivalent to

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f).start();

ViewPropertyAnimator is based on ObjectAnimatorV13

Page 34: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Makes animations simple, magic and generic

V13

ObjectAnimator Demystify

Page 35: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

First extends what you want (Object or View or what ever)

public class BlueDot extends View {

V13

ObjectAnimator Demystify

Page 36: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Define the property to animate using set/*MyProperty*/

public class BlueDot extends View {/** * The property to animate * * @param parameter value of the state to calculate the animation of the object */

private void setToto(int parameter) {/*Do your stuff, (call invalidate to redraw view)*/

V13

ObjectAnimator Demystify

Page 37: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Then animatepublic class BlueDot extends View {/** * The property to animate * @param parameter value of the state to calculate the animation of the object */private void setToto(int parameter) {/*Do your stuff,(call invalidate to redraw view)*/

ObjectAnimator.ofInt(blueDot, "toto", 0, 110) .start();

V13

ObjectAnimator Demystify

Page 38: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

ClipDrawable

Handler clipDrawableHandler=new Handler();Runnable clipDrawableRunnable=new Runnable() {

@Override public void run() {level++;

clipDrawableHorizontal.setLevel(level); clipDrawableHandler.postDelayed(clipDrawableRunnable,32); }};

<?xml version="1.0" encoding="utf-8"?><clip xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_android2ee" android:clipOrientation="horizontal" android:gravity="left" />

It was before

Works with every think !V13

ObjectAnimator Demystify

Page 39: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Works with every think !

public class MyActivity extends Activity{

private void setMoveDrawable(int level){ clipDrawableHorizontal.setLevel(level); }

private void animateDrawable() { ObjectAnimator.ofInt(this, "MoveDrawable", 0, 10000).start();}

No more Handler neither Runnable !!!yes thanks Chet !

V13

ObjectAnimator Demystify

Page 40: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Scene Transition

Page 41: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Demonstration !

Scene and Transitionv16

Page 42: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

One xml line to add<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/llSceneRoot" android:animateLayoutChanges="true">

v16Scene and Transition

Page 43: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

One xml line to add<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/llSceneRoot" android:animateLayoutChanges="true">

One line of code to addif(postICS){ LayoutTransition transition = ((ViewGroup)findViewById(R.id.llSceneRoot)).getLayoutTransition(); // New capability as of Jellybean; monitor the container for *all* layout changes // (not just add/remove/visibility changes) and animate these changes as well.(==size) transition.enableTransitionType(LayoutTransition.CHANGING);}

v16Scene and Transition

Page 44: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

v16

Activities transitions

v8

Page 45: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

You have the choice between Custom animation

Intent slidingActivity = new Intent(this, SlidingActivity.class);ActivityCompat.startActivity(this, slidingActivity, translationBundle);}

v16Activities transitions

v8

Bundle translationBundle = ActivityOptionsCompat.makeCustomAnimation(this, R.anim.anim_push_left_in_a2ee,R.anim.anim_push_left_out_a2ee).toBundle();

Page 46: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

You have the choice between Custom animation

Scaling Component

Intent slidingActivity = new Intent(this, SlidingActivity.class);ActivityCompat.startActivity(this, slidingActivity, translationBundle);}

v16Activities transitions

v8

Bundle translationBundle = ActivityOptionsCompat.makeCustomAnimation(this, R.anim.anim_push_left_in_a2ee,R.anim.anim_push_left_out_a2ee).toBundle();

Bundle translationBundle = ActivityOptionsCompat.makeScaleUpAnimation(btnScaling,0,0,btnScaling.getWidth(),btnScaling.getHeight() ).toBundle();

Page 47: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

You have the choice between: Custom animation

Scaling Component

Scaling bitmap

Intent slidingActivity = new Intent(this, SlidingActivity.class);ActivityCompat.startActivity(this, slidingActivity, translationBundle);}

Bundle translationBundle = ActivityOptionsCompat.makeCustomAnimation(this, R.anim.anim_push_left_in_a2ee,R.anim.anim_push_left_out_a2ee).toBundle();

Bundle translationBundle = ActivityOptionsCompat.makeScaleUpAnimation(btnScaling,0,0,btnScaling.getWidth(),btnScaling.getHeight() ).toBundle();

Bundle translationBundle = ActivityOptionsCompat.makeThumbnailScaleUpAnimation(imvSmiley,bitmap,0,0).toBundle();

v16Activities transitions

v8

Page 48: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

You have the choice between: Custom animation

Scaling Component

Scaling bitmap

You need to reverse :

public class otherActivity extends Activity {public void finish() { super.finish(); //this work for all version superior to level 5 overridePendingTransition(R.anim.anim_push_right_in_a2ee, R.anim.anim_push_right_out_a2ee);}}

v16Activities transitions

v8

Page 49: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

AwesomeFirst manage your theme

<resources> <!-- Thanks to :--> <!-- http://code.tutsplus.com/tutorials/introduction-to-the-new-lollipop-activity-transitions&#45;&#45;cms-23711--> <!-- Base application theme. --> <style name="AppTheme" parent="BaseTheme"> <!-- Set the transition between activities effective --> <item name="android:windowContentTransitions">true</item>

<item name="android:windowEnterTransition">@android:transition/slide_bottom</item> <item name="android:windowExitTransition">@android:transition/slide_bottom</item>

<item name="android:windowAllowEnterTransitionOverlap">true</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> <item name="android:windowSharedElementEnterTransition">@android:transition/move</item> <item name="android:windowSharedElementExitTransition">@android:transition/move</item>

</style></resources>

v21New Activities transitions

Page 50: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Set the android:transitionName to your components<ImageButton android:id="@+id/ibtnSprite" android:transitionName="@string/imvSprite_transition" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_gravity="center" android:src="@drawable/attack_magic_animation" />

<ImageView android:id="@+id/imvSprite" android:transitionName="@string/imvSprite_transition" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/attack_magic_animation" />

layout/main_activity layout/other_activity

v21New Activities transitions

Page 51: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Make your pairs and launch the new Activity

if (isPostLollipop) { ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( this, new Pair<View, String>(imvSprites, getString(R.string.imvSprite_transition)), ); }

ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle());}

v21New Activities transitions

Page 52: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

The best for the end !

V7

Page 53: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

53

RecyclerViewV7

Page 54: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

54

BuildGradle: Add the library

dependencies { ... compile 'com.android.support:recyclerview-v7:23.0.1'

<!-- A RecyclerView with some commonly used attributes --><android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />

Use the support.v7.widget.RecyclerView

V7

Page 55: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

55

Principle

RecyclerView

Adapter

ViewHolder

LayoutManager

ItemAnimator ItemDecoratorItemView management

(ClickListener,Animation...)

dataSet

V7

Page 56: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

56

RecyclerView: codeIts the natural evolution of the ListView, the ViewHolder is the one responsible of the view management

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View myView=inflater.inflate(R.layout.recyclerview,container,false);

recyclerView= (RecyclerView) myView.findViewById(R.id.my_recycler_view);

// use a layout manager recyclerViewLayoutManager = getLayoutManager(); recyclerView.setLayoutManager(recyclerViewLayoutManager);

// specify an adapter (see also next example) recyclerViewAdapter = new RecyclerViewAdapter(humans,getActivity()); recyclerView.setAdapter(recyclerViewAdapter); return myView ;}

find the View

set the LayoutManager

set the Adapter

Same principles as for ListView

V7

Page 57: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

57

RecyclerView: The AdapterCodeThis is the same code as for the ListView (ViewHolder next slide)

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{

/****Attributes (t for temp)**/ private ArrayList<Human> humans; private LayoutInflater inflater; private View tNewView; private ViewHolder tViewHolder; private Human tHuman;

/****** Constructor**/ public RecyclerViewAdapter(ArrayList<Human> dataSet,Context ctx){ humans=dataSet; inflater=LayoutInflater.from(ctx); }

@Override public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { tNewView=inflater.inflate(R.layout.simple_item,parent,false); tViewHolder=new ViewHolder(tNewView); return tViewHolder; }

@Override public void onBindViewHolder(RecyclerViewAdapter.ViewHolder holder, int position) { tHuman=humans.get(position); holder.getTxvName().setText(tHuman.getName()); holder.getTxvFirstName().setText(tHuman.getFirstName()); holder.getTxvMessage().setText(tHuman.getMessage()); } @Override public int getItemCount() { return humans.size(); }

V7

Page 58: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

58

RecyclerView: The AdapterCodeThis is the same code as for the ListView (ViewHolder next slide)

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{

/****Attributes (t for temp)**/ private ArrayList<Human> humans; private LayoutInflater inflater; private View tNewView; private ViewHolder tViewHolder; private Human tHuman;

/****** Constructor**/ public RecyclerViewAdapter(ArrayList<Human> dataSet,Context ctx){ humans=dataSet; inflater=LayoutInflater.from(ctx); }

@Override public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { tNewView=inflater.inflate(R.layout.simple_item,parent,false); tViewHolder=new ViewHolder(tNewView); return tViewHolder; }

@Override public void onBindViewHolder(RecyclerViewAdapter.ViewHolder holder, int position) { tHuman=humans.get(position); holder.getTxvName().setText(tHuman.getName()); holder.getTxvFirstName().setText(tHuman.getFirstName()); holder.getTxvMessage().setText(tHuman.getMessage()); } @Override public int getItemCount() { return humans.size(); }

Inflate the view and its viewHolderReturn the ViewHolder

Update the View using the ViewHolder

Set your DataSet and your LayoutInflater

V7

Page 59: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

59

RecyclerView: Le code de l'AdapterLe ViewHolder gère la vue qu'il encapsule

public class ViewHolder extends RecyclerView.ViewHolder{ TextView txvName=null; TextView txvFirstName=null; TextView txvMessage=null; View.OnClickListener clickListener; int position;

public ViewHolder(View itemView) { super(itemView); txvName= (TextView) itemView.findViewById(R.id.txvName); txvFirstName= (TextView) itemView.findViewById(R.id.txvFirstName); txvMessage= (TextView) itemView.findViewById(R.id.txvMessage); clickListener=new View.OnClickListener() { public void onClick(View v) {changeTxvMessageVisibilityState(); } }; itemView.setOnClickListener(clickListener); }

public TextView getTxvFirstName() {return txvFirstName;} public TextView getTxvMessage() {return txvMessage;} public TextView getTxvName() {return txvName;} public void changeTxvMessageVisibilityState(){ //Do the stuff }}

V7

Page 60: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

60

RecyclerView: Les LayoutManagerLe LinearLayoutManager

public RecyclerView.LayoutManager getLayoutManager() { return new LinearLayoutManager(getContext());}

V7

Page 61: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

61

RecyclerView: Les LayoutManagerLe StaggeredLayoutManager

public RecyclerView.LayoutManager getLayoutManager() {

StaggeredGridLayoutManager stagLayoutManager=new StaggeredGridLayoutManager(2,GridLayoutManager.VERTICAL);

stagLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);

return stagLayoutManager;}

V7

Page 62: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

62

RecyclerView: Les LayoutManagerLe GridLayoutManager

public RecyclerView.LayoutManager getLayoutManager() {

GridLayoutManager gridLayoutManager=new GridLayoutManager(getContext(),2,GridLayoutManager.VERTICAL,false);

//define specific span of specific cells according to a rule gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int arg0) { return (arg0 % 3) == 0 ? 2 : 1; } }); return gridLayoutManager;}

V7

Page 63: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

63

CoordinatorLayout

Tutoriaux:RecyclerView

V7

Page 64: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

64

BuildGradle: Add the library

dependencies { ... compile 'com.android.support:design:23.0.1'

V7

Page 65: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

65

All is done in the Layout file

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".CoordinatorLayout">

The parent Layout of all yours Layouts: The CoordinatorLayoutV7

Page 66: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

66

V7

Everything is done in the layout

<android.support.design.widget.CoordinatorLayout >

<android.support.design.widget.AppBarLayout ... android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<android.support.v7.widget.Toolbar ... app:layout_scrollFlags="scroll|enterAlways"/>

<android.support.design.widget.TabLayout ... android:fillViewport="true"/>

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager //Your content ... app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout >

Page 67: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

67

V7

Going further with the CollapsingToolBarLayout<android.support.design.widget.AppBarLayout ... > <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp">

<ImageView ... android:fitsSystemWindows="true" app:layout_collapseMode="parallax" />

<android.support.v7.widget.Toolbar ... app:layout_scrollFlags="scroll|enterAlways"/>

<android.support.design.widget.TabLayout ... android:fillViewport="true"/>

</android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout>

Page 68: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

68

V7

Plus complexe avec CollapsingToolBarLayout

<android.support.design.widget.AppBarLayout...>

<android.support.design.widget.CollapsingToolbarLayout...>

<ImageView.../>

<android.support.design.widget.TabLayout .../>

<android.support.v7.widget.Toolbar.../>

</android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

Set the title of the ActionBar on the CollapsingToolbarLayout not

on the ToolBar!

Page 69: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

69

V7

Plus complexe avec CollapsingToolBarLayout<android.support.design.widget.AppBarLayout...>

<android.support.design.widget.CollapsingToolbarLayout...>

<ImageView.../> <android.support.v7.widget.Toolbar.../>

<android.support.design.widget.TabLayout .../>

</android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

switch

Page 70: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

71

V7

The one I prefer

<android.support.design.widget.AppBarLayout ... >

<android.support.design.widget.CollapsingToolbarLayout ... >

<ImageView ... />

<android.support.v7.widget.Toolbar ... />

</android.support.design.widget.CollapsingToolbarLayout>

<android.support.design.widget.TabLayout />

</android.support.design.widget.AppBarLayout>

collapsingToolbar.setContentScrimResource(R.drawable.cardview_background_toolbar);

Page 71: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

An old trick : PageTransformer

Page 72: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

73

V13

ViewPager

Page 73: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Demonstration !

V13

ViewPager

Page 74: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

75

activity_main.xml<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.view.ViewPager android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/viewpager" android:background="#FF00F0F0"></android.support.v4.view.ViewPager>

public class MainActivity extends ActionBarActivity { private MyPagerAdapter pagerAdapter; private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) {... //instanciate the PageAdapter pagerAdapter=new MyPagerAdapter(this); //Find the viewPager viewPager = (ViewPager) super.findViewById(R.id.viewpager); // Affectation de l'adapter au ViewPager viewPager.setAdapter(pagerAdapter);

}

V13

ViewPager

Page 75: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

76

public class MyPagerAdapter extends FragmentPagerAdapter { private final ArrayList<Fragment> fragments;

public MyPagerAdapter(ActionBarActivity ctx) { super(ctx.getSupportFragmentManager()); fragments = new ArrayList<Fragment>(); //A stuff I never did before, instanciate my fragment Fragment frag =new MyFragment1(); fragments.add(frag);... }

public Fragment getItem(int position) { return fragments.get(position); }

public int getCount() {return fragments.size(); }

V13

ViewPager

Page 76: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

77

public class MainActivity extends ActionBarActivity {

@Overrideprotected void onCreate(Bundle savedInstanceState) {...//instanciate the PageAdapterpagerAdapter=new MyPagerAdapter(this);//Find the viewPagerviewPager = (ViewPager) super.findViewById(R.id.viewpager);// Affectation de l'adapter au ViewPagerviewPager.setAdapter(pagerAdapter);if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB){ viewPager.setPageTransformer(true, new PageTransformer(this));}

V13

ViewPager

Page 77: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

78

public class MyPageTransformer implements ViewPager.PageTransformer{ RecyclerView myRecyclerView;

public void transformPage(View view, float position) { //Only the main layout is passed here/ myRecyclerView= (RecyclerView) view.findViewById(R.id.my_recycler_view); if (position < -1) { // [-Infinity,-1)This page is way off-screen to the left. view.setAlpha(0); }

else if (position < 1) { //in the visible range [-1,1] myRecyclerView.setAlpha(1-Math.abs(position)); view.setAlpha(1); if (position < 0) {//coming from left myRecyclerView.setRotationX((position * 360)); } else {//coming from right myRecyclerView.setRotationX(-1*position *360); } }

else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } }}

V13

ViewPager

Page 78: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Tips

Page 79: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

First: Simplify your layout !!!if not enough you can also:

User LayerType Hardware accelerated

btnDoNotPress.setLayerType(View.LAYER_TYPE_HARDWARE,null);

new Animator.AnimatorListener() {public void onAnimationEnd(Animator animation) { btnDoNotPress.setLayerType(View.LAYER_TYPE_NONE, null);

}

V1

Optimize your Animation

Page 80: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Use Interface and Factory/** * The animation */MainActivityAnimMother anim;//the factory for the animations (you can create a Class to do that if you want) :if(isPostLollipop){ anim=new MainActivityAnimLLP();}else if(postICS){ anim=new MainActivityAnimICS();}else{ anim=new MainActivityAnimGinger();}

V1

Managing versions

MainActivity

MainActivity

MainActivityAnimGinger

MainActivityAnimICS

MainActivityAnimLLP

MainActivityMotherAnim

MainActivityAnimIntf

Animation code Animation attributes

Animation methods declaration

v21

Page 81: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

#[email protected]

www.android2ee.com

Android by passionPassionate by Training

Expert by technical love

Questions ?

Page 82: Animate Me, if you don't do it for me do it for chet (DroidCon Paris)

Code:https://github.com/MathiasSeguy-

Android2EE

Android2EE@android2ee

Thank you!

Mathias Seguy

Slides:http://fr.slideshare.net/Android2EE