画面のフッター部分に入力エリアがある場合、ソフトウェアキーボードが表示されると入力エリアが隠れてしまい、入力することができなくなる場合があります。
そのような場合は、ソフトウェアキーボードが表示される際に、JavaScript からソフトウェアキーボード分、画面の高さを変更する処理を行う必要があります。
#viewport-fit=cover の影響
iPhone X が登場し、iOS 11 からセーフエリアが導入されました。
Monaca で iPhone X の画面に対応する場合は、viewport 設定に viewport-fit=cover
を追加する必要があります。(参考:iPhoneXのセーフ エリア対応について)
viewport 設定に viewport-fit=cover を追加した場合、コンテンツ内容を画面全体に表示するため、JavaScript から画面の高さ ( height ) を変更しても設定が反映されない場合があります。
viewport 設定に viewport-fit=cover を追加した場合は、画面の高さを変更するのではなく、フッター要素の margin-bottom
にソフトウェアキーボード分の高さを設定することで対応することができます。
ソフトウェアキーボードの高さを取得する
フッター要素の margin-bottom
にソフトウェアキーボードの高さを設定するためには、初めにソフトウェアキーボードの高さを取得する必要があります。
JavaScript からは、直接ソフトウェアキーボードの高さを取得することができないため、今回は、cordova-plugin-ionic-keyboard プラグイン ( v2.1.3 ) を利用します。
注意点として、サードパーティー製 Cordova プラグインを利用する場合は、Proプラン
以上が必要になります。また、cordova-plugin-ionic-keyboard プラグインは、カスタムビルドデバッガーでは正常に動作しないため、デバッグビルドをして実機で確認する必要があります。
cordova-plugin-ionic-keyboard プラグインのイベント
cordova-plugin-ionic-keyboard プラグインでは、下記のイベントが用意されています。
イベント名 | 説明 |
---|---|
keyboardWillShow | キーボードが表示される前に実行されます。 |
keyboardWillHide | キーボードが閉じる前に実行されます。 |
keyboardDidShow | キーボードが完全に表示された時に実行されます。 |
keyboardDidHide | キーボードが完全に閉じた時に実行されます。 |
ソフトウェアキーボードの高さは、keyboardWillShow
や keyboardDidShow
イベントから event.keyboardHeight
で取得することができます。
window.addEventListener('keyboardWillShow', (event) => {
console.log(event.keyboardHeight);
});
keyboardWillShow
でフッター要素の margin-bottom
にソフトウェアキーボードの高さを設定し、keyboardWillHide
でフッター要素の margin-bottom
を 0px
に戻すことで対応することができます。
サンプル
Monaca で提供している Onsen UI V2 JS Tabbar
テンプレートをベースにサンプルを作成してみました。
サンプルでのフッター要素は、ons-tabbar
になります。
ons-tabbar
に id
として tabbar1
を設定し、JavaScript から tabbar1 に対し、マージン設定を行なっています。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
<script src="components/loader.js"></script>
<script src="lib/onsenui/js/onsenui.min.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="lib/onsenui/css/onsenui.css">
<link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css">
<link rel="stylesheet" href="css/style.css">
<script>
ons.ready(function() {
console.log("Onsen UI is ready!");
// iPhoneX対応
if (ons.platform.isIPhoneX()) {
document.documentElement.setAttribute('onsflag-iphonex-portrait', '');
document.documentElement.setAttribute('onsflag-iphonex-landscape', '');
}
});
document.addEventListener('show', function(event) {
var page = event.target;
var titleElement = document.querySelector('#toolbar-title');
if (page.matches('#page1')) {
titleElement.innerHTML = 'My app - Page 1';
//ソフトウェアキーボード表示前イベント処理
window.addEventListener('keyboardWillShow', (event) => {
// マージンを追加。
if (ons.platform.isIOS) {
document.getElementById("tabbar1").style.marginBottom = event.keyboardHeight + "px";
}
});
//ソフトウェアキーボード非表示前イベント処理
window.addEventListener('keyboardWillHide', () => {
// マージンを削除。
if (ons.platform.isIOS) {
document.getElementById("tabbar1").style.marginBottom = "0px";
}
});
} else if (page.matches('#page2')) {
titleElement.innerHTML = 'My app - Page 2';
}
});
</script>
<style>
html {
height: 100%;
}
#page1 {
margin: 0;
padding: 0;
min-height: 100%;
height: auto !important;
height: 100%;
position: relative;
}
.page_bottom {
position: absolute;
width: 100%;
bottom: 0;
text-align: center;
overflow: hidden;
}
textarea {
width: 80%;
height: 8em;
}
</style>
</head>
<body>
<ons-page>
<ons-toolbar>
<div class="center" id="toolbar-title"></div>
</ons-toolbar>
<ons-tabbar id="tabbar1" position="bottom">
<ons-tab label="Tab 1" page="tab1.html" active>
</ons-tab>
<ons-tab label="Tab 2" page="tab2.html">
</ons-tab>
</ons-tabbar>
</ons-page>
<ons-template id="tab1.html">
<ons-page id="page1">
<div class="content">
<p style="text-align: center;">
This is the first page.
<br /><br />
<textarea id="textarea1"></textarea>
<br /><br />
<textarea id="textarea2"></textarea>
<br /><br />
<textarea id="textarea3"></textarea>
</p>
<div class="page_bottom">
<textarea id="textarea4"></textarea>
</div>
</div>
</ons-page>
</ons-template>
<ons-template id="tab2.html">
<ons-page id="page2">
<p style="text-align: center;">
This is the second page.
</p>
</ons-page>
</ons-template>
</body>
</html>
おわりに
viewport 設定に viewport-fit=cover
を追加している場合に、画面の高さに対しソフトウェアキーボード分の高さの設定が反映されない場合は、フッター要素に対してマージン設定を試してみてください。