#ご挨拶 今日も無銭知的労働に勤しむ大学生です。ご機嫌よう。

徳島の街は21時には主な飲食店が閉まったりするので悲しいね! でも大学周辺にいい感じの飲食店少ないんだぜ!ひっどい!

#本題:ImageViewで画像やDrawableをレイヤー表示する。 昨日の記事 でのサンプルXML、不思議でしたね。 完成図では4つの画像なのにImageViewが8つあったりね。

実は昨日本当にやりたかったことは、

  • タップした画像が
  • 「今これ選択されてますよー!」というのを
  • ユーザーにわかりやすく示して
  • でも細かいデザインにもこだわりたい・・・!

という欲求を解決したかったのです。ありがちですね。 そんなわけで、先に仕上がり図を見せます。 http://twitpic.com/9qkrug

注目してみていただきたいところとして、

  • 丸とバツの画像
  • フォーカスがあることを示すShape
  • 対象となる画像

の順にかさなっています。この順番が重要で、例えば対象となる画像がShapeより上にくると見苦しいものになるんですね。 えっそんな細かいところ誰も気にしない?はい。

ともかく、この重なりをどうやって実現するか、ですが、 2つの重要ポイントを抑えるだけです。

  • FrameLayoutでImageView2つを重ねる
  • ImageView 1つにつき、2つのDrawableが設定できる

FrameLayoutでViewを重ねる

実はこれはAndroid Developersに掲載 されています。 リンク先のxmlをご覧ください。非常にシンプルです。 FrameLayout内にImageViewを2つ置くだけで、まず画像2つの重ね合わせを実現することができます。 個人的に思ったのが、FrameLayoutは大皿で、その上にピザとか食パンとか積み重ねていくイメージです。

ImageViewには2つのDrawableが設定できる

FrameLayoutで重ねあわせていくなら、あとは必要枚数だけImageViewを置いて、といきたいですが、 そうなるとIDは、ImageViewをおいた数だけ増えるという事です。 これは結構煩雑で、その都度findViewById呼ぶのかよ、という話です。(※)

で、今回は3つのDrawableを重ねるわけですが、ImageViewは、

  • setImageDrawable
  • setBackgroudDrawable

のメソッドを呼び出せます。俺が言う「ImageView1つにつき2つのDrawableが設定できる」の根拠です。 今回、2階層目はShapeなので、これをBackgroundに持ってきて、一番上の丸とバツはImageとしてセットしています。

これで、見かけ上3レイヤーあるようなUIが完成すると思います。

考察

レイヤーを作る、と考えた時、LayerDrawableを使う方法 もあるのですが、 俺の今回の要求はLayerDrawableでは実現できませんでした。

というのも、LayerDrawableをShapeと○×画像に直接使うと、Shapeのサイズが○×画像と同じになり、 その後ImageViewに表示すると、非常に残念なことになってしまいました。 原因は推測ですが、仮想キャンパス(というものが仮にあるとして、)の最大サイズが、予め画像サイズがわかっている○×画像のサイズにセットされたのではないかな、と思っております。

そんなわけで、Shapeのサイズを固定させるためにImageViewに貼り付け・・・、あっ、ImageViewのImageDrawableはまだ未使用なんだね!と気が付きました。

余談

唐揚げ弁当食べたいな。

(※)

最近、こういうコードを書いてオブジェクトの操作をやってますが、これは割と一般的な操作方法なんでしょうか。。。

private FrameLayout[] frameLayouts = new FrameLayout[4];

private int[] QuizSelectId = {
        R.id.clickable_select_one,
        R.id.clickable_select_two,
        R.id.clickable_select_three,
        R.id.clickable_select_four
};

(中略)

for (int i = 0; i < 4; i++) {
        frameLayouts[i] = (FrameLayout) getActivity().findViewById(QuizSelectId[i]);
}

OSO2012では、onClickListenerをセットする程度ならfindViewByIdに直接書くという有難い助言も頂いてたりします。 こんな感じですね。

findViewById(R.id.button_ok).setOnClickListener(new OnClickListener(){ /* コード */ });

でもTextViewで文字操作したりすると、これだけでは限界があったりするというのも知っておくべきこと、というか最近知りました。