Toolbarの挙動をコードで変える

例えば, 最初の画面ではToolbarを動かさないようにしたいが,次の画面ではToolbarをcollapseさせたい時の方法

方法


android.support.design.widget.CollapsingToolbarLayoutapp:layout_scrollFlags属性をJavaコード中で変更する.
実際には、以下のように行う.
1
2
3
4
5
6
7
8
9
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
 
...
 
CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
AppBarLayout.LayoutParams appBarLayoutParams = (AppBarLayout.LayoutParams)collapsingToolbarLayout.getLayoutParams();
appBarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
toolbarLayout.setLayoutParams(appBarLayoutParams);

setScrollFlagsメソッドに代入する定数は以下の通りで, 複数指定したい場合は, 上のコードのようにビット演算子OR|をはさんでやる.

定数 対応するapp:layout_scrollFlagsの値
SCROLL_FLAG_ENTER_ALWAYS enterAlways
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED enterAlwaysCollapsed
SCROLL_FLAG_SCROLL scroll
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED exitUntilCollapsed
SCROLL_FLAG_SNAP snap

上の定数は, android.support.design.widget.AppBarLayout.LayoutParamsのフィールドであるが, ToolBarの挙動については, こちらが詳しい.

実装例


FloatingActionButtonを押すことで, Toolbarの挙動をenterAlways <-> scroll|exitUntilCollapsedと相互に変える. 以下のような感じ.

styles.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<resources>
 
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
 
    <style name="CollapsedTextAppearance" parent="@android:style/TextAppearance.Medium">
        <item name="android:textColor">#ffffff</item>
    </style>
 
    <style name="ExpandTextAppearance" parent="@android:style/TextAppearance.Large">
        <item name="android:textColor">#ffffff</item>
        <item name="android:textSize">56sp</item>
    </style>
</resources>

ToolBarをつかうので, アプリケーションテーマとしてNoActionBarを採用している.
また, 11行目から13行目, 15行目から18行目は, ToolBarのタイトル文字がデフォルトでは黒色なので, 見やすい白色にするために追加している(後に, activity_main.xmlのCollaspingToolbarLayoutapp:collapsedTitleTextAppearance, app:expandedTitleTextAppearanceで指定してやる).

activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
 
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:collapsedTitleTextAppearance="@style/CollapsedTextAppearance"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleTextAppearance="@style/ExpandTextAppearance"
            app:layout_scrollFlags="enterAlways"
            app:title="Hello!"
            app:toolbarId="@+id/toolbar">
 
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize" />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
 
    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
 
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="WORLD!"
            android:textAlignment="inherit"
            android:textSize="200sp" />
 
    </android.support.v4.widget.NestedScrollView>
 
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:clickable="true"
        android:focusable="true"
        app:srcCompat="@drawable/ic_refresh_white_24dp" />
 
</android.support.design.widget.CoordinatorLayout>

styles.xmlで述べたが, 17行目と19行目でToolBarのタイトルのテキストスタイルを変更している
54行目に出てくる, FloatingActionButtonに使うdrawableリソースはここには載せないが, 適当な画像を使えばよい.

MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.blogspot.ko_ika.changeappbarlayout;
 
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
 
public class MainActivity extends AppCompatActivity {
 
    // status : Toolbarの状態, 0の時, enterAlwaysで, 1の時, scroll|exitUntilCollapsed
    private int status;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        status = 0;
 
        // floatingActionButtonを押したときのイベントを登録
        FloatingActionButton floatingActionButton = findViewById(R.id.floatingActionButton);
        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CollapsingToolbarLayout collapsingToolbarLayout;
                AppBarLayout.LayoutParams appBarLayoutParams;
                AppBarLayout appBarLayout;
                ViewGroup.LayoutParams layoutParams;
                switch (status) {
                    case 0:
                        collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
                        appBarLayoutParams = (AppBarLayout.LayoutParams)collapsingToolbarLayout.getLayoutParams();
                        appBarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
                        collapsingToolbarLayout.setLayoutParams(appBarLayoutParams);
 
                        // AppBar(Toolbar)の高さを192dpにする.
                        appBarLayout = findViewById(R.id.appbar);
                        layoutParams = appBarLayout.getLayoutParams();
                        layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 192, getResources().getDisplayMetrics());
                        appBarLayout.setLayoutParams(layoutParams);
                        status = 1;
                        break;
                    case 1:
                        collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
                        appBarLayoutParams = (AppBarLayout.LayoutParams)collapsingToolbarLayout.getLayoutParams();
                        appBarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
                        collapsingToolbarLayout.setLayoutParams(appBarLayoutParams);
 
                        // AppBar(Toolbar)の高さをwrap_contentにする.
                        appBarLayout = findViewById(R.id.appbar);
                        layoutParams = appBarLayout.getLayoutParams();
                        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
                        appBarLayout.setLayoutParams(layoutParams);
                        status = 0;
                        break;
                }
            }
        });
    }
}

ハイライトしたところで, Toolbarの挙動を変更している.
基本的に, statusで現在の状態を管理している. 詳しい説明は, コード中のコメントを参照.

実装例の最初に挙げたgifを見て気づいた方もいるかもしれないが, このコードの問題として, AppBarLayouheightwrap_contentか, あまり大きくない値を指定するとタイトルが表示されないことが挙げられる(Toolbarapp:titleを設定してないことは関係ない!). この問題は, CollapsingToolbarLayoutを使わないようにすれば回避できる:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="Hello!"
            app:layout_scrollFlags="enterAlways"/>
    </android.support.design.widget.AppBarLayout>
 
    ...
 
</android.support.design.widget.CoordinatorLayout>

しかし, この方法では, Toolbarの挙動をJavaコード中では変えられないっぽく, 自作のカスタムViewを作る等面倒なことをしないといけないみたい(? 現在模索中)

参考にしたサイト




0 件のコメント:

コメントを投稿

FloatingActionButtonをスクロール中に消す

NestedScrollView を下にスクロールしている間は, FloatingActionButton を表示させないようにする. 少し変えれば, RecyclerView 等の他のScrollViewにも使えそう(未確認). 下に実際の挙動を示した. 目次 ...