You are on page 1of 72

Material Design

+Ran Nachmany

M AT E R I A L D E S I G N

A coherent cross-platform
experience

A coherent cross-platform
experience
A more flexible design system
for Android

A coherent cross-platform
experience
A more flexible design system
for Android
A rational approach to visual,
interaction, and motion design

Tangible
surfaces

Print-like
design

Meaningful
motion

Adaptive
design

Tangible
surfaces

Print-like
design

Meaningful
motion

Adaptive
design

Tangible
surfaces

Print-like
design

Meaningful
motion

Adaptive
design

Tangible
surfaces

Print-like
design

Meaningful
motion

Adaptive
design

Tangible
surfaces

Print-like
design

Meaningful
motion

Adaptive
design

Tangible surfaces

Constrained depth

Interaction cues
(scrolling and pinning)

Surface
reaction

Z-eam me
up, Scotty

Elevation
The base Z-depth of a View
+
!

Translation Z
The transient delta
!

Z-eam me
up, Scotty
<ImageView
...
android:elevation="8dp" />
view.animate().translationZ().start();

StateListAnimator
<ImageView
android:layout_width=wrap_content
android:layout_height=wrap_content
android:elevation="8dp"
android:stateListAnimator=@anim/my_state_list_animator
... />

Note: the Button provides this automatically

StateListAnimator
anim/my_state_list_animator.xml

<selector>

</selector>

StateListAnimator
anim/my_state_list_animator.xml

<selector>
<item android:state_pressed="true" android:state_enabled="true">
<objectAnimator android:propertyName="translationZ"
android:valueTo="8dp"
android:valueType="floatType"/>
</item>

</selector>

StateListAnimator
anim/my_state_list_animator.xml

<selector>

<item>
<objectAnimator android:propertyName="translationZ"
android:valueTo="0"
android:valueType="floatType"/>
</item>
</selector>

Outline
A views outline defines the shadow it casts
By default, the outline is derived from the views background

<shape android:shape="oval">
<solid android:color=@color/blue />
</shape>

Outline
But you can do much more with Outline.
Say you want an avatar clipped within a circle
static class OvalOutlineProvider extends ViewOutlineProvider {
@Override
public void getOutline(View view, Outline outline) {
outline.setOval(0, 0, view.getWidth(), view.getHeight());
}
}
!

view.setOutlineProvider(new OvalOutlineProvider());

Cards
A card is a piece of paper
that contains a unique
data set of related,
heterogeneous
information.

Cards
A card is a piece of paper
that contains a unique
data set of related,
heterogeneous

information.
outline
elevation

Cards
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
!

<!-- Your card content -->


!

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

Dont over
cardify!

Print-like design

Front View

Side View

YES

NO

Refined
typography

Refined
typography

Typographic
scale

Display 4
!

Display 3
!
Display 2
!
Display 1
!
Headline
!
Title
!
Subhead
!
Body 2
!
Body 1
!
Caption
!
Menu
!
Button

Typographic
scale

Display 4
!

Display 3
!
Display 2
!
Display 1
!
Headline
!
Title
!
Subhead
!
Body 2
!
Body 1
!
Caption
!
Menu
!
Button

android:fontFamily=
sans-serif-medium

Display 4
!

Display 3
!
Display 2
!

android:TextAppearance.Material.

Display 1
!
Headline
!
Title
!
Subhead
!
Body 2
!
Body 1
!
Caption
!
Menu
!
Button

Display 4
!

Display 3
!
Display 2
!

TextAppearance.AppCompat.

Display 1
!
Headline
!
Title
!
Subhead
!
Body 2
!
Body 1
!
Caption
!
Menu
!
Button

Bold
color

Primary
+
Accent

colorPrimaryDark

colorPrimary

colorAccent

Theme.Material
API v21 and above

<style name=MyAwesomeTheme"
parent=android:Theme.Material.Light.DarkActionBar>
!

<item name="android:colorPrimary">@color/blue</item>
<item name=android:colorPrimaryDark">@color/darker_blue</item>
<item name=android:colorAccent">@color/teal</item>
!

</resources>

Theme.AppCompat
API v7 and above

<style name=MyAwesomeTheme"
parent=Theme.AppCompat.Light.DarkActionBar>
!

<item name="colorPrimary">@color/blue</item>
<item name="colorPrimaryDark">@color/darker_blue</item>
<item name="colorAccent">@color/teal</item>
!

</resources>

Content can
provide color

Light Vibrant

Vibrant

Dark Vibrant

Light Muted

Muted

Dark Muted

P
Palette p = Palette.generate(bitmap);
Swatch vibrant = p.getVibrantSwatch();
Swatch darkVibrant = p.getDarkVibrantSwatch();
Swatch lightVibrant = p.getLightVibrantSwatch();
Swatch
Swatch
Swatch

Whats in a Swatch?
getRgb()
The RGB value of this Swatch (aka the colour)

getTitleTextColor()
ARGB color for legible title text over this Swatch

Title
Body

getBodyTextColor()
ARGB color for legible body text over this Swatch
getHsl()

The HSL value of this Swatch

getPopulation()

The relative amount of pixels this colour represents

Meaningful motion

Activity transitions
1. Enable the feature
From your theme

<style name="MyTheme" parent=android:Theme.Material">


<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
</style>
From your Activity

requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);

Activity transitions

2. Specify the shared element(s)


layout/album_details.xml

<ImageView
...
android:transitionName="@string/transition_album_cover" />

Activity transitions

3. Start the Activity (transition)


Intent intent = ... // setup Intent as usual
!

String transitionName = getString(R.string.transition_album_cover);


!

ActivityOptionsCompat opts = ActivityOptionsCompat


.makeSceneTransitionAnimation(
activity,
// Our starting Activity
albumCoverView,
// The view which starts the transition
transitionName
// The transitionName of the view were transitioning to
);
!

// Now start the Activity, using our options bundle


ActivityCompat.startActivity(activity, intent, opts.toBundle());

Asymmetric
motion

Users
initiate
change

RippleDrawable
New (v21+)

Bound to another Drawable

<ripple android:color=?android:colorControlHighlight>
<item>
<shape android:shape="rectangle">
<solid android:color=@color/grey />
</shape>
</item>
</ripple>

RippleDrawable
New (v21+)

Bound to an invisible mask

<ripple android:color=?android:colorControlHighlight>
<item android:id="@id/mask">
<shape android:shape="rectangle">
<solid android:color=@color/white />
</shape>
</item>
</ripple>

RippleDrawable
New (v21+)

Unbounded

<ripple android:color=?android/colorControlHighlight />

Ripples
Bounded ripple

android:selectableItemBackground
Unbounded ripple

New (v21+)

android:selectableItemBackgroundBorderless

Circular Reveal

Circular Reveal
Animator reveal
= ViewAnimationUtils.createCircularReveal(
viewToReveal, // View to reveal
centerX,
// mask centre x
centerY,
// mask centre y
startRadius, // mask start radius
endRadius);
// mask end radius
reveal.start();

Adaptive design

Keylines

Increments
64dp
56dp

Think in blocks

Toolbar

Toolbar

Toolbar

New (v21+)

Place it within your layouts

<Toolbar
android:id=@+id/my_toolbar
android:layout_height=?android:actionBarSize
android:layout_width=match_parent
android:background=?android:colorPrimary />
Then in your Activity/Fragment

Toolbar toolbar = findViewById(R.id.my_toolbar);


setActionBar(toolbar);

Toolbar (AppCompat)

New (v7+)

Place it within your layouts

<android.support.v7.widget.Toolbar
android:id=@+id/my_toolbar
android:layout_height=?actionBarSize
android:layout_width=match_parent
android:background=?colorPrimary />
Then in your ActionBarActivity/Fragment

Toolbar toolbar = findViewById(R.id.my_toolbar);


setSupportActionBar(toolbar);

Banesy Top Tip


Window provided Progress Bars no longer work

<Toolbar
...>
!

<ProgressBar
...
android:gravity="top|end" />
!

</Toolbar>

M AT E R I A L D E S I G N

Q?