Androidでソフトウェアキーボードを表示するとViewオブジェクトがせり上がってしまう


Titaniumには素晴らしいサポートサイト( http://support.titanium-mobile.jp/ )があるので、これまでQiitaには何も投稿していませんでしたが、先日のユーザー会でこのままでは地味すぎて世間から忘れられてしまいそうだという懸念が提出されましたので、投稿してみます。

で、表題の件ですが。まあ、ありがちですよね。例えば、WebViewを表示して、戻るボタンなどのコントロール用のViewをフッタ部分に表示するとします。

<Alloy>
  <Window>
    <WebView id="webview" url="http://www.google.com/" />
    <View id="footer">
      <Button>戻る</Button>
      <Button>進む</Button>
      <Button>再読込</Button>
    </View>
  </Window>
</Alloy>

footerオブジェクトを画面最下部に表示したいので、tssはこんな感じでしょうか。Buttonオブジェクトは省略しますね。

"#webview":{
  top: 0,
  left: 0,
  right: 0,
  bottom: 60
},
"#footer":{
  bottom: 0,
  height: 60,
  left: 0,
  right: 0
}

で、この状態で動作させると、一見正常に動いているような感じがします。

でも、WebView内のテキストフィールドをタップすると…

This Is What You Want... This Is What You Get!

footerのオブジェクトがせり上がって、キーボードの上に表示されてしまっています。これは鬱陶しい。

実はこれ、footerオブジェクトがbottom: 0で指定されているのが原因です。なので、同じレイアウトを再現したければ、bottom: 0を消して、端末にあわせてWebViewの高さを調整し、footerのViewを配置すればおしまい。

おしまいですよ。

もう何にもありませんからね。

さあ帰った帰った。

ほんとだってば、あんたもしつこいね。動いたでしょ?

動かない?

あ、そう。

そうですね。WebViewの高さを指定するのって、この場合どうすればいいんでしょう。

TitaniumのAPIで画面の高さを取得するには「Ti.Platform.displayCaps.platformHeight」を利用できます。が、これ、実はAndroidの場合は値をピクセルで返すんですよね。iOSはDIPなので端末の解像度を意識しないでいいのですが、Androidだと上のtssではデフォルトのdpを指定しているため、WebViewの高さを調整しようとすると、footerのViewの高さをピクセルに換算して計算してやる必要があります。

そこで、JS側をこんな風にしてみます。72はヘッダのActionBarのPortrait時の高さなのであまり気にしないでください。

function pixelToDp(px){
  return (px / (Titanium.Platform.displayCaps.dpi / 160));
}

$.index.addEventListener('open', function(e){
  var actionBarHeight = 72;
  var footerHeight = 60;
  var height = pixelToDp(Ti.Platform.displayCaps.platformHeight) - actionBarHeight - footerHeight;
  //$.webview.applyProperties({height: height}); // -> これがあると不具合が*1
  $.footer.applyProperties({top: height});
});

で、tssからfooterのbottom指定を消しましょう。

"#footer":{
  layout: 'absolute',
  top: 0,
  height: 60,
  left: 0,
  right: 0
},
"WebView":{
  top: 0,
  left: 0,
  right: 0,
  bottom: 60
},

結果はこちら:

Qiitaって、「Q」の後ろが「U」になっていない単語にアレルギーがあるので使ってなかったのですが、結構検索とかで活用されている方もおられるようなので、これからもたまに何か書いてみます。

*1 heightを変更するとキーボードが表示されたときの挙動が変わってしまうようです。