質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

387閲覧

アプリ起動時のonLayoutChildの挙動について

inzs

総合スコア17

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2018/05/06 21:10

前提・実現したいこと

ViewPagerの実装を勉強しながらそれっぽいアプリのような形になるまでどんどん機能を追加していこうという勉強をしています。
ViewPagerが形になったのでBottomNavigationViewを追加して、こちらのサイトの「■スクロール時に隠す」の項を参考にしてBottomNavigationViewをスクロール時に隠すようにしようとしています。

BottomNavigationViewのカスタマイズ - Re.Ra.Ku アドベントカレンダー day 18

実装はサイトにあるものほぼそのまま(サイト上ではRecycleViewがあるところにViewPagerを指定してなかに長文TextViewを仕込んでいる)で、実際に動かしてみたところ下スクロールすると消えることは消えるのですが上スクロールしても表示が元に戻りません。
おかしいなと思い色々試していると、"起動時だけ"、childのgetTop, getBottomが0になっていることがわかりました。
しかし、なぜそうなっているのか、どう回避すれば良いかがわかりません。
ご教示お願いします。

試したこと

  • 起動時に発動する時のchildがBottomNavigationViewではない別のなにかを拾っているのかと思ったのですが、childの中身はきちんとBottomNavigationViewであることをgetIdで確認しています。
  • 起動後にBottomNavigationViewの最初以外のメニュー(※)をタップすると、正常にgetTop等が働いて目的通りの動作をします。

※メニューA,B,Cとある時、AをタップしてもonLayoutChildは発動せず、BまたはCをタップした時のみonLayoutChildが発動しています。なお各種メニューはイベント未設定のため現状見かけだけです。

該当のソースコード

activity_main.xml

XML

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:id="@+id/ll" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 android:orientation="vertical" 9 tools:context="com.hoge.viewpager.MainActivity"> 10 11 <android.support.design.widget.CoordinatorLayout 12 android:id="@+id/cl" 13 android:layout_width="match_parent" 14 android:layout_height="match_parent" 15 android:fitsSystemWindows="true"> 16 17 <android.support.v4.view.ViewPager 18 android:id="@+id/viewpager" 19 android:layout_width="match_parent" 20 android:layout_height="match_parent" 21 app:layout_behavior="@string/appbar_scrolling_view_behavior"> 22 23 </android.support.v4.view.ViewPager> 24 25 <android.support.design.widget.BottomNavigationView 26 android:id="@+id/bottomNavigationView" 27 android:layout_width="match_parent" 28 android:layout_height="wrap_content" 29 android:layout_gravity="bottom" 30 app:itemBackground="@color/colorPrimaryDark" 31 app:itemIconTint="@android:color/white" 32 app:itemTextColor="@android:color/white" 33 app:layout_behavior="com.hoge.viewpager.BottomNavigationBehavior" 34 app:layout_constraintBottom_toTopOf="@+id/viewpager" 35 app:layout_constraintEnd_toEndOf="@+id/viewpager" 36 app:layout_constraintHorizontal_bias="1.0" 37 app:layout_constraintStart_toStartOf="@+id/viewpager" 38 app:layout_constraintTop_toTopOf="parent" 39 app:menu="@menu/navigation" /> 40 41 </android.support.design.widget.CoordinatorLayout> 42 43</LinearLayout>

問題の箇所

Java

1 public boolean onLayoutChild(CoordinatorLayout parent, BottomNavigationView child, int layoutDirection) { 2 defaultTop = child.getTop(); 3 defaultBottom = child.getBottom(); 4 defaultHeight = defaultBottom - defaultTop; 5 Log.d(TAG, "onLayoutChild: "+defaultTop); //起動時0 メニューB,Cタップ時は正常に取得 6 Log.d(TAG, "onLayoutChild: "+defaultBottom); //起動時0 メニューB,Cタップ時は正常に取得 7 Log.d(TAG, "onLayoutChild: "+defaultHeight); 8 Log.d(TAG, "onLayoutChild: "+ _context.getResources().getResourceEntryName(child.getId()) ); //起動時ちゃんとbottomNavigationViewが表示される 9 10 return super.onLayoutChild(parent, child, layoutDirection); 11 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

CoordinatorLayoutのソースコードを読んでみた限りだと、初回はレイアウトがされていない状態でbehavior.onLayoutChildが呼ばれるようなので、自分でレイアウト用のメソッドを呼んであげる必要がありそうです。

java

1public boolean onLayoutChild(CoordinatorLayout parent, BottomNavigationView child, int layoutDirection) { 2 // 自分でレイアウト用のメソッドを呼ぶ 3 parent.onLayoutChlid(child, layoutDirection); 4 5 defaultTop = child.getTop(); 6 defaultBottom = child.getBottom(); 7 defaultHeight = defaultBottom - defaultTop; 8 9 // 自分でレイアウト用のメソッドを呼んだことを上に伝える 10 return true; 11}

このようにしてみてはいかがでしょうか?

投稿2018/05/07 02:30

編集2018/05/07 05:58
kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

inzs

2018/05/07 05:13 編集

ありがとうございます。回答頂いた方法で目的通り動作しました。 一応初回だけでいいかと思って以下のようにしてみました。 if (child.getTop()== child.getBottom()) parent.onLayoutChild(child,layoutDirection);
kakajika

2018/05/07 06:00

そうですね、たしかに無駄なレイアウト処理を行うようになっていました。 ソースコードによると、behavior.onLayoutChildでtrueを返すことにより、レイアウト処理が重複して走ってしまわないように指定できるようです。そのように回答を修正しておきました。
inzs

2018/05/07 06:33

なるほど!それだけで問題なさそうですね。 私が先に書いた if (child.getTop() == child.getBottom()) とした場合、return super.onLayoutChild~で再レイアウト処理されていましたが、レイアウト処理前にTop,Bottomを取得してしまっているため、BottomNavigationViewを隠した後にViewPagerをスライドさせた時にonLayoutChildが発動して、BottomNavigationViewが隠れてしまっている状態の座標を取得するため正しく表示されないようです。 よって、編集回答頂いた内容そのままが一番良いようです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問