LoginSignup
7
7

More than 5 years have passed since last update.

[Android] bringToFrontが効かない

Posted at

bringToFront not working!!

もともと、以下のような階層で描かれているxmlがあって、
bringToFrontを使って、root直下のFrameLayoutのviewをトップに出していました。(FrameLayoutを一番下に置いてもいいです。)

before.xml
root: RelativeLayout

-FrameLayout
-LinearLayout
 - ImageButton
 - EditText
 - ImageButton
- RecyclerView

それを以下の様にする必要がありましたが、なぜがbringToFrontが効かなくなりました。

after.xml
root: RelativeLayout

-FrameLayout
-LinearLayout
 - ImageButton
 - EditText
 - ImageButton
- CardView
 - RecyclerView

詳細

間違いなくCardViewが悪いのは予測がつくわけですが、bringToFrontのメソッドを覗きにいくと、

View.java
public void bringToFront() {
 if (mParent != null) {
  mParent.bringChildToFront(this);
 }
}

親Viewがいれば、親Viewが所持する子Viewを一番前に持ってくるようです。
そこでViewParent(mParentのオブジェクト)の中身を見ると、

ViewParent.java
/**
 * this method should be followed by calls to 
 * {@link#requestLayout()} and {@link View#invalidate()} 
 * on this parent to force the parent to redraw with the new child ordering.
 * /

だそうです。
つまり、bringToFrontを使った際には、親Viewが子Viewの順番を考慮して、再描画する必要があるので、requestLayout() と invalidate()を利用しろということでした。

ところが、これをやってもL以上ではダメでした。
bringToFrontにしてroot直下の階層で一番前面に出してもロリポップ以上では、エレベーションを考慮する必要があります。

今回の場合利用している、root直下のCardViewのエレベーションを2dpつけていたのですが、root直下のFrameLayoutのプロパティでandroid:elevation="2dp"を追加してあげると直りました。(2dp以上ならOK)

結論

  1. bringToFront -> requestLayout && invalidate()の順番で呼ぶ。
  2. ロリポップ以上はエレベーションに気をつけて、必要ならばelevationをつける。(Material Designに沿って)

以上です。

7
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7