[翻訳] リストをスクロールしたときToolbarを表示・非表示にする方法(パート2)

#原文
[How to hide/show Toolbar when list is scrolling (part 2)](https://mzgreen.github.io/2015/02/28/How-to-hideshow-Toolbar-when-list-is-scrolling%28part2%29/)
訳文を掲載する承諾は得ております。

#まえがき
このシリーズの2回目(そして最後)の投稿です。もしあなたが[パート1](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)を読んでいないなら、読むことをお勧めします。[前のパート](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)ではGoogle+のようにToolbarを隠す効果の実装を行うことができました。今日はGoogle PlayストアのToolbarのような振る舞いをどのように作れるかを見ていきましょう。はじまりはじまり。

始める前に、この[プロジェクト](https://github.com/mzgreen/HideOnScrollExample)を少しリファクタリングしたことを述べておきます。`MainActivity`から呼び出される2つの`Activity`、`PartOneActivity`と`PartTwoActivity`に分離しました。あなたが参照したいクラスを簡単に見つけられるように、コードは`partone`と`parttwo`のパッケージにあります。

最終的に完成した効果をPlay StoreのToolbarと比較してみます。
![goal](http://mzgreen.github.io/images/2/goal.gif)
![playstore](http://mzgreen.github.io/images/2/playstore.gif)

#まず最初に
`build.gradle`は[パート1](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)と同じなので、そちらを参照してもらうことにして、`Activity`のレイアウトを作るところから始めたいと思います。

```xml:activity_part_two.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingTop="?attr/actionBarSize"
            android:clipToPadding="false"/>
            
    <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>
 
</FrameLayout>
```

`RecyclerView`と`Toolbar` (後ほど`Tabs`を追加)だけでできています。[前の投稿](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)では(`RecyclerView`にpaddingを追加するという) 2つ目の方法を用いていたことに気を付けてください。

リストアイテムのレイアウトファイルは、[前](https://gist.github.com/mzgreen/b44afa284a0c3c4e0b9c#file-recycler_item-xml)とまったく同じなので省略します。`RecyclerAdapter`も同様に飛ばします。([こちら](https://gist.github.com/mzgreen/f0dc97062bb5f1c534b1#file-recycleradapter-java)を参照してください。シンプルでヘッダーのないアダプターです。)

`PartTwoActivity`のコードを見てみます。

```java:ActivityPartTwo.java
public class PartTwoActivity extends ActionBarActivity {
 
    private Toolbar mToolbar;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppThemeGreen);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_part_two);
 
        initToolbar();
        initRecyclerView();
    }
 
    private void initToolbar() {
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        setTitle(getString(R.string.app_name));
        mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
    }
 
    private void initRecyclerView() {
        final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
        recyclerView.setAdapter(recyclerAdapter);
        recyclerView.setOnScrollListener(new HidingScrollListener(this));
    }
 
    private List<String> createItemList() {
        List<String> itemList = new ArrayList<>();
        for(int i=0;i<20;i++) {
            itemList.add("Item "+i);
        }
        return itemList;
    }
}
```

`RecyclerView`と`Toolbar`の基本的な初期化をしています。27行目で`OnScrollListener`をセットしていることに注意してください。

最も重要な部分は`HidingScrollListener`です。これを作っていきます。

```java:HidingScrollListener.java
public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {
 
    private int mToolbarOffset = 0;
    private int mToolbarHeight;
 
    public HidingScrollListener(Context context) {
        mToolbarHeight = Utils.getToolbarHeight(context);
    }
 
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
 
        clipToolbarOffset();
        onMoved(mToolbarOffset);
 
        if((mToolbarOffset <mToolbarHeight && dy>0) || (mToolbarOffset >0 && dy<0)) {
            mToolbarOffset += dy;
        }
    }
 
    private void clipToolbarOffset() {
        if(mToolbarOffset > mToolbarHeight) {
            mToolbarOffset = mToolbarHeight;
        } else if(mToolbarOffset < 0) {
            mToolbarOffset = 0;
        }
    }
 
    public abstract void onMoved(int distance);
}
```

もしあなたが[前のパート](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)を読んだのなら、見覚えがあることでしょう。(実際には、よりシンプルになっています。)スクロールされた`Toolbar`の間接的なオフセットを保存しておく`mToolbarOffset`という重要な変数のみを用いています。次のように0と`Toolbar`の高さの間で値を変化させる、簡単な実装です。

```java:HidingScrollListener.java
if((mToolbarOffset <mToolbarHeight && dy>0) || (mToolbarOffset >0 && dy<0)) {
    mToolbarOffset += dy;
} 
```

上にスクロールした時に(`Toolbar`の高さより大きくならないように)値を増加させ、下にスクロールした時に(0より小さくならないように)値を減少させます。これらの値を制限する理由がだんだん見えてくると思います。(例えばフリックした時に)短時間で範囲外の値を撮る可能性があり、ちらつきを起こす可能性があるため、`mToolbarOffset`をクリップするのです。また、`onMoved()`をスクロール時に呼び出す抽象メソッドを定義しておきます。ここでは不思議に思われることでしょう。

`PartTwoActivity`に戻って、メソッド`onMoved()`をスクロールリスナーの中に実装します。

```java:PartTwoActivity.java
private void initRecyclerView() {
    final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
    recyclerView.setAdapter(recyclerAdapter);
 
    recyclerView.setOnScrollListener(new HidingScrollListener(this) {
        @Override
        public void onMoved(int distance) {
            mToolbarContainer.setTranslationY(-distance);
        }
    });
}
```

はい、動きました。アプリを実行すると、実装通りに動きます。
![nosnap](https://mzgreen.github.io/images/2/nosnap.gif)

まあまあです。予想通り、`Toolbar`はリストとともに動いて隠れ、また戻ってきます。変数`mToolbarOffset`に実装した制限のおかげです。もし0より大きく`mToolbarOffset`より小さいかのチェックを省略していたなら、`Toolbar`は画面の外のどこか遠くへ行ってしまうことでしょう。`mToolbarHeight`より上にスクロールしたとき、それより上にスクロールさせず、リストの上で停止させることで、下にスクロールしたとき、すぐ表示することができます。

まあまあ良く動きますが、望んでいたものではありません。スクロールを途中で止めたときに`Toolbar`が半分だけ見てているのは気持ち悪いです。実際に、Google Playゲームアプリで見られるこの動きはバグではないでしょうか。

#Toolbarのスナップ
Chromeアプリのロゴ・検索バーやPlayストアアプリの`Toolbar`のように、Viewは所定の位置にスムーズにスナップするべきです。マテリアルデザインのガイドライン・チェックリストのどこかで見たか、Google I/Oのプレゼンの中で聞いたはずです。

もう一度、`HidingScrollListener`のコードを見てみましょう。

```java:HidingScrollListener.java
public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {
 
    private static final float HIDE_THRESHOLD = 10;
    private static final float SHOW_THRESHOLD = 70;
 
    private int mToolbarOffset = 0;
    private boolean mControlsVisible = true;
    private int mToolbarHeight;
 
    public HidingScrollListener(Context context) {
        mToolbarHeight = Utils.getToolbarHeight(context);
    }
 
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
 
        if(newState == RecyclerView.SCROLL_STATE_IDLE) {
            if (mControlsVisible) {
                if (mToolbarOffset > HIDE_THRESHOLD) {
                    setInvisible();
                } else {
                   setVisible();
                }
            } else {
                if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                    setVisible();
                } else {
                    setInvisible();
                }
            }
        }
        
    }
 
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
 
        clipToolbarOffset();
        onMoved(mToolbarOffset);
 
        if((mToolbarOffset <mToolbarHeight && dy>0) || (mToolbarOffset >0 && dy<0)) {
            mToolbarOffset += dy;
        }
 
    }
 
    private void clipToolbarOffset() {
        if(mToolbarOffset > mToolbarHeight) {
            mToolbarOffset = mToolbarHeight;
        } else if(mToolbarOffset < 0) {
            mToolbarOffset = 0;
        }
    }
 
    private void setVisible() {
        if(mToolbarOffset > 0) {
            onShow();
            mToolbarOffset = 0;
        }
        mControlsVisible = true;
    }
 
    private void setInvisible() {
        if(mToolbarOffset < mToolbarHeight) {
            onHide();
            mToolbarOffset = mToolbarHeight;
        }
        mControlsVisible = false;
    }
 
    public abstract void onMoved(int distance);
    public abstract void onShow();
    public abstract void onHide();
}
```

少し複雑になりましたが、そこまで身構えないで大丈夫です。クラス`RecyclerView.OnScrollListener`の2つ目のメソッド`onScrollStateChanged()`をオーバーライドしただけです。このメソッドの中では次のようなことをしています。

* リストがスクロール中でもフリック中でもない状態`RecyclerView.SCROLL_STATE_IDLE`にあるかどうかを確認します。(もしスクロール中かフリック中であるなら、前のように`Toolbar`のY座標を手動で変化させていくためです。)

* 指を離してリストが止まって(状態`RecyclerView.SCROLL_STATE_IDLE`に)いるなら、表示されているかを確認します。表示されている場合には`mToolbarOffset`が`HIDE_THRESHOLD`より大きければ非表示にし、非表示の場合には`mToolbarOffset`が`SHOW_THRESHOLD`より小さければ再び表示させます。

    ```java:HidingScrollListener.java
    if (mControlsVisible) {
        if (mToolbarOffset > HIDE_THRESHOLD) {
            setInvisible();
        } else {
           setVisible();
        }
    } 
    ```

* そして非表示の場合には逆の動きをします。(`mToolbarHeight - mToolbarOffset`により上の座標を求めて)`mToolbarOffset`が`SHOW_THRESHOLD`より大きければ表示し、`HIDE_THRESHOLD`より小さければ再び非表示にします。

    ```java:HidingScrollListener.java
    else { // it's not visible
        if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
            setVisible();
        } else {
            setInvisible();
        }
    }
    ```

`onScrolled()`は以前のままで、これら以外には書き換える箇所はありません。最後にクラス`PartTwoActivity`の中に新しく2つの抽象メソッドを実装する必要があります。

```java:PartTwoActivity.java
private void initRecyclerView() {
    final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
    recyclerView.setAdapter(recyclerAdapter);
 
    recyclerView.setOnScrollListener(new HidingScrollListener(this) {
 
        @Override
        public void onMoved(int distance) {
            mToolbarContainer.setTranslationY(-distance);
        }
 
        @Override
        public void onShow() {
            mToolbarContainer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
        }
 
        @Override
        public void onHide() {
            mToolbarContainer.animate().translationY(-mToolbarHeight).setInterpolator(new AccelerateInterpolator(2)).start();
        }
 
    });
}
```

ビルドして実装した効果を見てみましょう。
![snapnotabs](https://mzgreen.github.io/images/2/snapnotabs.gif)

良く動いています。:smile: 

タブを追加するとコードが複雑になると思われるかもしれませんが、そうではないことをお見せしましょう。

#タブの追加
`Activity`のレイアウトを修正する必要があります。

```xml:part_two_activity.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"/>
 
    <LinearLayout
            android:id="@+id/toolbarContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
 
        <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"/>
 
        <include layout="@layout/tabs"/>
    </LinearLayout>
 
</FrameLayout>
```

そして`tabs.xml`は次のようにします。

```xml:tabs.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/tabsHeight"
    android:background="?attr/colorPrimary">
    <FrameLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" >
        <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="@string/tab_1"
                android:gravity="center"
                style="@style/Base.TextAppearance.AppCompat.Body2"
                android:textColor="@android:color/white"
                android:background="@android:color/transparent" />
        <View
                android:layout_width="match_parent"
                android:layout_height="6dp"
                android:layout_gravity="bottom"
                android:background="@android:color/white" />
    </FrameLayout>
    <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="@string/tab_2"
            android:gravity="center"
            style="@style/Base.TextAppearance.AppCompat.Body2"
            android:textColor="@android:color/white"
            android:background="@android:color/transparent" />
</LinearLayout>
```

御覧のように、本物の`Tabs`ではなく、見かけを似せたレイアウトだけを追加しています。実装を変更するのはここだけです。ここに色々なViewを置くことができます。マテリアルデザインに基づいた`Tabs`の実装がgithubにはいくつかあるので、ご自分でそれらを実装してください。:smile:

`Tabs`を追加するということは、リストを少し覆うということで、paddingを増やす必要があります。自由に設定するため、xmlではこの設定を行いません。(`part_two_activity.xml`の`RecyclerView`からpaddingを削除することに注意してください。)`Toolbar`は向きや端末(例えばタブレットなど)により異なる高さを持つことがあり、すべてのケースに対応するには大量のxmlを記述する必要があるからです。その代り、コードでpaddingを設定します。

```java:PartTwoActivity.java
private void initRecyclerView() {
   final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
 
   int paddingTop = Utils.getToolbarHeight(PartTwoActivity.this) + Utils.getTabsHeight(PartTwoActivity.this);
   recyclerView.setPadding(recyclerView.getPaddingLeft(), paddingTop, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
 
   recyclerView.setLayoutManager(new LinearLayoutManager(this));
   
   // ...
}
```

非常に簡単で、`Toolbar`の高さと`Tabs`の高さの合計をpaddingに設定するだけです。実行した結果、このようになります。

![withtabs](https://mzgreen.github.io/images/2/withtabs.png)

大丈夫、リストの一つ目の項目は完全に表示されており、移動することもできています。実際に、クラス`HidingScrollListener`に何も変更を加えていません。`PartTwoActivity`に変更を加えるだけです。

```java:PartTwoActivity.java
public class PartTwoActivity extends ActionBarActivity {
 
    private LinearLayout mToolbarContainer;
    private int mToolbarHeight;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppThemeGreen);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_part_two);
 
        mToolbarContainer = (LinearLayout) findViewById(R.id.toolbarContainer);
        initToolbar();
        initRecyclerView();
    }
 
    private void initToolbar() {
        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        setTitle(getString(R.string.app_name));
        mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
        mToolbarHeight = Utils.getToolbarHeight(this);
    }
 
    private void initRecyclerView() {
        final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
 
        int paddingTop = Utils.getToolbarHeight(PartTwoActivity.this) + Utils.getTabsHeight(PartTwoActivity.this);
        recyclerView.setPadding(recyclerView.getPaddingLeft(), paddingTop, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
 
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
        recyclerView.setAdapter(recyclerAdapter);
 
        recyclerView.setOnScrollListener(new HidingScrollListener(this) {
 
            @Override
            public void onMoved(int distance) {
                mToolbarContainer.setTranslationY(-distance);
            }
 
            @Override
            public void onShow() {
                mToolbarContainer.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
            }
 
            @Override
            public void onHide() {
                mToolbarContainer.animate().translationY(-mToolbarHeight).setInterpolator(new AccelerateInterpolator(2)).start();
            }
 
        });
    }
 
    private List<String> createItemList() {
        List<String> itemList = new ArrayList<>();
        for(int i=0;i<20;i++) {
            itemList.add("Item "+i);
        }
        return itemList;
    }
}
```

変更点がお分かりでしょうか。`mToolbarContainer`が`Toolbar`の代わりに`LinearLayout`を参照するようになり、メソッド`onMove()`、`onHide()`の中では`Toolbar`の代わりにこのViewを移動させ、アニメーションさせています。ここでは`Toolbar`と`Tabs`を含むコンテナを移動させる必要があるのです。

実行してみると予想通りに動く気がしますが、目を凝らすと小さなバグがることに気付くでしょう。たまにコンマ何秒の間、`Tabs`と`Toolbar`の間に白い線が現れます。アニメーションが完全に同期していないために生じていると思われます。不幸なことにこれ自体を直すことは無理でしょう。

修正は簡単で、`Toolbar`と`Tabs`の背景を親のレイアウトに移すだけです。

```xml:part_two_activity.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"/>
 
    <LinearLayout
            android:id="@+id/toolbarContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:background="?attr/colorPrimary">  <!-- added here -->
 
        <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"/> <!-- removed from here and tabs.xml -->
 
        <include layout="@layout/tabs"/>
    </LinearLayout>
 
</FrameLayout>
```

これにより、たとえViewのアニメーションが完全に同期していなくても、白い線は現われません。もう一つバグがあり、こちらは[パート1](http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/)と同じものです。`HIDE_THRESHOLD`が十分に小さい場合には、リストの一番上で少し上にスクロールした際に、`Toolbar`が隠れて何もない空間(padding)がリストの上に表示されてしまいます。前回同様に、非常に簡単に直すことができます。

```java:HidingScrollListener.java
public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {
 
    private static final float HIDE_THRESHOLD = 10;
    private static final float SHOW_THRESHOLD = 70;
 
    private int mToolbarOffset = 0;
    private boolean mControlsVisible = true;
    private int mToolbarHeight;
    private int mTotalScrolledDistance;
 
    public HidingScrollListener(Context context) {
        mToolbarHeight = Utils.getToolbarHeight(context);
    }
 
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
 
        if(newState == RecyclerView.SCROLL_STATE_IDLE) {
            if(mTotalScrolledDistance < mToolbarHeight) {
                setVisible();
            } else {
                if (mControlsVisible) {
                    if (mToolbarOffset > HIDE_THRESHOLD) {
                        setInvisible();
                    } else {
                       setVisible();
                    }
                } else {
                    if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                        setVisible();
                    } else {
                        setInvisible();
                    }
                }
            }
        }
    }
    
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
 
        //...
 
        mTotalScrolledDistance += dy;
    }
    
    //...
}
```

リストがどれだけスクロールされたかを格納する変数を追加しただけで、`Toolbar`の表示・非表示すべきかをチェックする際に、まず`Toolbar`の高さよりスクロールされているかをチェック(そうでない場合には再び`Toolbar`を表示)します。

これで終わりです。実行してみましょう。
![goal](https://mzgreen.github.io/images/2/goal.gif)

とてもうまく動作するようになりました。:smile:恐らく他のLayoutManagersでも変更を加えることなく動作するでしょう。

```java:PartTwoActivity.java
private void initRecyclerView() {
   final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
 
   int paddingTop = Utils.getToolbarHeight(PartTwoActivity.this) + Utils.getTabsHeight(PartTwoActivity.this);
   recyclerView.setPadding(recyclerView.getPaddingLeft(), paddingTop, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
 
   recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
   RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
 
   //...
}
```

![grid](https://mzgreen.github.io/images/2/grid.png)

スクロールの状態を保存することについてコメントで質問があり、実際に少しの問題があります。項目のテキストが十分に長く、縦長の画面では2行に、横長の画面では1行になる場合に、アイテムの高さが縦か横かで変化するという点です。縦の状態で100の位置にスクロールしており、`mTotalScrolledDistance`にその値を保存していた場合、端末を回転させ一番上までスクロールすると、`mTotalScrolledDistance`は0にならないのです。簡単な修正方法はありませんが、その場合でも特に問題になりません。本当にしたいことを思い出してみると、回転した後に`mTotalScrolledDistance`を0にリセットし`Toolbar`を表示させれば良いのです。

これでこのシリーズの最後の投稿です。前のパートからいくつかの点を学べたことをうれしく思います。ありがたい言葉に感謝します。:smile:このブログを書き続けていこうと思いますが、次は何を書くかはまだわかりません。:smile:

今回と前回の投稿で述べた方法はとてもよく動くと思いますが、十分にはテストできていませんし、(前に述べた状態保存の問題に見られるように)製品のコードで用いるのに十分かは保証できません。このシリーズのゴールは難しいように見える効果であっても、簡単な方法と標準のAPIで達成できるという点を証明することです。また、この方法は他の多くの事柄(例えば、Google+のプロフィール画面にみられるような、視差効果を伴い、指についてくるTabsを作るなど)にも利用できることでしょう。楽しくコーディングしましょう。

#コード
この投稿で用いたプロジェクトのソースコードはGitHubの[レポジトリ](https://github.com/mzgreen/HideOnScrollExample)にあります。

Michal Z