Upgrade to Pro — share decks privately, control downloads, hide ads and more …

実例で理解する Material Design Animation

Ryo Sakaguchi
February 08, 2018

実例で理解する Material Design Animation

DroidKaigi 2018 2/8 Room2

Ryo Sakaguchi

February 08, 2018
Tweet

More Decks by Ryo Sakaguchi

Other Decks in Programming

Transcript

  1. 2018.2.8
    ࣮ྫͰཧղ͢Δ
    Material Design Animation
    DroidKaigi 2018 Room2 Feb 8th, 2018
    Ryo Sakaguchi (wakwak3125)

    View Slide

  2. 2018.2.8
    Ryo Sakaguchi
    @wakwak3125
    • Wantedly, Inc
    • Android application developer
    • Wantedly People
    • Music, Guitar, UI/UX
    About me

    View Slide

  3. 2018.2.8
    Ryo Sakaguchi
    @wakwak3125
    • Wantedly, Inc
    • Android application developer
    • Wantedly People
    • Music, Guitar, UI/UX
    About me

    View Slide

  4. 2018.2.8
    Wantedly People

    View Slide

  5. 2018.2.8
    Wantedly People
    • ໊ࢗ؅ཧΞϓϦ
    • ػցֶशΛ࢖༻͍ͯ͠Δ
    • ಡΈऔ໊ͬͨࢗ΍ɺࣗ෼ͷ৘ใΛݩ
    ʹʮ࿩୊ʯΛఏڙ͢Δ
    • ؾ໊͍͍࣋ͪࢗࡱӨମݧ

    View Slide

  6. 2018.2.8
    Wantedly People
    • ໊ࢗ؅ཧΞϓϦ
    • ػցֶशΛ࢖༻͍ͯ͠Δ
    • ಡΈऔ໊ͬͨࢗ΍ɺࣗ෼ͷ৘ใΛݩ
    ʹʮ࿩୊ʯΛఏڙ͢Δ
    • ؾ໊͍͍࣋ͪࢗࡱӨମݧ

    View Slide

  7. 2018.2.8
    Agenda

    View Slide

  8. 2018.2.8
    Agenda
    • ʮ࿩୊ʯػೳͷΞχϝʔγϣϯͷ঺հ
    • ࣮૷ͷղઆ
    • Ξχϝʔγϣϯ࣮૷ͷצॴ
    • ΞχϝʔγϣϯͷDebug

    View Slide

  9. 2018.2.8
    ʮ࿩୊ʯػೳͷΞχϝʔγϣϯ঺հ

    View Slide

  10. 2018.2.8
    Article
    ࿩୊ͷهࣄΛදࣔ͢Δը໘
    • ഑৴͞ΕΔ࿩୊Λදࣔ͢Δը໘
    • Ϣʔβʔʹରͯ͠஫໨ͯ͠΄͍͠ʮը૾ʯ
    Λ࣠ʹΞχϝʔγϣϯ͢Δɻ
    • RecyclerViewʹΧʔυܕͷΞΠςϜΛฒ
    ΂ɺͦΕ͕Expand͢ΔΠϝʔδ
    • ΧʔυഎܠˠΧόʔΠϝʔδ
    • هࣄͷ֓ཁ/λΠτϧͷίϯςΩετ
    Λڞ༗Ͱ͖Δ
    ʮ࿩୊ʯػೳͷΞχϝʔγϣϯ঺հ Article

    View Slide

  11. 2018.2.8
    Graphic contents
    ΠϯϑΥάϥϑΟοΫ
    • ΠϯϑΥάϥϑΟοΫ͕ϝΠϯͷهࣄΛ
    දࣔ͢Δ
    • ίϯςϯπࣗମ͸AfterEffectsΛ࢖༻͠
    ͯ࡞੒͠ɺbodymovinΛ࢖༻ͯ͠
    WebViewͰ࠶ੜ͍ͯ͠Δ
    • Χʔυͷഎܠը૾͕શ໘ʹ޿͕͍ͬͯ͘
    • Χʔυˠهࣄৄࡉ΁ͷભҠͰੈք؍
    ΛଛͳΘͳ͍
    ʮ࿩୊ʯػೳͷΞχϝʔγϣϯ঺հ Graphic contents

    View Slide

  12. 2018.2.8
    Timeline
    هࣄ͕දࣔ͞ΕΔTimeline
    • هࣄΛҰཡͰදࣔ͢ΔRecyclerView
    • Χʔυ͕എܠը૾Λ࣋ͭλΠϓͱ࣋ͨ
    ͳ͍λΠϓ͕͋Δ
    • എܠը૾Λ࣋ͭλΠϓͷ΋ͷͷ৔߹͸ɺ
    Timelineͷഎܠશମʹϒϥʔ͕͔͔ͬ
    ͨ΋ͷ͕هࣄͷग़ݱͱڞʹΫϩεϑΣʔ
    υ͢Δ
    • ࠓճϝΠϯͰ࿩Λ͢Δͭ΋Γͷɺ
    SharedElementTransitionͱ͸ҧ͏͚
    ͲɺҰԠ঺հ
    ʮ࿩୊ʯػೳͷΞχϝʔγϣϯ঺հ Timeline

    View Slide

  13. 2018.2.8
    ΞχϝʔγϣϯͬͯͳΜͰඞཁͳͷʁ

    View Slide

  14. 2018.2.8
    ͔͍͍͔ͬ͜Β

    View Slide

  15. 2018.2.8
    ͔͍͍͔ͬ͜Βʁ
    ͚ͩ͡Όͳ͍Ͱ͢
    • ΞχϝʔγϣϯʹΑͬͯɺϢʔβʔʹ
    ஫໨ͯ͠΄͍͠΋ͷΛΞϐʔϧͰ͖Δ
    • ࢖͍ͬͯͯɺಥવίϯςϯπ͕ೖΕସ
    Θͬͨ෩ʹײͯ͡͠·͏Ϣʔβʔ΋ډ
    Δ͸ͣɻ
    • ΍Βͳ͍ΑΓ͸΍ͬͨ΄͏͕ઈରྑ͍
    • ΍Γ͗͢͸ྑ͘ͳ͍ɻ͚Ͳɺ·ͣ
    ͸࡞͔ͬͯΒ࡟͍ͬͯ͘ͷ͕େࣄ
    • ΋ͪΖΜ͔͍͍ͬͬͯ͜΋ͷ͋Δʂ
    ΞχϝʔγϣϯͬͯͳΜͰඞཁͳͷʁ

    View Slide

  16. 2018.2.8
    ࣮૷ͷղઆ

    View Slide

  17. 2018.2.8
    ࣮૷ͷղઆ
    • Shared Element Transitionͷجຊͷ
    ͓͞Β͍
    • ֤ػೳ(Article/Graphic contents)
    ʹґଘ͠ͳ͍෦෼ͷڞ௨࣮૷ͷ࿩
    • ֤ػೳຖʹߦ͍ͬͯΔಛผͳ෦෼ͷ࿩
    • Article
    • Graphic content

    View Slide

  18. 2018.2.8
    ·ͣ͸جຊͷ͓͞Β͍

    View Slide

  19. 2018.2.8
    Transition Name 1/3
    ڞ༗͍ͨ͠Viewʹ໊લΛ͚ͭΔ
    ·ͣ͸جຊͷ͓͞Β͍ Shared Element Transition
    public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(
    this,
    R.layout.activity_main
    );
    binding.button.setOnClickListener(v -> goToNextActivity());
    }
    void goToNextActivity() {
    Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
    this, /*ભҠݩͷActivity*/
    binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/

    View Slide

  20. 2018.2.8
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(
    this,
    R.layout.activity_main
    );
    binding.button.setOnClickListener(v -> goToNextActivity());
    }
    Transition Name 2/3
    Transitionʹඞཁͳ৘ใΛBundleʹ٧Ίͯ౉͢
    ·ͣ͸جຊͷ͓͞Β͍ Shared Element Transition
    void goToNextActivity() {
    Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
    this, /*ભҠݩͷActivity*/
    binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/
    "transition:image" /*ڞ༗͍ͨ͠ViewͷTransition Name*/
    ).toBundle();
    ActivityCompat.startActivity(
    this,
    new Intent(this, NextActivity.class),
    bundle);
    }

    View Slide

  21. 2018.2.8
    Transition Name 3/3
    ભҠઌͷActivityͷڞ༗͍ͨ͠ViewʹTransition NameΛηοτ͢Δ
    ·ͣ͸جຊͷ͓͞Β͍ Shared Element Transition
    this, /*ભҠݩͷActivity*/
    binding.imageView, /*ભҠݩͱભҠઌͰڞ༗͍ͨ͠View*/
    "transition:image" /*ڞ༗͍ͨ͠ViewͷTransition Name*/
    ).toBundle();
    ActivityCompat.startActivity(
    this,
    new Intent(this, NextActivity.class),
    bundle);
    }
    public class NextActivity extends AppCompatActivity {
    ActivityNextBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this,
    R.layout.activity_next);
    binding.imageView.setTransitionName("transition:image");
    }
    }

    View Slide

  22. 2018.2.8

    View Slide

  23. 2018.2.8
    Default animation
    theme_material.xmlͰ

    σϑΥϧτͰҎԼͷΞχϝʔγϣϯ͕ηοτ͞Ε͍ͯΔ
    ·ͣ͸جຊͷ͓͞Β͍ Shared Element Transition






    move.xml

    View Slide

  24. 2018.2.8
    Postpone Transition
    Transition animationΛ೚ҙͷλΠϛϯάͰ։࢝Ͱ͖Δ
    ·ͣ͸جຊͷ͓͞Β͍ Shared Element Transition
    public class NextActivity extends AppCompatActivity {
    static final Handler sHandler = new Handler(Looper.getMainLooper());
    ActivityNextBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this,
    R.layout.activity_next);
    binding.imageView.setTransitionName("transition:image");
    ActivityCompat.postponeEnterTransition(this);
    sHandler.postDelayed(() ->
    ActivityCompat.startPostponedEnterTransition(this),
    1000
    );
    }
    }

    View Slide

  25. 2018.2.8
    ࣮૷ͷղઆ
    Wantedly PeopleͰ࢖͍ͬͯΔShared Element Transitionͷڞ௨ͳ෦෼

    View Slide

  26. 2018.2.8
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    .BJO"DUJWJUZ

    View Slide

  27. 2018.2.8
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    .BJO"DUJWJUZ
    5JNFMJOF'SBHNFOU

    View Slide

  28. 2018.2.8
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    .BJO"DUJWJUZ
    5JNFMJOF'SBHNFOU
    1PTU"SUJDMF"DUJWJZ

    View Slide

  29. 2018.2.8
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    .BJO"DUJWJUZ
    5JNFMJOF'SBHNFOU
    1PTU"SUJDMF"DUJWJZ
    1PTU"SUJDMF'SBHNFOU

    View Slide

  30. 2018.2.8
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    .BJO"DUJWJUZ
    5JNFMJOF'SBHNFOU
    1PTU"SUJDMF"DUJWJZ
    1PTU"SUJDMF'SBHNFOU

    View Slide

  31. 2018.2.8
    ͔͜͜ΒϓϩμΫγϣϯίʔυ
    ͍Ζ͍Ζͳྺ࢙తͳഎܠͰग़དྷ্͕ͬͯ·͢ɻ
    ࠓ೔͸େ໨ʹݟͯ΄͍͠ʂ
    Page Title Page Subtitle

    View Slide

  32. 2018.2.8
    TimelineFragment
    ͜ͷFragment͔ΒTransitionΛ։࢝͢Δ
    /**
    * @param fragment ભҠݩͷFragment
    * @param postKey هࣄͷKey
    * @param provider TransitionʹඞཁͳViewΛViewHolder͔Βऔͬͯ͘Δ
    * adapterΛ࣋ͭ
    */
    public void openPost(BaseFragment fragment,
    String postKey,
    PostLogic.ITransitionAdapterProvider provider) {
    PostArticleFragment nextFragment =
    PostArticleFragment.newInstance(postKey);
    TransitionExtra extra = new TransitionExtra.Builder().build();
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    // ର৅ͱͳΔViewͱTransition nameͷPairͷListΛ࡞Δ
    List> pairList = new ArrayList<>();
    if (provider != null) {
    PostLogic.TransitionAdapter adapter =
    provider.getTransitionAdapter();
    // Viewʹରͯ͠ Transition nameΛ༩͍͑ͯ͘

    View Slide

  33. 2018.2.8
    TimelineFragment
    ͜ͷFragment͔ΒTransitionΛ։࢝͢Δ
    * @param provider TransitionʹඞཁͳViewΛViewHolder͔Βऔͬͯ͘Δ
    * adapterΛ࣋ͭ
    */
    public void openPost(BaseFragment fragment,
    String postKey,
    PostLogic.ITransitionAdapterProvider provider) {
    PostArticleFragment nextFragment =
    PostArticleFragment.newInstance(postKey);
    TransitionExtra extra = new TransitionExtra.Builder().build();
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    // ର৅ͱͳΔViewͱTransition nameͷPairͷListΛ࡞Δ
    List> pairList = new ArrayList<>();
    if (provider != null) {
    PostLogic.TransitionAdapter adapter =
    provider.getTransitionAdapter();
    // Viewʹରͯ͠ Transition nameΛ༩͍͑ͯ͘
    pairList.add(Pair.create(
    adapter.getCoverImage(),
    fragment.getString(R.string.transition_image_cover)));
    // ଞʹ΋View͕͋Ε͹͜͜Ͱηοτ͍ͯ͘͠...
    }
    //TransitionExtraʹpairListΛ౉͢
    extra.setSharedElementPair(pairList);
    // BaseFragment͕ը໘ભҠΛߦ͏ؔ਺Λ͍࣋ͬͯΔͷͰͦΕΛݺͼग़͢
    fragment.replaceFragment(nextFragment, extra);

    View Slide

  34. 2018.2.8
    BaseFragment
    replaceFragment
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    public void replaceFragment(@NonNull BaseFragment fragment,
    @Nullable TransitionExtra extra) {
    // BaseActivity͕listenerΛ࣮૷͍ͯ͠ΔͷͦͪΒʹϦϨʔ͢Δ
    getListener().replaceFragment(fragment, extra);
    }

    View Slide

  35. 2018.2.8
    BaseActivity
    replaceFragment
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    @Override
    public void replaceFragment(BaseFragment fragment,
    @Nullable TransitionExtra extra) {
    if (extra != null) {
    Intent intent = PostArticleActivity.createIntent(this);
    Pair[] sharedElements;
    if (!isEmpty(extra.getSharedElementPair())) {
    sharedElements =
    new Pair[extra.getSharedElementPair().size()];
    for (int i = 0; i < extra.getSharedElementPair().size(); i++) {
    Pair pair =
    extra.getSharedElementPair().get(i);
    if (pair.first != null && pair.second != null) {
    sharedElements[i] = pair;
    }
    }
    } else {
    sharedElements = new Pair[0];
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    ActivityOptionsCompat options =

    View Slide

  36. 2018.2.8
    BaseActivity
    replaceFragment
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    new Pair[extra.getSharedElementPair().size()];
    for (int i = 0; i < extra.getSharedElementPair().size(); i++) {
    Pair pair =
    extra.getSharedElementPair().get(i);
    if (pair.first != null && pair.second != null) {
    sharedElements[i] = pair;
    }
    }
    } else {
    sharedElements = new Pair[0];
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    ActivityOptionsCompat options =
    ActivityOptionsCompat.makeSceneTransitionAnimation(this,
    sharedElements);
    ActivityCompat.startActivity(this, intent, options.toBundle());
    } else {
    startActivity(intent);
    }
    } else {
    /*͔͜͜ΒFragmentͰ։͘৔߹ͷॲཧ*/
    }

    View Slide

  37. 2018.2.8
    PostArticleActivity
    TransitionΛҰ࣌ఀࢭ͢Δ
    ࣮૷ͷղઆ ڞ௨ͷ෦෼
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    // ৭ʑͳॳظԽͷॲཧΛ͢Δ
    // FragmentͷView͕ग़དྷ্͕Δ·ͰɺTransitionΛҰ࣌ఀࢭ͢Δ
    // ࠶։͸Fragmentଆ͔ΒݺΜͰ͋͛Δ
    supportPostponeEnterTransition();
    }

    View Slide

  38. 2018.2.8
    PostArticleActivity
    ҎԼͷTransitionSet͕ద༻͞Ε͍ͯΔ
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:duration="250"
    android:transitionOrdering="together">
    android:interpolator="@anim/interpolator_transition" />
    android:interpolator="@anim/interpolator_transition" />
    android:interpolator="@anim/interpolator_transition" />

    ࣮૷ͷղઆ ڞ௨ͷ෦෼

    View Slide

  39. 2018.2.8
    ࣮૷ͷղઆ
    Article

    View Slide

  40. 2018.2.8
    Article
    Transition։࢝લ
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ

    View Slide

  41. 2018.2.8
    Article
    Transition։࢝લ
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ

    View Slide

  42. 2018.2.8
    Article
    Transition։࢝લ
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ

    View Slide

  43. 2018.2.8
    Article
    Transition։࢝લ
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ

    View Slide

  44. 2018.2.8
    Article
    Transition։࢝લ
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ

    View Slide

  45. 2018.2.8
    Article
    Transition։࢝ޙং൫
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ
    • CardViewͷSharedElementͱͯ͠
    ഑ஔ͍ͯͨ͠ന͍͚ͩͷ
    FrameLayout

    View Slide

  46. 2018.2.8
    Article
    Transition։࢝ޙऴ൫
    ࣮૷ͷղઆ Article
    • CardView
    • ImageView(Mark Zuckerberg)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    • ͍͍Ͷ΍ίϝϯτϘλϯͷϨΠΞ΢τ
    • CardViewͷSharedElementͱͯ͠
    ഑ஔ͍ͯͨ͠ന͍͚ͩͷ
    FrameLayout

    View Slide

  47. 2018.2.8

    View Slide

  48. 2018.2.8
    Article
    Shared Elements
    ࣮૷ͷղઆ Article
    5JNFMJOF'SBNFOU 1PTU"SUJDMF'SBHNFOU
    7JFX %FTDSJQUJPO 7JFX %FTDSJQUJPO
    *NBHF7JFX Χʔυഎܠ *NBHF7JFX ΧόʔΠϝʔδ
    $BSE7JFX Χʔυ 'SBNF-BZPVU μϛʔͷഎܠ
    -JOFBS-BZPVU ౤ߘऀͷϨΠΞ΢τ -JOFBS-BZPVU ౤ߘऀͷϨΠΞ΢τ
    5FYU7JFX λΠτϧ 5FYU7JFX λΠτϧ
    5FYU7JFX ϝσΟΞ 5FYU7JFX ϝσΟΞ
    $POTUSBJOU-BZPVU ίϝϯτϘλϯͳͲ $POTUSBJOU-BZPVU ίϝϯτϘλϯͳͲ

    View Slide

  49. 2018.2.8
    PostArticleFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ Article
    fragment_post_article.xml

    android:id=“@+id/reaction">


    View Slide

  50. 2018.2.8
    android:id="@+id/content_root">
    ࣮૷ͷղઆ Article
    android:id="@+id/background_view"
    android:background="@drawable/background_post_article" />

    android:id=“@+id/reaction">


    PostArticleFragment
    ϨΠΞ΢τߏ଄
    fragment_post_article.xml

    View Slide

  51. 2018.2.8
    android:id="@+id/content_root">
    ࣮૷ͷղઆ Article
    android:id="@+id/background_view"
    android:background="@drawable/background_post_article" />

    android:id="@+id/parent_nested_scroll_view">


    android:id=“@+id/reaction">


    PostArticleFragment
    ϨΠΞ΢τߏ଄
    fragment_post_article.xml

    View Slide

  52. 2018.2.8
    android:id="@+id/content_root">
    ࣮૷ͷղઆ Article
    android:id="@+id/background_view"
    android:background="@drawable/background_post_article" />




    android:id="@+id/parent_nested_scroll_view">


    android:id=“@+id/reaction">


    PostArticleFragment
    ϨΠΞ΢τߏ଄
    fragment_post_article.xml

    View Slide

  53. 2018.2.8
    android:id="@+id/content_root">
    ࣮૷ͷղઆ Article
    android:id="@+id/background_view"
    android:background="@drawable/background_post_article" />


    android:id="@+id/parent_nested_scroll_view">

    android:id="@+id/image_cover" />

    android:id="@+id/layout_poster"
    layout="@layout/item_post_user" />
    android:id="@+id/text_title" />
    android:id="@+id/label_ad" />
    android:id="@+id/text_source_media" />
    android:id="@+id/text_published_at" />


    PostArticleFragment
    ϨΠΞ΢τߏ଄
    fragment_post_article.xml

    View Slide

  54. 2018.2.8
    ࣮૷ͷղઆ Article
    layout="@layout/item_post_user" />
    android:id="@+id/text_title" />
    android:id="@+id/label_ad" />
    android:id="@+id/text_source_media" />
    android:id="@+id/text_published_at" />


    android:id="@+id/web_view_short_article" />


    android:id=“@+id/reaction">



    PostArticleFragment
    ϨΠΞ΢τߏ଄
    fragment_post_article.xml

    View Slide

  55. 2018.2.8
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
    @Nullable ViewGroup container,
    @Nullable Bundle savedInstanceState) {
    mBinding = FragmentPostArticleBinding.inflate(inflater, container, false);
    ViewCompat.setTransitionName(mBinding.imageCover,
    getString(R.string.transition_image_cover));
    ViewCompat.setTransitionName(mBinding.backgroundView,
    getString(R.string.transition_background));
    ViewCompat.setTransitionName(mBinding.layoutPoster.getRoot(),
    getString(R.string.transition_item_user));
    ViewCompat.setTransitionName(mBinding.textTitle,
    getString(R.string.transition_text_title));
    ViewCompat.setTransitionName(mBinding.textSourceMedia,
    getString(R.string.transition_item_source_media));
    ViewCompat.setTransitionName(mBinding.reaction,
    getString(R.string.transition_item_reactions));
    return mBinding.getRoot();
    }
    ࣮૷ͷղઆ Article
    PostArticleFragment
    TransitionपΓͷίʔυ

    View Slide

  56. 2018.2.8
    @Override
    public void onStart() {
    super.onStart();
    mPostAccessor.getObservable()
    .compose(this.bindToLifecycle())
    .subscribe(post -> {
    refreshPost(post, mState);
    getActivity().supportStartPostponedEnterTransition();
    }, e -> recordError(null, this, e, null));
    }
    ࣮૷ͷղઆ Article
    PostArticleFragment
    Ωϟογϡʹ͋Δهࣄͷσʔλ(post)Λऔಘ͠ɺ׬ྃޙTransitionΛ࠶։

    View Slide

  57. 2018.2.8
    ϙΠϯτ
    • Transition։࢝લͷλΠϛϯάͰҰ࣌ఀࢭ͢Δ
    • Viewͷ४උ͕Ͱ͖ͨΒ࠶։
    • Χʔυ͕expand͢ΔΑ͏ͳΞχϝʔγϣϯ
    ͸ͪΐͬͱͨ͠τϦοΫΛ࢖͍ͬͯΔ͚ͩɻ
    ೉͘͠͸ͳ͍
    ࣮૷ͷղઆ Article
    PostArticleFragment

    View Slide

  58. 2018.2.8
    ࣮૷ͷղઆ
    Graphic contents

    View Slide

  59. 2018.2.8
    Graphic contents
    Transition։࢝લ
    ࣮૷ͷղઆ Graphic contents
    • CardView
    • ImageView(Χʔυഎܠ)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title

    View Slide

  60. 2018.2.8
    Graphic contents
    ࣮૷ͷղઆ Graphic contents
    • CardView
    • ImageView(Χʔυഎܠ)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title
    Transition։࢝લ

    View Slide

  61. 2018.2.8
    Graphic contents
    ࣮૷ͷղઆ Graphic contents
    Transition։࢝લ
    • CardView
    • ImageView(Χʔυഎܠ)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title

    View Slide

  62. 2018.2.8
    Graphic contents
    ࣮૷ͷղઆ Graphic contents
    Transition։࢝લ
    • CardView
    • ImageView(Χʔυഎܠ)
    • ౤ߘऀΛදࣔ͢ΔϨΠΞ΢τ
    • Title

    View Slide

  63. 2018.2.8
    Graphic contents
    Transition։࢝ޙং൫
    • Χʔυશମ͕ը໘ΛຒΊΔ༻ʹ޿͕ͬͯ
    ͍͘
    • ౤ߘऀ΍λΠτϧͳͲ΋ಉ͡Α͏ʹಈ͍
    ͍ͯ͘
    ࣮૷ͷղઆ Graphic contents

    View Slide

  64. 2018.2.8
    Graphic contents
    Transition։࢝ޙத൫
    • എܠʹઃఆ͍ͯͨ͠ImageView͕ը໘
    ͍ͬͺ͍ʹ޿͕Δ
    ࣮૷ͷղઆ Graphic contents

    View Slide

  65. 2018.2.8
    Graphic contents
    Transition։࢝ޙऴ൫1/2
    • ίϯςϯπͷϩʔυ͕ऴྃ͠ɺϔομʔ
    ෦෼͕ϑΣʔυΞ΢τ&্ʹফ͍͑ͯ͘
    ࣮૷ͷղઆ Graphic contents

    View Slide

  66. 2018.2.8
    Graphic contents
    Transition։࢝ޙऴ൫2/2
    • ίϯςϯπͱഎܠը૾͕ΫϩεϑΣʔυ
    ͢ΔܗͰೖΕସΘΔ
    ࣮૷ͷղઆ Graphic contents

    View Slide

  67. 2018.2.8

    View Slide

  68. 2018.2.8
    Graphic contents
    Shared Elements
    ࣮૷ͷղઆ
    5JNFMJOF'SBNFOU (SBQIJD$POUFOUT'SBHNFOU
    7JFX %FTDSJQUJPO 7JFX %FTDSJQUJPO
    *NBHF7JFX Χʔυഎܠ *NBHF7JFX എܠը૾
    -JOFBS-BZPVU ౤ߘऀͷϨΠΞ΢τ -JOFBS-BZPVU ౤ߘऀͷϨΠΞ΢τ
    5FYU7JFX λΠτϧ 5FYU7JFX λΠτϧ
    5FYU7JFX ϝσΟΞ 5FYU7JFX ϝσΟΞ
    Graphic contents

    View Slide

  69. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml

    Graphic contents

    View Slide

  70. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml

    Graphic contents
    android:id="@+id/web_view_graphic_content" />
    android:id="@+id/background_view" />

    View Slide

  71. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml

    Graphic contents
    android:id="@+id/web_view_graphic_content" />
    android:id="@+id/background_view" />

    View Slide

  72. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml

    Graphic contents
    android:id="@+id/web_view_graphic_content" />
    android:id="@+id/background_view" />


    View Slide

  73. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml

    Graphic contents
    android:id="@+id/web_view_graphic_content" />
    android:id="@+id/background_view" />


    android:id="@+id/header">

    View Slide

  74. 2018.2.8
    GraphicContentsFragment
    ϨΠΞ΢τߏ଄
    android:id="@+id/content_root">
    ࣮૷ͷղઆ
    fragment_graphic_contents.xml
    Graphic contents
    android:id="@+id/web_view_graphic_content" />
    android:id="@+id/background_view" />


    android:id="@+id/header">


    android:id="@+id/layout_poster" />
    android:id="@+id/text_title" />
    android:id="@+id/label_ad" />
    android:id="@+id/text_source_media" />
    android:id="@+id/text_published_at" />

    View Slide

  75. 2018.2.8
    GraphicContentsFragment
    TransitionपΓͷίʔυ1/2
    ࣮૷ͷղઆ Graphic contents
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
    @Nullable ViewGroup container,
    @Nullable Bundle savedInstanceState) {
    mBinding = FragmentPostArticleSp1Rev2Binding.inflate(inflater,
    container, false);
    ViewCompat.setTransitionName(mBinding.backgroundView,
    getString(R.string.transition_background));
    ViewCompat.setTransitionName(mBinding.textTitle,
    getString(R.string.transition_text_title));
    ViewCompat.setTransitionName(mBinding.layoutPoster.getRoot(),
    getString(R.string.transition_item_user));
    ViewCompat.setTransitionName(mBinding.textSourceMedia,
    getString(R.string.transition_item_source_media));
    return mBinding.getRoot();
    }

    View Slide

  76. 2018.2.8
    GraphicContentsFragment
    TransitionपΓͷίʔυ2/2
    ࣮૷ͷղઆ Graphic contents
    @Override
    public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    TransitionSet transitionSet =
    new TransitionSet().setDuration(400).setStartDelay(200);
    Fade fadeTransition = new Fade();
    Transition slideUpTransition = new Slide(Gravity.TOP)
    .setStartDelay(100)
    .excludeTarget(R.id.background_view, true);
    transitionSet.addTransition(fadeTransition);
    transitionSet.addTransition(slideUpTransition);
    transitionSet.setInterpolator(AnimationUtils.loadInterpolator(
    getContext(),
    R.anim.accelerate_quad));
    TransitionManager.beginDelayedTransition(((ViewGroup) getView()),
    transitionSet);
    mBinding.card.setVisibility(View.INVISIBLE);
    mBinding.backgroundView.setVisibility(View.INVISIBLE);
    view.setVisibility(View.VISIBLE);
    }

    View Slide

  77. 2018.2.8
    @Override
    public void onStart() {
    super.onStart();
    mPostAccessor.getObservable()
    .compose(this.bindToLifecycle())
    .subscribe(post -> {
    refreshPost(post, mState);
    getActivity().supportStartPostponedEnterTransition();
    }, e -> recordError(null, this, e, null));
    }
    ࣮૷ͷղઆ
    GraphicContentsFragment
    Ωϟογϡʹ͋Δهࣄͷσʔλ(post)Λऔಘ͠ɺ׬ྃޙTransitionΛ࠶։
    Graphic contents

    View Slide

  78. 2018.2.8
    ϙΠϯτ
    • Transition։࢝લͷλΠϛϯάͰҰ࣌ఀࢭ͢Δ
    • Viewͷ४උ͕Ͱ͖ͨΒ࠶։
    • ࣮ࡍʹେ͖͘ಈ͍͍ͯΔͷ͸ImageView͚ͩ
    • ࡉ͔͘ಈ͍͍ͯΔΞΠςϜୡ͸
    TransitionFrameworkͷ͓͔͛
    • ΞχϝʔγϣϯͷAPI͸৭ʑ͋ΔͷͰɺཁॴཁ
    ॴͰ૊Έ߹Θͯ͠࢖͍ͬͯ͘
    ࣮૷ͷղઆ
    GraphicContentsFragment
    Graphic contents

    View Slide

  79. 2018.2.8
    Ξχϝʔγϣϯ࣮૷ͷצॴ
    ·ͣ͸ਅͬ޲͔Βߟ͑ͣʹ΍Ζ͏

    View Slide

  80. 2018.2.8
    ࡶʹ࡞Δ
    Ξχϝʔγϣϯ࣮૷ͷצॴ ·ͣ͸ਅͬ޲͔Βߟ͑ͣʹ΍Ζ͏

    View Slide

  81. 2018.2.8
    ὃ͢Α͏ʹߟ͑Δ
    Ξχϝʔγϣϯ࣮૷ͷצॴ ·ͣ͸ਅͬ޲͔Βߟ͑ͣʹ΍Ζ͏

    View Slide

  82. 2018.2.8
    ਅࣅΛ͢Δ
    Ξχϝʔγϣϯ࣮૷ͷצॴ ·ͣ͸ਅͬ޲͔Βߟ͑ͣʹ΍Ζ͏

    View Slide

  83. 2018.2.8
    ఘΊͳ͍
    Ξχϝʔγϣϯ࣮૷ͷצॴ ·ͣ͸ਅͬ޲͔Βߟ͑ͣʹ΍Ζ͏

    View Slide

  84. 2018.2.8
    ΞχϝʔγϣϯͷDebug

    View Slide

  85. 2018.2.8
    • AnimatorεέʔϧΛ5xʙ10xʹ͢Δ
    • ϨΠΞ΢τͷڥքઢΛදࣔ͢Δ
    • γϣʔτΧοτͱͯ͠௨஌ͷॴʹஔ͍ͱ͘
    ͱྑ͍͔΋
    ΞχϝʔγϣϯͷDebug
    ։ൃऀΦϓγϣϯ

    View Slide

  86. 2018.2.8
    • android:animateLayoutChanges=“true"
    ͕ViewGroupʹઃఆ͞Ε͍ͯΔ͔΋ʁ
    • ࣗ෼Ͱద༻ͨ͠ΞχϝʔγϣϯͱίϯϑϦ
    ΫτΛى͍ͯ͜͠ΔՄೳੑ͕͋Δ
    • clipChildren/clipToPaddingͷࢦఆΛ͍ͬ͡
    ͯΈΔ
    • େ͖͘࿮Λ௒͑ͯΞχϝʔγϣϯ͢Δ࣌͸
    ্هͷࢦఆ͕ฉ͍ͯ͘Δɻfalseʹ͢Δ͜ͱ
    ͰViewGroupͷ࿮Λඈͼग़ͯ͠ಈ͘Α͏
    ʹͰ͖Δ͔΋͠Εͳ͍
    ΞχϝʔγϣϯͷDebug
    มͳಈ͖Λ͍ͯͨ͠Β1/2
    ҎԼͷ߲໨ΛٙͬͯΈͯ΋͍͍͔΋

    View Slide

  87. 2018.2.8
    • Ұ୴ϨΠΞ΢τϑΝΠϧΛ࡞Γ௚ͯ͠ΈΔ
    • ແཧͷ͋ΔϨΠΞ΢τϑΝΠϧʹͳ͍ͬͯ
    Δ͔΋͠Εͳ͍
    • ֊૚͕ਂ͍ͱ΍΍͘͜͠ͳΔɻͳΔ΂͘
    ConstrainLayoutͳͲΛ࢖ͬͯ֊૚Λઙ͘
    ͢Δ͜ͱ͕ग़དྷͳ͍͔ߟ͑Δ
    • Ұͭͷख๏͚ͩͰΰϦԡ͠͠Α͏ͱ͍ͯ͠ͳ
    ͍͔ʁ
    • ଞʹָͳํ๏͕ͳ͍͔ݕূ͢Δɻ·ͨɺࣅ
    ͨΑ͏ͳΞϓϦ͕ͳ͍͔୳ͯ͠ΈΔ
    ΞχϝʔγϣϯͷDebug
    มͳಈ͖Λ͍ͯͨ͠Β2/2
    ҎԼͷ߲໨ΛٙͬͯΈͯ΋͍͍͔΋

    View Slide

  88. 2018.2.8
    • Shared Element Transition͸αϯϓϧίʔυ
    ࣗମ͸؆୯ͳ΋ͷ͕ଟ͍͚Ͳɺ࣮ࡍʹ૊Έࠐ
    ΉͱͳΔͱɺϨΠΞ΢τϑΝΠϧͷ࡞Γํ౳
    ޻෉͕ඞཁʹͳΔ
    • Shared Element Transition͸Ұ࣌ఀࢭ/࠶։
    ͕ίϯτϩʔϧͰ͖Δ
    • ͜·ͬͨΒɺҰ୴Ϧηοτͯ͠ߟ͑Δɻ·ͨɺ
    ࣅͯΔΞϓϦΛ୳ͯ͠Α͘؍࡯͢Δ
    ·ͱΊ
    ·ͱΊ

    View Slide

  89. 2018.2.8
    Thanks!

    View Slide