Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save benju69/c0fef8b3f22a982396ee to your computer and use it in GitHub Desktop.
Save benju69/c0fef8b3f22a982396ee to your computer and use it in GitHub Desktop.
Animated Stroke. The google I/O website this year (https://google.com/io) has some funky animated lettering. I especially liked the animated stroke around the letters and wondered how you might implement that on Android. Turns out that AnimatedVectorDrawable makes this very easy! Here's how it looks: https://twitter.com/crafty/status/71077957997…
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="360dp"
android:height="200dp"
android:viewportWidth="360"
android:viewportHeight="200">
<path
android:name="hash"
android:pathData="M39,45L39,80 M57,45L57,80 M66,54L31,54 M66,71L31,71"
android:strokeColor="@color/indigo_400"
android:strokeLineCap="round"
android:strokeWidth="@dimen/hashtag_stroke_width" />
<path
android:name="i_body"
android:pathData="M83,82L107,82A2,2 0,0 1,109 84L109,155A2,2 0,0 1,107 157L83,157A2,2 0,0 1,81 155L81,84A2,2 0,0 1,83 82z"
android:strokeColor="@color/indigo_400"
android:strokeWidth="@dimen/hashtag_stroke_width" />
<path
android:name="i_dot"
android:pathData="M94,59m-14,0a14,14 0,1 1,28 0a14,14 0,1 1,-28 0"
android:strokeColor="@color/indigo_400"
android:strokeWidth="@dimen/hashtag_stroke_width" />
<path
android:name="o"
android:pathData="M159.5,119.5m-37.5,0a37.5,37.5 0,1 1,75 0a37.5,37.5 0,1 1,-75 0"
android:strokeColor="@color/indigo_400"
android:strokeWidth="@dimen/hashtag_stroke_width" />
<!-- Here's the trick, we place four copies of the path for the number one on top of each other.
We then set different trim values to show only a quarter of each path. We can then animate
the trimPathOffset property to make the shown segment describe the whole path. -->
<path
android:name="one_1"
android:pathData="@string/path_one"
android:strokeColor="@color/cyan_a100"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0"
android:trimPathEnd="0.25" />
<path
android:name="one_2"
android:pathData="@string/path_one"
android:strokeColor="@color/pink_500"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.25"
android:trimPathEnd="0.5" />
<path
android:name="one_3"
android:pathData="@string/path_one"
android:strokeColor="@color/indigo_400"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.5"
android:trimPathEnd="0.75" />
<path
android:name="one_4"
android:pathData="@string/path_one"
android:strokeColor="@color/cyan_300"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.75"
android:trimPathEnd="0" />
<!-- we do the same for the number six. -->
<path
android:name="six_1"
android:pathData="@string/path_funky_six"
android:strokeColor="@color/cyan_a100"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0"
android:trimPathEnd="0.25" />
<path
android:name="six_2"
android:pathData="@string/path_funky_six"
android:strokeColor="@color/pink_500"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.25"
android:trimPathEnd="0.5" />
<path
android:name="six_3"
android:pathData="@string/path_funky_six"
android:strokeColor="@color/indigo_400"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.5"
android:trimPathEnd="0.75" />
<path
android:name="six_4"
android:pathData="@string/path_funky_six"
android:strokeColor="@color/cyan_300"
android:strokeWidth="@dimen/hashtag_stroke_width"
android:trimPathStart="0.75"
android:trimPathEnd="0" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_hashtag">
<target
android:name="one_1"
android:animation="@animator/offset_trim_one" />
<target
android:name="one_2"
android:animation="@animator/offset_trim_one" />
<target
android:name="one_3"
android:animation="@animator/offset_trim_one" />
<target
android:name="one_4"
android:animation="@animator/offset_trim_one" />
<target
android:name="six_1"
android:animation="@animator/offset_trim_six" />
<target
android:name="six_2"
android:animation="@animator/offset_trim_six" />
<target
android:name="six_3"
android:animation="@animator/offset_trim_six" />
<target
android:name="six_4"
android:animation="@animator/offset_trim_six" />
</animated-vector>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Define elements that are repeated here and reference them so that we only have to update them
in one place. -->
<resources>
<string name="path_funky_six">M302.14,60.72C302.29,61.46 276.46,97.06 270.1,112.55C260.87,138.44 278.6,149.83 284.3,152.76C299.15,160.38 316.85,150.27 323.08,141.43C329.3,132.59 333.05,109.99 316.85,100.57C306.85,94.75 290.54,97.32 290.2,97.06C289.85,96.79 276.32,81.31 276.46,80.88C276.6,80.45 294.73,77.62 302.88,84.28C315.76,92.99 315.62,114.99 306.84,127.42C298.06,139.85 276.46,144.38 260.54,130.73C238.46,111.79 259.06,85.64 260.87,83.1C260.87,83.1 286.23,46.19 286.83,46.03C287.43,45.87 301.99,59.99 302.14,60.72Z</string>
<string name="path_one">M211,45L235,45A2,2 0,0 1,237 47L237,155A2,2 0,0 1,235 157L211,157A2,2 0,0 1,209 155L209,47A2,2 0,0 1,211 45z</string>
<item name="hashtag_stroke_width" type="dimen" format="float">5</item>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- we use separate anims for the 1/6 to allow different durations (as the path lengths are
different, using the same duration produces different speeds). -->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathOffset"
android:valueFrom="0"
android:valueTo="1"
android:duration="4000"
android:interpolator="@android:interpolator/linear"
android:repeatCount="infinite"
android:repeatMode="restart" />
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- we use separate anims for the 1/6 to allow different durations (as the path lengths are
different, using the same duration produces different speeds). -->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathOffset"
android:valueFrom="0"
android:valueTo="1"
android:duration="5000"
android:interpolator="@android:interpolator/linear"
android:repeatCount="infinite"
android:repeatMode="restart" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment