ページ

2011/05/04

Android SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

|
他の部品を隠さずにSlidingDrawerを使い、コンテンツの大きさに合わせてSlidingDrawerをレイアウトする方法についてです。この説明もタイトルも、一言でうまく伝えられないので、まずは完成イメージをまず載せます。
ソースコードは改めて投稿します。

完成イメージ

1. 画面の下方にスクロールする部品があります。(TextView)
2. ドロワーを開くと、スクロールするビューのスクロールバーがずれています。つまり、ドロワーで隠れてしまった部分を下方にスクロールすることで表示できます。
3. 実際、最下部までスクロールできます。(「終わり」という部分です。)
4. ドロワーを閉じると、スクロールビューが元のサイズに戻ります。


一見するとごく普通の動きで、Gmailのアプリでもメールのチェックボックスにチェックをつけるとドロワーが現れ、同様の動きをします。

Gmailやspモードメールのアプリの動作を見て、これはSlidingDrawerを使っているのだろう、とあたりをつけた所までは良かったのですが、これを実現するのにかなり苦労してしまいました。

問題1

まずSlidingDrawerをよくあるサンプルの通りに作成し、SlidingDrawerのサイズをコンテンツ(上記でいうダミーボタン)のサイズに合わせるためにandroid:layout_height="wrap_content"を指定します。

1. ドロワーが閉じているにもかかわらず、スクロールビューが非表示になっています。(ドロワーが画面一杯に広がってしまっています。)
2. ドロワーを開くと、画面一杯にドロワーが開いてしまいます。


問題2

wrap_contentが効かないので、固定値で100dpと指定してみます。

1. ドロワーを開くと、とりあえずはうまくいっているように見えます。ただ、SlidingDrawerに含めるコンテンツに合わせて100dpの値を調整することになるのであまり良いやり方ではありません。
2. しかも、ドロワーが閉じていても100dp分の空きスペースができてしまいます。


問題3

stackoverflowのQ&Aに、wrap_contentを有効にする方法がありました。
SlidingDrawerのラッパーを使い、wrap_contentが有効になるようにonMeasure()をオーバーライドする、ということのようです。

1. このラッパーを使うことでwrap_contentが効きました。調度よいサイズでドロワーがレイアウトされているようです。
2. しかし、やはりドロワーが閉じている状態では空きスペースができてしまいます。


問題4

ドロワーが閉じている時は、ウィジェットのサイズを0にするように修正してみます。

1. ドロワーが閉じているときにスクロールビューがきちんと表示されました。
2. ドロワーを開くと、スクロールビューがレイアウト調整されて、隠れた部分がスクロールできるようになっているのがスクロールバーの位置からわかります。
3. 実際に隠れた部分を表示できました。これでやっと完成、と思いましたが…
4. ドロワーを閉じると空きスペースができてしまいます…


Android SDKのソースコードもざっと見てみましたが、どうやらドロワーが閉じたときは再レイアウトされないようです。ドロワーを閉じたとき(onDrawerClosed())にrequestLayout()を呼ぶようにしたところ、最初の完成イメージのようになりました。

別の問題

RelativeLayoutで、スクロールビューがドロワーの位置をandroid:layout_aboveで指定しているために上記のような問題が起こります。これを外すと、スクロールビューのレイアウトはドロワーのレイアウトの影響を受けなくなります。

1. ドロワーが閉じているときに空きスペースができてしまうようなことはありません。
2. その代わり、ドロワーが表示されるとドロワーで隠れた部分を見ることができなくなります。

0 件のコメント: