georgiy shur: bring onboarding to life
TRANSCRIPT
GEORGIY SHURAndroid Developer, Ackee
Bring onboarding to lifewith ViewPager-based animations
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Onboarding techniques
● Walkthroughs and tours
● Contextual tips and tutorials
● Empty states
● Dummy data, chatbots, etc....
Static screens are boring?
● Animated
● Interactive
ViewPager-based animations concept● Offset between pages
ViewPager-based animations concept● Offset between pages
● Parameter to animate (position, scale, color, …)
ViewPager-based animations concept● Offset between pages
● Parameter to animate (position, scale, color, …)
● Relation between them (linear, …)
ViewPager-based animations concept● Offset between pages
● Parameter to animate (position, scale, color, …)
● Relation between them (linear, …)
● Pages involved
Between pages 1 and 2 I want to change x position of view with relation x = offset/2
Parameters to animate● Position (translation)
● Angle (rotation)
● Scale (size)
● Color
● Alpha (fade in/out)
● Progress (GIF, Lottie view)
● Custom, ...
private void initHandWithPhone() {
ImageView hand = (ImageView) LayoutInflater. from(mPagerLayout.getContext())
.inflate(R.layout. decor_hand_with_phone, mPagerLayout, false);
Decor handDecor = new Decor.Builder(hand).setPage(Page. pageRange(2, 3))
.behindViewPage().withLayer().build();
RotationAnimation handRotateInAnim = new RotationAnimation(Page. singlePage(2), 30, 0);
handRotateInAnim.setInterpolator( new DecelerateInterpolator());
TranslationAnimation handMoveInAnim = new TranslationAnimation(Page. singlePage(2),
mCircleRadius + hand.getDrawable().getIntrinsicWidth() / 2,
-UiUtils. dpToPx(this, 16), UiUtils.dpToPx(this, 28), 0, true);
handMoveInAnim.setInterpolator( new DecelerateInterpolator());
RotationAnimation handRotateOutAnim = new RotationAnimation(Page. singlePage(3), 0, -60);
TranslationAnimation handMoveOutAnim = new TranslationAnimation(Page. singlePage(3),
UiUtils. dpToPx(this, 28), 0,
-mCircleRadius - hand.getDrawable().getIntrinsicWidth() / 2,
UiUtils. dpToPx(this, 166), true);
mSparkleMotion.animate(handRotateInAnim).animate(handMoveInAnim)
.animate(handRotateOutAnim).animate(handMoveOutAnim).on(handDecor);
}
ImageView hand = (ImageView) LayoutInflater
.from(mPagerLayout.getContext())
.inflate(R.layout.decor_hand_with_phone,
mPagerLayout, false);
Decor handDecor = new Decor.Builder(hand)
.setPage(Page.pageRange(2, 3))
.behindViewPage().withLayer().build();
RotationAnimation handRotateInAnim = new
RotationAnimation(Page.singlePage(2), 30, 0);
handRotateInAnim.setInterpolator(new DecelerateInterpolator());
TranslationAnimation handMoveInAnim = new TranslationAnimation(
Page.singlePage(2), mCircleRadius +
hand.getDrawable().getIntrinsicWidth() / 2,
-UiUtils.dpToPx(this, 16),
UiUtils.dpToPx(this, 28), 0, true);
handMoveInAnim.setInterpolator(new DecelerateInterpolator());
RotationAnimation handRotateOutAnim = new
RotationAnimation(Page.singlePage(3), 0, -60);
TranslationAnimation handMoveOutAnim = new
TranslationAnimation(Page.singlePage(3),
UiUtils.dpToPx(this, 28), 0, -mCircleRadius -
hand.getDrawable().getIntrinsicWidth() / 2,
UiUtils.dpToPx(this, 166), true);
mSparkleMotion
.animate(handRotateInAnim)
.animate(handMoveInAnim)
.animate(handRotateOutAnim)
.animate(handMoveOutAnim)
.on(handDecor);
class CustomPageTransformer : ViewPager.PageTransformer {
override fun transformPage(view: View, position: Float) {
with(view.find<Button>(R.id.btn_first)) {
alpha = position
translationX = -(1 - position) * 1.4f * view.width
}
with(view.find<Button>(R.id.btn_second)) {
alpha = position
translationX = -(1 - position) * 1.6f * view.width
}
}
}
viewPager.setPageTransformer(false, CustomPageTransformer())
val spritz = Spritz
.with(lottieAnimationView)
.withSteps(
SpritzStep.Builder()
.withAutoPlayDuration(500, TimeUnit.MILLISECONDS)
.withSwipeDuration(500, TimeUnit.MILLISECONDS)
.build(),
SpritzStep.Builder()
.withAutoPlayDuration(500, TimeUnit.MILLISECONDS)
.withSwipeDuration(500, TimeUnit.MILLISECONDS)
.build(),
SpritzStep.Builder()
.withAutoPlayDuration(500, TimeUnit.MILLISECONDS)
.build()
)
.build()
override fun onStart() {
super.onStart()
spritz.attachTo(viewPager)
spritz.startPendingAnimations()
}
override fun onStop() {
spritz.detachFrom(viewPager)
super.onStop()
}
https://github.com/IFTTT/SparkleMotion
https://developer.android.com/reference/android/support/v4/view/ViewPager.
PageTransformer.html
https://github.com/novoda/android-demos/tree/master/spritz
WWW.MDEVTALK.CZmdevtalk